The Problem
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>
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>
The trailing space at the end of the span block had disappeared. Why?
The Explanation
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 Solution
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 white-space: pre-wrap
.
<div className="flex whitespace-pre-wrap">
<span>For extra assistance, please </span>
<a href="#">contact support</a>
</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.