7
votes

I'm trying to position a few elements in a row, so that they all fit in the width of the container. To prevent them from word-wrapping I added "white-space: nowrap" to the parent, and added "white-space: normal" to the children to allow them to wrap the text (as desired).

The problem is that with this configuration the right most child sometimes exceeds the width of the parent.

expected vs actual

HTML:

<div id="container">
    <div class="child">
        child 1
    </div>
    <div class="child">
        child 2 text that might be long enough to wrap, but still exceed the parent
    </div>
</div>

CSS:

#container {
    white-space: nowrap;
    width: 200px;
    background: yellow;
    border: 1px solid brown;
    padding: 5px;
}

.child {
    display: inline-block;
    border: 2px solid red;
    vertical-align: top;
    white-space: normal;
}

http://jsfiddle.net/7e5TU/1/ (change the length of the text if the problem doesn't appear straight away).

I know that I can solve it with a table, and probably with a float on the left child, and "overflow: hidden" on the right, but I see no reason why this should not work.

Could anyone provide some insights? I'd mostly love to understand what in the box model causes this behavior. Thanks!

3
That's the expected behavior. By using white-space: nowrap; for the parent, you've collapsed the whitespaces between inline(-block) elements. white-space treats the children, not the element itself. - Hashem Qolami
Thanks Hashem. I understand that, and giving it some thought I understand that what I'm trying to achieve might not be reasonable. I think what threw me off was that the right child DOES wrap the text, but (as I realized now) is expanded up until the width of the parent. - Sasha
@HashemQolami "... white-space treats the children, not the element itself. ". This is not correct - see w3.org/TR/CSS2/text.html#white-space-prop "This property declares how white space inside the element is handled."! - Netsurfer
@Netsurfer Exactly, white space inside the element means between inline nodes whether the text itself or inline(-block) elements. - Hashem Qolami
@Sasha Yes, when it comes to white-space your HTML markup plays an important role, because any line breaks, white spaces, tabs or new lines will effect the rendering. Google will give you lots of resources about this. And yes, expanding up to the parents width (minus a given padding of the parent) is the normal behaviour for inline-block elements. - Netsurfer

3 Answers

1
votes

I agree with @hashem That's the expected behavior. By using white-space: nowrap; for the parent, you've collapsed the whitespaces between inline(-block) elements. white-space treats the children, not the element itself.

Well if you still need a fix you can add width to second child to make it fit inside container.

fiddle

e.g.

.child2
{
    width: 70%;
}
1
votes

If you are willing to use flexbox (https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes) you could do it like this: http://jsfiddle.net/7e5TU/6/

HTML

<div id="container">
    <div class="child1">
        child 1
    </div><div class="child2">
        child 2 text that might be long enough to wrap, 
        but still exceed the parent
    </div>
</div>

CSS

#container {
    width: 200px;
    background: yellow;
    border: 1px solid brown;
    padding: 5px;
    display: flex;
    flex-direction: row
}

.child1, .child2 {
    display: block;
    border: 1px solid red;
    vertical-align: top;
}

.child1 {
    min-width: 50px;   
}
0
votes

You can do this with CSS display:table. This way no sizing details are needed. It ensures the elements stay in a row and the text will wrap perfectly to the width of the parent container.

HTML

<div class='container'>
  <div class='field'>
    <div class='data'>
      child 1
    </div>
  </div>
  <div class='field'>
    <div class='data'>
      child 2 text that might be long enough to wrap, but still exceed the parent
    </div>
  </div>
</div>

CSS

.container {
  display: inline-table;
  border-spacing: 4px;
  background: yellow; border: 1px solid brown;
  padding: 5px;
}
.field {
  display: table-cell;
}
.data {
  border: 2px solid red;
  padding: 3px;
}