skip to Main Content

I have a parent div with blue background and black border (the width is 650px fixed).

My array data looks like :

  const data = [
    { id: 1, name: "banana", category: "fruit" },
    { id: 11, name: "r", category: "fruit" },
    { id: 12, name: "dsfgh", category: "fruit" },
    { id: 13, name: "jjhjh", category: "fruit" },
    { id: 14, name: "rsrse", category: "fruit" },
    { id: 15, name: "tyfh", category: "fruit" },
    { id: 16, name: "sfss", category: "fruit" },
    { id: 17, name: "azee", category: "fruit" },
    { id: 20, name: "oriented", category: "legs" },
    { id: 21, name: "orio", category: "legs" },
    { id: 22, name: "balance", category: "legs" },
    { id: 23, name: "navigo", category: "legs" },
    { id: 24, name: "href", category: "legs" },
    { id: 25, name: "john", category: "legs" },
    { id: 3, name: "lovanica", category: "muscles" },
    { id: 4, name: "biceps", category: "muscles" },
    { id: 5, name: "interior", category: "legs" },
    { id: 6, name: "avocado", category: "fruit" },
    { id: 7, name: "triceps", category: "muscles" },
    { id: 70, name: "tri", category: "muscles" },
    { id: 71, name: "avant", category: "muscles" },
    { id: 72, name: "delto", category: "muscles" },
    { id: 73, name: "lateral", category: "muscles" },
    { id: 74, name: "latos", category: "muscles" },
    { id: 75, name: "vini", category: "muscles" },
    { id: 8, name: "pomme", category: "fruit" },
    { id: 9, name: "framboi", category: "fruit" },
    { id: 10, name: "varius", category: "legs" }
  ];

Like you see, each item have a category, so I’m trying to display id in my parent div like this :

enter image description here

And it’s done by my code:

import "./styles.css";
import { useRef } from "react";

export default function App() {
  const parentRef = useRef(null);

  const data = [
    { id: 1, name: "banana", category: "fruit" },
    { id: 11, name: "r", category: "fruit" },
    { id: 20, name: "oriented", category: "legs" },
    { id: 21, name: "orio", category: "legs" },
    { id: 22, name: "balance", category: "legs" },
    { id: 23, name: "navigo", category: "legs" },
    { id: 24, name: "href", category: "legs" },
    { id: 25, name: "john", category: "legs" },
    { id: 3, name: "lovanica", category: "muscles" },
    { id: 4, name: "biceps", category: "muscles" },
    { id: 5, name: "interior", category: "legs" },
    { id: 6, name: "avocado", category: "fruit" },
    { id: 7, name: "triceps", category: "muscles" },
    { id: 70, name: "tri", category: "muscles" },
    { id: 71, name: "avant", category: "muscles" },
    { id: 72, name: "delto", category: "muscles" },
    { id: 73, name: "lateral", category: "muscles" },
    { id: 74, name: "latos", category: "muscles" },
    { id: 75, name: "vini", category: "muscles" },
    { id: 8, name: "pomme", category: "fruit" },
    { id: 9, name: "framboi", category: "fruit" },
    { id: 10, name: "varius", category: "legs" }
  ];

  console.log(data);
  const fruit = data.filter((el) => el.category === "fruit");
  const legs = data.filter((el) => el.category === "legs");
  const muscles = data.filter((el) => el.category === "muscles");

  return (
    <div
      ref={parentRef}
      className="parent"
      style={{
        background: "blue",
        height: "100px",
        width: "650px",
        display: "flex",
        border: "2px solid black"
      }}
    >
      <div className="fruit">
        {fruit.map((el) => (
          <div className="child">{el.name}</div>
        ))}
      </div>
      <div className="legs">
        {legs.map((el) => (
          <div className="child">{el.name}</div>
        ))}
      </div>
      <div className="muscles">
        {muscles.map((el) => (
          <div className="child">{el.name}</div>
        ))}
      </div>
    </div>
  );
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

The problem I got is when my data is growing, some div gonna be outside the blue div (parent), so the solution is to select all data that gonna be outside my parent div because I want to create another div with it, so for this example :

enter image description here

As you can see : lateral,latos,vini are outside the parent div, so the output should be :

{ id: 73, name: "lateral", category: "muscles" },
{ id: 74, name: "latos", category: "muscles" },
{ id: 75, name: "vini", category: "muscles" },

I want to create function to do this and avoid DOM manipulations, but I don’t have any idea how to achieve this..

I’ve create a sandbox demo.

2

Answers


  1. If I understood, you would like the overflowing children to stay inside the parent container and be accessible via horizontal scrolling.

    You can achieve this by applying the overflow-x: auto; style to the parent div.

    function App() {
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <div
            className="parent"
            style={{
              background: "blue",
              height: "100px",
              width: "500px",
              display: "flex",
              alignItems: "center",
              overflowX: "auto", // Add this
            }}
          >
            {/* Your children here */}
          </div>
        </div>
      );
    }
    
    ReactDOM.createRoot(document.getElementById('app')).render(<App/>);
    

    This will enable a horizontal scrollbar for the parent container when the child elements’ combined width exceeds the parent’s width. All the children will remain inside the parent container and be accessible by scrolling.
    —————update——————
    gotcha
    try this:

    import "./styles.css";
    import { useRef,useEffect } from "react";
    
    export default function App() {
      const parentRef = useRef(null);
     
    
      useEffect(() => {
        const parent = parentRef.current;
        const parentRect = parent.getBoundingClientRect();
        const children = Array.from(parent.children);
        let outsideChildren = [];
        for (let i = 0; i < children.length; i++) {
          const childRect = children[i].getBoundingClientRect();
          if (childRect.right > parentRect.right) {
            outsideChildren.push(children[i]);
            parent.removeChild(children[i]);
          }
        }
        // Now "outsideChildren" contains the DOM nodes of the children outside the parent. 
        // You can create a new div and append these children to that div.
        const newDiv = document.createElement('div');
        outsideChildren.forEach(child => {
          newDiv.appendChild(child);
        });
        // Append newDiv to the body or wherever you want it in your document
        document.body.appendChild(newDiv);
      }, []);
    
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <div
            ref={parentRef}
            className="parent"
            style={{
              background: "blue",
              height: "100px",
              width: "500px",
              display: "flex",
              alignItems: "center"
            }}
          >
            <div style={{ background: "cyan", marginRight: "12px", width: "23px" }}>
              E1
            </div>
            <div style={{ background: "red", marginRight: "12px", width: "40px" }}>
              E2
            </div>
            <div style={{ background: "cyan", marginRight: "12px", width: "23px" }}>
              E33
            </div>
            <div style={{ background: "red", marginRight: "12px", width: "63px" }}>
              E4444
            </div>
            <div style={{ background: "cyan", marginRight: "12px", width: "23px" }}>
              E555
            </div>
            <div style={{ background: "red", marginRight: "12px", width: "113px" }}>
              E666666
            </div>
            <div style={{ background: "cyan", marginRight: "12px", width: "53px" }}>
              E7
            </div>
            <div style={{ background: "red", marginRight: "12px", width: "33px" }}>
              E8
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E9
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E10
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E11
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E12
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E13
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E14
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E15
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E16
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E17
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E18
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E19
            </div>
            <div
              style={{ background: " cyan", marginRight: "12px", width: "43px" }}
            >
              E20
            </div>
          </div>
        </div>
      );
    }
    

    This will remove all children that are outside of the parent div’s right boundary and append them to a new div.
    ———— recommended way ——-

    import "./styles.css";
    import { useRef,useState,useEffect } from "react";
    
    function Child({ color, width, children }) {
      return (
        <div style={{ background: color, marginRight: '12px', width: `${width}px` }}>
          {children}
        </div>
      );
    }
    export default function App() {
      const parentRef = useRef(null);
      const initialChildren = [
        { color: 'cyan', width: 23, text: 'E1' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
        { color: 'red', width: 40, text: 'E2' },
    
        // ...more children here...
      ];
      const [fitChildren, setFitChildren] = useState(initialChildren);
      const [overflowChildren, setOverflowChildren] = useState([]);
      useEffect(() => {
        const parentWidth = 500; // The fixed width of your parent div
        let accumulatedWidth = 0;
        let fit = [];
        let overflow = [];
        
        initialChildren.forEach((child) => {
          accumulatedWidth += child.width + 12; // child width + margin
          if (accumulatedWidth <= parentWidth) {
            fit.push(child);
          } else {
            overflow.push(child);
          }
        });
    
        setFitChildren(fit);
        setOverflowChildren(overflow);
      }, []);
      return (
        <div className="App">
        <h1>Hello CodeSandbox</h1>
        <div className="parent" style={{ background: 'blue', height: '100px', width: '500px', display: 'flex', alignItems: 'center' }}>
          {fitChildren.map((child, index) => (
            <Child key={index} color={child.color} width={child.width}>
              {child.text}
            </Child>
          ))}
        </div>
        <div className="overflow" style={{ background: 'green', height: '100px', width: '500px', display: 'flex', alignItems: 'center' }}>
          {overflowChildren.map((child, index) => (
            <Child key={index} color={child.color} width={child.width}>
              {child.text}
            </Child>
          ))}
        </div>
      </div>
         
       
      );
    }
    

    This version still only runs the check once after the initial render. If you’re adding children dynamically, you would need to adapt this to respond to those changes.

    Login or Signup to reply.
  2. Not sure if it’s a React issue, I think it’s more a Css issue that need a tricky solution..

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search