3

I need to make a panel title with two elements. The first one gets most of the space, while the second gets only the one he needs.

The structure is as follow:

.flex-child> display: flex
    .child-1 > flex-grow: 1
    .child-2 > align-self: center

For stylinng reasons, the first element has a text with white-space: nowrap, to show ellipsis if greater than the parent. But the parent with display: flex is not limiting the element to its available space.

The code snippet bellow shows how the element is when 1) the first element has a lot of text; 2) the first element has a reasonable amount of text; and 3) how I would like the element to appear, but am only being able to do with a magic number as max-width. A fiddle with the same code: https://jsfiddle.net/mjtf4ec3/1/.

.fixed-width-parent {
  margin: 1em 2em;
  width: 300px;
  background: #dedede;
  padding: 15px;
}

.unbreakable-text {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flex-child {
  display: flex;
}

.child-1 {
  flex-grow: 1;
}

.child-2 {
  align-self: center;
  margin-left: 5px;
}

.fancy-button {
  padding: 5px;
  background-color: #1a1;
  border: 1px solid #080;
  border-radius: 5px;
  color: #fff;
}

.expectation .child-1 {
  min-width: 80%;
}

.unimportant {
  color: #bbb;
}

body {
  font-family: sans-serif;
  font-size: 14px;
}
<div class="fixed-width-parent">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>Very long text NOT OK</strong>
        Lorem ipsum dolor sit amet, consectetur
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>

<div class="fixed-width-parent">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>Short text OK</strong>
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>

<div class="fixed-width-parent expectation">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>EXPECTATION (without <code>max-width</code> as %)</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>
danguilherme
  • 642
  • 8
  • 23
  • 5
    [mcve] in your question please. While highlighting `white-space: nowrap` as code bypassed the SO filter when you linked to jsFiddle, we need a complete example here. Thanks. – j08691 Mar 27 '17 at 19:21
  • Your question is confusing... why dont you just change the white-space property to 'wrap' instead of 'nowrap' https://jsfiddle.net/pttgas4p/ – Maxwelll Mar 27 '17 at 19:21
  • How to fit a wider element, in a fixed width less wide parent... answer...you can't – mayersdesign Mar 27 '17 at 19:22
  • @j08691: Updated the question to make it clearer, thanks for pointing out. Wasn't my intention to bypass the SO filter. @Maxwell: I put `white-space: nowrap` for styling purposes. – danguilherme Mar 27 '17 at 20:18

2 Answers2

10

Just set min-width: 0px on .child-1, to indicate to the flexbox layout that it is okay to shrink that child. That is all you need really. Demo below (only added this single line).

.fixed-width-parent {
  margin: 1em 2em;
  width: 300px;
  background: #dedede;
  padding: 15px;
}

.unbreakable-text {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flex-child {
  display: flex;
}

.child-1 {
  flex-grow: 1;
  min-width: 0px; /* added this */
}

.child-2 {
  align-self: center;
  margin-left: 5px;
}

.fancy-button {
  padding: 5px;
  background-color: #1a1;
  border: 1px solid #080;
  border-radius: 5px;
  color: #fff;
}

.expectation .child-1 {
  min-width: 80%;
}

.unimportant {
  color: #bbb;
}

body {
  font-family: sans-serif;
  font-size: 14px;
}
<div class="fixed-width-parent">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>Very long text NOT OK</strong>
        Lorem ipsum dolor sit amet, consectetur
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>

<div class="fixed-width-parent">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>Short text OK</strong>
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>

<div class="fixed-width-parent expectation">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>EXPECTATION (without <code>max-width</code> as %)</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>
Just a student
  • 10,560
  • 2
  • 41
  • 69
  • Both answers worked, but I will stick to this one because it seems more reasonable. Thanks! – danguilherme Mar 27 '17 at 20:42
  • `min-width:0` doesn't always work. Sometimes you need to put `overflow:auto` on the item with `flex-wrap:nowrap`, as well as `overflow:auto` on all immediate ancestors that are also `display:flex`. – trusktr Apr 20 '23 at 06:14
1

Not sure on the cross-browser compatibility, but I've noticed that overflow:hidden (necessary for text-overflow: ellipsis; to work) doesn't behave the same on a flex element as a block element. In light of that, you can add it to an element that doesn't have a declared width and still have it hide the "overflow" under certain conditions. Again, not sure on compatibility, but try adding overflow:hidden to .child-1.

.fixed-width-parent {
  margin: 1em 2em;
  width: 300px;
  background: #dedede;
  padding: 15px;
}

.unbreakable-text {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flex-child {
  display: flex;
}

.child-1 {
  flex-grow: 1;
  overflow: hidden; /* added here */
}

.child-2 {
  align-self: center;
  margin-left: 5px;
}

.fancy-button {
  padding: 5px;
  background-color: #1a1;
  border: 1px solid #080;
  border-radius: 5px;
  color: #fff;
}

.expectation .child-1 {
  min-width: 80%;
}

.unimportant {
  color: #bbb;
}

body {
  font-family: sans-serif;
  font-size: 14px;
}
<div class="fixed-width-parent">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>Very long text NOT OK</strong>
        Lorem ipsum dolor sit amet, consectetur
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>

<div class="fixed-width-parent">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>Short text OK</strong>
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>

<div class="fixed-width-parent expectation">
  <div class="flex-child">
    <div class="child-1">
      <div class="unbreakable-text">
      <strong>EXPECTATION (without <code>max-width</code> as %)</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
      </div>
      <div class="unimportant">Unimportant text
        <br> Very unimportant</div>
    </div>
    <div class="child-2">
      <div class="fancy-button">
        Button
      </div>
    </div>
  </div>
</div>
Joseph Marikle
  • 76,418
  • 17
  • 112
  • 129