Home > database >  how to get width of an element dynamically in reactjs?
how to get width of an element dynamically in reactjs?

Time:11-08

I have this span element. am fetching data and putting some text in that span element, therefore sometimes that span elements width is 200 px, sometimes its 100px. I want this span to have margin-right: half of its width. I am using this technique:

const [width, setWidth] = useState()

    const ref = useRef(null)
  useLayoutEffect(()=>{
        setWidth(ref.current.offsetWidth);
      },[])



 <span className='big ' id='meria' ref={ref} style={{marginRight:  width / 2    }}>sometext</span>

I want the width element to re-render on change of window.location.pathname, but I cant use that as dependency. any tips?

CodePudding user response:

Don't use a dependency array. The useEffect would be called on each render, but if the offsetWidth didn't change, setting the state won't have any effect:

useLayoutEffect(() => { 
  setWidth(ref.current.offsetWidth);
})

Since the change happens on each render, you can skip the state, and just calculate it directly from the ref as suggested by kind user's comment:

<span className='big ' id='meria' ref={ref} style={{marginRight: ref.current.offsetWidth / 2 }}>sometext</span>

Note: margin doesn't work on inline elements, you should change the display CSS property inline-block or block.

Another option for this specific case is to set the margin using percentage in CSS, since according to MDN:

The size of the margin as a percentage, relative to the inline size (width in a horizontal language, defined by writing-mode) of the containing block.

CodePudding user response:

Do you use a seperate CSS-stylesheet? (even if you don't this still should work, because it's basically just CSS) - If yes you can easily do some CSS trickery to get the same effect without a single line of JS needed You would do that as follows:

Wrap the span (or whatever element you want to have the dynamic margin for) in a div - this div then gets the width: fit-content - you can now set margin-right: 50% on your span element. This is everything you need for your desired result (The 50% always are calculated from the parent ... and with fit-content the parent will be the childs width)

Since you are using spans you'll need to add white-space: nowrap to the span (otherwise the span wouldn't overflow out of the div and just linebreak, which is not what we want)

span {
  margin-left: 50%;
  width: fit-content;
  white-space: nowrap;
  border: solid
}

.container {
  width: fit-content;
}
<div >
  <span>short one</span>
</div>

<div >
  <span>this one is longer</span>
</div>

<div >
  <span>and this one is even longer than the one before</span>
</div>

I used margin-left for demonstartion purpouse (just change it tho whatever you need . the snippet is more to show what I meant, and show the dinamically changing maring based on width of the span)

  • Related