We are working on a component library with React, and recently we had an interesting issue related to the most basic component that you could imagine: a horizontal line that works as a divider.
It all happened when a user contacted us about a problem with the Divider component. A simplified version of it would look like this:
const Divider = props => {
const { dataTest, type } = props;
const className = type === 'thick' ? 'thick' : undefined;
return (
<hr
className={className}
data-test={dataTest}
/>
);
}
Which generates the following code once rendered (without props):
<hr />
As you can see, it is a single <hr />
tag that displays as a horizontal line. It is plain old HTML... so what could go wrong with it?
According to the user, the line was not displayed even when they had verified that it was there and that they had imported everything correctly.
And the code was fairly simple overall:
<div class="container">
<p>Some text here</p>
<hr />
<p>More text here</p>
</div>
We were puzzled. After verifying the version of the library, making sure the imports were correct and that the component was used in the right way, and double-checking that no additional CSS was been applied to the HR. Everything seemed fine... but when the user showed us their page the horizontal line was not there.
It took us a few minutes too many before we realized what was happening. Here is some space in case you want to think about it before jumping to the mystery solution.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
The issue was that the user was wrapping all the content in a <div>
with the following styles (among others):
.container {
display: flex;
flex-direction: column;
}
When using FlexBox, the elements inside the flex container behave differently than how they are originally defined. Some properties like float
, clear
, or display
do not apply in the same way.
Browsers display <hr>
as an empty block element with automatic horizontal margins (that will center it if a width
is specified). But when the <hr>
becomes a flex item, the automatic width is pushed to 0. Disappearing from the view.
Here is a demo of the issue on CodePen:
There are two possible solutions for this issue:
- Specify a width for the
<hr>
tag - Do not use FlexBox in this case
FlexBox is a powerful tool –and an amazing one, probably the best to come to CSS in a long time–, but as with any other tool, it is important to understand it and only use it when it is needed. This particular example showcases a time in which it is not needed and causes unexpected side effects.
Top comments (6)
Ha, nice, as soon as I saw the disappearing line I thought about flex -- something similar happened to us on a pop-up component, I don't remember the exact details but flex was causing it to appear with a weird width or on a wrong location.
CSS bugs are why I frequently remind our team members that tests are helpful, but they can also provide a false sense of security and that in the long run we win more by writing good code and spending the necessary time to clean up code that starts to smell. (Testing is still a must, but some devs rely too much on them)
It was a fun tidbit. I didn't know flex could create such interesting mysteries
Just do
width: 100%;
on the<hr/>
to restore normal behaviourthis is time saving issue that we needed to know in the era of flex layout to rule them all. Thank you
Thanks! Very helpful
Very useful article. Thank you!