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.
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:
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>
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.