简体   繁体   中英

React: Making width of div equal to height. The height is not being calculated correctly

Github repo of this project


Based on other solutions that I have seen to this problem, I've created a component that is supposed to calculate the width and height of it's children, and then set the width and the height to be equal to the length of whichever one is longer.

  • Ex. If the width=30 and the height=20, the width and height should be set to 30. The result should be the same if the height is 30 and the width is 20.

 import React, {useState, useEffect, useRef} from 'react'; const SymmetricalDiv = ({style, children, ...props}) => { const [diamStyle, setDiamStyle] = useState({}); const elementRef = useRef(null); style = style ? Object.assign({}, diamStyle, style) : diamStyle ; useEffect(() => { const width = elementRef.current.clientWidth; const height = elementRef.current.clientHeight; const diam = Math.max(width, height); setDiamStyle({width: diam, height: diam}); }, []); return ( <div ref={elementRef} {...props} style={style}> {children} </div> ); };


Here's an example where I try to use this component. (The styling is done using bootstap)

 import React from 'react'; import {SymmetricalDiv} from 'components/Styled' import svgLogo from 'src/SVG_logo.svg' const MyComponent = () => { return ( <SymmetricalDiv className='rounded-circle d-flex flex-column align-items-center bg-danger'> <strong >A title</strong> <span>A description</span> <img className='my-3' src={svgLogo} /> <a href="#">A Link</a> </SymmetricalDiv> ); };

This example is producing the following result. It's calculating the height incorrectly, and deciding that the width is the longer dimension . Then it's setting the width and the height to be equal to the width , which is why some of the children appear outside the circle.

在此处输入图片说明

The reason it doesn't match the height/width appears to be because your image doesn't have a set height/width.

Images without set heights/widths initially start out with 0 width/height, this is where your calculation happens. The image then loads and a reflow happens.

There's two easy ways to fix your issue:

Set the width for the image

This makes sure the image knows its height/width before it's fully loaded.

<SymmetricalDiv className="rounded-circle d-flex flex-column align-items-center bg-danger">
  <strong>A title</strong>
  <span>A description</span>
  <img className="my-3" width="168px" height="150px" src={svgLogo} />
  <a href="#">A Link</a>
</SymmetricalDiv>

Inline the SVG/Make it a component

This removes the load step of the image altogether.

// SVGLogo.js

export default () => {
  return <svg>...</svg>
}
// App.js

<SymmetricalDiv className="rounded-circle d-flex flex-column align-items-center bg-warning">
  <strong>A title</strong>
  <span>A description</span>
  <SVGLogo />
  <a href="#">A Link</a>
</SymmetricalDiv>

You can see both implementations in action in this Code Sandbox example

Being explicit about the sizes of images can be really helpful for ensuring your app behaves as expected.

You can also read more about preventing reflow due to image loading

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM