Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the wrapping on Firefox, with a display: block; overflow: hidden inside a display: inline-block?

Tags:

html

css

Code

#a {
  display: inline-block;
}
#b {
  float: left;
}
#c {
  display: block;
  overflow: hidden;
}
<span id="a">
    <span id="b">b</span>
    <span id="c">c1 c2</span>
</span>

On Chrome and IE, this gets rendered as:

Chrome

However, Firefox renders this as:

Firefox

You can try it in this jsFiddle.

Questions

  1. Why this difference? Is this a Firefox bug? (If it is, a bug, I'd be interested in the link to the bug, so I can vote for it to be fixed.)
  2. How to get Firefox to render this like Chrome does, given some of the constraints mentioned in the next section?

Context

Here is just a little bit of context, without which what I'm trying to do above might seem crazy. I intend to use the above blocks for a label, like:

First name label

The elements #a, #b, and #c correspond to:

What the elements correspond to

The CSS is designed to deal with the following constraints:

  1. In need this to work with IE8 (no flexbox for me).
  2. Block #a is clickable, and I don't want it to expand to the right more than is necessary, hence the inline-block. But obviously, another way to do the same would work.
  3. The content of block #c must wrap if it become too long, and shouldn't go "below" block #b, as shown below. This explain the overflow: hidden or display: table.

Long label

like image 220
avernet Avatar asked Mar 23 '16 23:03

avernet


1 Answers

The Fix

Don't mix, embrace the table!

"Fixes" it on Firefox (tested 31.2.0) and IE 8, and is honestly more semantically correct.

.a{ display:inline-table; max-width:45%; }
.b{ display:table-cell; padding-right:5px;}
.c{ display:table-cell; }
<span class="a">
  <span class="b">b</span>
  <span class="c">c1 c2</span>
</span>

<br /><hr /><br />

<span class="a">
  <span class="b">longer</span>
  <span class="c">Bacon ipsum dolor amet excepteur laboris irure, corned beef minim pastrami venison in anim incididunt strip steak ea non doner.</span>
</span>

Why There Was An Issue

The problem with your original code is that Firefox takes the floated element completely out of flow when calculating its shrink-to-fit sizing. While floats affect in-flow content width, they themselves are not in-flow, and thus, are merely taking the horizontal space from the rest of the content- causing the behavior you were seeing

Here is a demonstration of what is happening (view in Firefox to actually see it). Note that outlines are used on .a and .c but a thick border (which actually takes up space) is used on .b.

.a { display: inline-block; outline: 1px solid blue; }
.b { float: left; border: 5px solid green; }
.c { display: table; outline: 1px solid red; }
<span class="a">
    <span class="b">b</span>
    <span class="c">c1 c2</span>
</span>
<br />
<span class="c">c1 c2</span>

This is by design, not a bug, and checking the current spec, the basic box model working draft, and the spec regarding calculating widths you'll find that floats are noted as out-of-flow, and the spec regarding block-formatting and inline-formatting explicitly states that floats are part of an inline-context width, but does not for a block-context (the inside of an inline-block). Thus, Firefox is actually behaving according to a strict interpretation of the spec- this is technically a bug in the other browsers.

Yet, there is still an issue with how Firefox does this.

If we make the float larger than our in-flow content (and switch back to borders as outlines include overflowing children; I've shifted the sibling red left by 1px so it will line up with its nephew clone) (again, view in Firefox)

.a { display: inline-block; border: 1px solid blue; }
.b { float: left; border: 5px solid green; width:200px; }
.c { display: table; border: 1px solid red; }
.d { position:relative; left:1px; }
.e { max-width:100px; }
<span class="a">
    <span class="b">b</span>
    <span class="c">c1 c2</span>
</span>
<br />
<span class="c d">c1 c2</span>
<br />
^^^ without <em>.a</em> having a width limit
<hr />
vvv with <em>.a</em> having a width limit
<br />
<span class="a e">
    <span class="b">b</span>
    <span class="c">c1 c2</span>
</span>
<br />
<span class="c d">c1 c2</span>

The blue box is stretched to contain its entire green child, even though, according to the strict interpretation of the spec, it is supposed to overflow instead. THIS is a bug with Firefox, as floats are only supposed to affect parent width:auto in an inline context. In a block context, which the inside of an inline-block is supposed to be, the width of floats is not included.

Note, this is also how most other browsers behave (to a degree- Firefox will size the parent to the float's box width, while other browsers will put the in-flow next to it if the parent can still grow), and that if you provide any width values or limits on .a (ala .e in my example), you get the expected behavior (as shown) of the green float overflowing its parent (should be the case in all browsers, as all of these behavioral issues are based on width:auto).


Credits

Many beers to Oriol (poster of the other answer)- if I didn't start arguing with him on this, I wouldn't've had a reason to actually get into the specs and figure out what was really happening. Also credit to him for pointing out Firefox did still mis-render it- that entire chunk was thanks to him.

like image 171
abluejelly Avatar answered Nov 15 '22 06:11

abluejelly