Reputation: 1166
I am trying to implement a flexbox layout that works as follows:
A flexbox container with flex-direction: row
contains two children.
The parent should only be as big as it needs to to accommodate the children (achieved via display: inline-flex
).
The children contain text of different lengths, which does not wrap (i.e. all on one line).
The children should be exactly the same width, which is the width of the widest of the two texts. This is very important, and precludes the usage of flex-basis: auto
, because that will cause the length of the two texts to vary rather than being exactly the same.
In order to make the children the exact same width, determined by the largest of the two, I am using flex: 1 0 0px
.
The layout works exactly as expected, except that the text only seems to grow to the width as if it didn't have white-space: nowrap
! The following screenshot from this codepen that I've created illustrates the problem:
Is there any way to implement this exact behaviour without line wrapping? I know that I can do something like add a fixed width, but I want to know if this is possible to implement dynamically (always growing to exactly the correct width of arbitrary text) using flexbox.
Thanks
.parent {
display: inline-flex;
margin-bottom: 60px;
}
.child {
flex: 1 0 0px;
padding: 20px;
}
.nowrap {
white-space: nowrap;
overflow: hidden;
}
.left {
background-color: #89e7dc;
}
.right {
background-color: #e7cc89;
}
<p>In the first example, when the text is allowed to wrap, we see that the two sides grow correctly to the same width as the larger text</p>
<div class="parent">
<div class="child left">This is some short text</div>
<div class="child right">This is some long text that is intended to cause the previous child to grow to the width of this one</div>
</div>
<p>In the second example, where the text is forced onto a single line by
<pre>white-space: nowrap; overflow: hidden;</pre> we see that the boundaries grow to the size that the wrapped text would occupy, even though it's all on one line.</p>
<div class="parent">
<div class="child left nowrap">This is some short text</div>
<div class="child right nowrap">This is some long text that is intended to cause the previous child to grow to the width of this one</div>
</div>
<p>
How can we get the same behaviour as the first example (both sides growing to exactly the size of the larger content) while keeping the text on the same line?
</p>
Upvotes: 5
Views: 3183
Reputation: 157
I tried within the codepen you provided and ended up preppending the following, not sure if it's what you meant/wanted:
HTML
<div class="grid">
<div class="child left">This is some short text</div>
<div class="child right">This is some long text that is intended to cause the previous child to grow to the width of this one</div>
</div>
CSS
.grid {
/* choose one of these below depending whether you want it (the parent) take the full width */
display: inline-grid;
display: grid;
grid-template-columns: 1fr 1fr;
/* choose one of these below depending whether you want it overflowing horizontally */
width: fit-content;
width: max-content;
}
The full demo:
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
width: max-content;
}
.parent {
display: inline-flex;
margin-bottom: 60px;
width: max-content;
}
.child {
flex: 1 0 0px;
padding: 20px;
}
.nowrap {
white-space: nowrap;
overflow: hidden;
}
.left {
background-color: #89e7dc;
}
.right {
background-color: #e7cc89;
}
<h2>Answer</h2>
<div class="grid">
<div class="child left">This is some short text</div>
<div class="child right">This is some long text that is intended to cause the previous child to grow to the width of this one</div>
</div>
<h2>Question</h2>
<p>In the first example, when the text is allowed to wrap, we see that the two sides grow correctly to the same width as the larger text</p>
<div class="parent">
<div class="child left">This is some short text</div>
<div class="child right">This is some long text that is intended to cause the previous child to grow to the width of this one</div>
</div>
<p>In the second example, where the text is forced onto a single line by
<pre>white-space: nowrap; overflow: hidden;</pre> we see that the boundaries grow to the size that the wrapped text would occupy, even though it's all on one line.</p>
<div class="parent">
<div class="child left nowrap">This is some short text</div>
<div class="child right nowrap">This is some long text that is intended to cause the previous child to grow to the width of this one</div>
</div>
<p>
How can we get the same behaviour as the first example (both sides growing to exactly the size of the larger content) while keeping the text on the same line?
</p>
It's always tricky for a child to control the parent or its siblings with CSS, and I think we got either hacky or lucky with this one... (if it at all is what you meant)
Upvotes: 6
Reputation: 5011
Does this work? https://codepen.io/cheapsteak/pen/qBrPVda
<div class="parent">
<div class="left child" style="">This is some short text</div><div class="right child" style="">This is some long text that is intended to cause the previous child to grow to the width of this one</div>
</div>
<style>
.parent {
margin-bottom: 60px;
}
.child {
padding: 20px;
box-sizing: border-box;
display: inline-block;
width: 50%;
min-width: max-content;
}
.nowrap {
white-space: nowrap;
overflow: hidden;
}
.left {
background-color: #89e7dc;
}
.right {
background-color: #e7cc89;
}
</style>
Upvotes: 0
Reputation: 371331
Won't work with flex-grow
because this function distributes free space on the line.
This means that the longer text item will first consume the free space in the shorter item before the container can expand. This kills the equal width layout you're seeking.
Put another way, flex-grow: 1
, applied to both items, will distribute free space evenly between them. However, the longer the content, the less the free space, and flex-grow
can't work as you expect. It can only create equal width items with flex-basis: 0
and enough free space.
Same problem with grid: the use of free space.
I don't think this layout can be achieved with flex-grow
or fr
. You would need another CSS method or JS.
Upvotes: 1