Today I bumped into a flexbox problem I hadn't seen before. My code looks like this:
<div> <span>For extra assistance, please </span> <a href="#">contact support</a> <div></div> </div>
Notice the space just before the closing
span tag. The idea was that it would look like a normal sentence, but clicking the link would take the user to customer support.
For various reasons, the two texts weren't quite lining up with each other. I thought I could quickly solve the problem with a quick
display: flex. But when I did that, something weird happened.
<div className="flex"> <span>For extra assistance, please </span> <a href="#">contact support</a> <div></div> </div>
The trailing space at the end of the span block had disappeared. Why?
For the answer, let's look at the 'white-space' processing model, which describes how the browser handles white space. The part that interests us is how white space at the end of lines is handled:
As each line is laid out, [...] If a space (U+0020) at the end of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is also removed.
If a space is at the end of a line, it is also removed. Why does this matter?
When we don't use
display: flex, the container
div has the property
display: block. If we don't define the children to be otherwise, the text children are treated as inline elements:
Any text that is directly contained inside a block container element (not inside an inline element) must be treated as an anonymous inline element. - w3.org
However, once we use
display: flex, we blockify the children:
The display value of a flex item is blockified: if the specified display of an in-flow child of an element generating a flex container is an inline-level value, it computes to its block-level equivalent. - w3.org
In other words, they are treated as if they were
display: block. This means the white space is now treated as if it were at the end of a line and is removed.
The 'white-space' processing model also gives us the key to fixing the problem. The rule quoted above only applies when a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line'. We can solve our problem by setting
<div className="flex whitespace-pre-wrap"> <span>For extra assistance, please </span> <a href="#">contact support</a> <div></div> </div>
As MDN explains, by using
pre-wrap, "sequences of white space are preserved". We could also use
white-space: pre, which behaves the same as
pre-wrap but prevents text wrapping.