mamackenzie
mamackenzie

Reputation: 1166

`white-space: nowrap` inside flex container only grows to width of text as if it were wrapped

I am trying to implement a flexbox layout that works as follows:

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:

Showing what happens with and without white-space: nowrap

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

Answers (3)

Neo
Neo

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

CheapSteaks
CheapSteaks

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

Michael Benjamin
Michael Benjamin

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

Related Questions