Why a wrapper on Firefox, with the display: block; overflow: hidden inside the display: built-in unit?

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> 

In Chrome and IE, this appears as:

Chrome

However, Firefox displays this as:

Firefox

You can try it in this jsFiddle .

Questions

  • Why is this a difference? Is this a Firefox bug? (If so, an error, I will be interested in a link to the error, so I can vote for its correction.)
  • How to get Firefox to do this, like Chrome does, given some of the limitations mentioned in the next section?

Context

Here is just a little context, without which what I am trying to do above might seem crazy. I intend to use the above blocks for tags, for example:

Name label

Elements #a , #b and #c correspond to:

What correspond to these elements

CSS is designed to address the following limitations:

  • For this you need to work with IE8 (no flexbox for me).
  • Block #a is #a , and I don’t want it to expand to the right more than necessary, therefore, inline-block . But obviously, another way will work to do the same.
  • The contents of the #c block should be completed if it is too long, and should not go β€œbelow” the #b block, as shown below. This explains overflow: hidden or display: table .

Long mark

+6
source share
2 answers

Correction

Do not mix, hug the table!

"Fixes" it on Firefox (checked 31.2.0) and IE 8 and 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 a problem occurred

The problem with your source code is that Firefox takes the floating-point element completely out of the stream when calculating the size of the compressible matrix. While float affect the width of the contents of the stream, they themselves are not in the stream and therefore simply take horizontal space from the rest of the content, causing the behavior you saw

Here is a demonstration of what is happening (view in Firefox to see it). Note that outline used on .a and .c , but a thick border (which actually occupies a 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, and not an error and checking the current specification , the basic working model of the box, and the specification for calculating the width , you will see that the floats are marked out-of-flow and the specification of block formatting and inline formatting clearly indicates that the float are part of the inline-context width , but does not for block context (inside inline-block ). Thus, Firefox actually behaves in accordance with a strict interpretation of the specification - this is technically a bug in other browsers.

However, there is still a problem with how Firefox does this.

If we make the float larger than our streaming content (and go back to the borders, since the paths include overflowing children, I moved the remaining brother to the left by 1px so that it aligns with my nephew) (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="cd">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="ae"> <span class="b">b</span> <span class="c">c1 c2</span> </span> <br /> <span class="cd">c1 c2</span> 

The blue box is stretched to contain all of its green child, although, according to a strict interpretation of the specification , it is assumed that it is overflowing. This is a bug with Firefox, since floats should only affect the parent width:auto in the embedded context. In the context of the block, which is supposed to be inside the inline-block , the width of the floats is not included.

Note that just like most other browsers (to some extent, Firefox will increase the size of the parent to the width of the float window, while other browsers will put the incoming stream next to it if the parent can still grow) and if you specify any values ​​or width limits for .a (ala .e in my example), you will get the expected behavior (as shown) of the green fleet overflowing its parent element (should be in all browser cases, since all of these behavioral issues are based on width:auto ).


Loans

A lot of Oriol beer (poster of another answer) - if I did not argue with him about this, I would have no reason to really delve into the specifications and find out what is really happening. He also credited him for pointing out that Firefox still hadn't completed it - that was all he liked.

+6
source

What happens under the hood

  • In accordance with the width of the built-in block, the width #a calculated using the reduction to match algorithm:

    If width auto , the value used is shrink-to-fit width

    compressed algorithm (now called a fit-content measure )

    min ( max-content , max ( min-content , fill-available ))

    This means that if there is enough space, its width will be the maximum preferred width of the content (that is, without breaking lines other than where explicit line breaks occur). Otherwise, it will be as wide as the available space.

  • Then the browser first calculates the preferred width #a .

    Typically, a float overrides the following block locks, as described in Floats :

    Since the float is not in the stream, blocks are created with non-positioned blocks before and after the flow of float boxes vertically, as if the float did not exist.

    Firefox then seems to calculate this preferred width, as if #b and #c could overlap. Thus, the preferred width is the maximum width of the float #b and the width #c .

    However, #c sets up a new formatting unit (BFC) due to overflow: hidden :

    block blocks with "overflow", except for "visible" [...], establish new contexts for formatting blocks for their contents.

    Your #c script has a table instead, but it's the same as the Model Table ,

    In the table shell field, the formatting context of the block is set.

    But as explained in the BFC next to floats , BFC roots cannot overlap floats:

    A table field boundary, a block-level replacement element, or an element in a normal stream that establishes a new formatting for a block context (such as an element with "overflow" other than "visible") should not overlap the field field of any floats in the same block formatting context as the element itself.

    Instead, the float can β€œpush” the BFC to the right. Therefore, in Chrome and Edge, the preferred width #a is the sum of the preferred widths #b and #c .

  • Then width #a will be the preferred width calculated in the previous step if it does not exceed the available width.

    Otherwise, browsers will calculate the preferred minimum width by entering a line break between #b and #c . So this will be the maximum minimum preferred width of #b and #c . The final width #a will be maximum between this preferred minimum width and the available width.

  • Now width #a been allowed, so widths #b and #c can also be allowed.

    Since #b floating, it will also be sized using a shrink algorithm.

    If #c is a block, it will take up the remaining space (if there is no free space, it will be transferred to the next line). If it is a table, the algorithm for the automatic table format is implementation dependent, but is similar to shortening to match. The result is basically the same.

    In the case of Chrome and Edge, if there was enough space, the remaining space occupied by #c is its preferred width, because the preferred width of #a was the sum of #b and #c .

    However, Firefox used the maximum. Therefore, if #b wider than #c , #b completely fill out #a , and #c will be moved to the next line. If #c wider than #b , there will be some remaining space next to #b , so #c will decrease to that extent. This compression causes #c be smaller than its preferred width (even if #a has free space to increase), so the following line break will appear in #c .

Summary

  • By default, a block is enlarged to fill the available width of the block containing it.
  • If the float is smaller than the containing block, the next block will overlap it and still be as wide as the containing block.
  • But if this next block sets the BFC, it will shrink to avoid overlapping the float and fill the remaining space left by the float.
  • By default, a float or inline block tries to be as wide as its contents are required.

Chrome and Edge first discover that the BFC root does not overlap the float, and then the width of the inline-block parent becomes the sum of the float and the BFC root.

Instead, Firefox initially sees the BFC root as a regular block, it thinks it overrides the float and accordingly calculates the width of the parent. Then it detects its BFC root, prevents overlapping and compresses it so that it fits into the remaining space.

So the difference seems to be that they calculate the width of the parent element and prevent the BFC roots from overlapping floats in a different order.

The wrong behavior seems to be Firefox. As defined in the Inside Dimensions of Unreplaced Units , the preferred width should be calculated after layout, and most likely the layout includes pushing the BFC roots next to the floats.

The value of max-content in the field of the container of blocks is a measure of the field after the layout, if all children have a size under the maximum size limit .

Fix

Using a built-in display, such as display: inline-block or display: inline-table on #c , Firefox summarizes the widths of #b and #c when calculating the width of #a . Thus, if there is enough free space, #c will not decrease, and no line breaks will appear.

The problem is that if the contents of the built-in level are too large to fit the remaining space left by the float, the built-in level will be moved to the next line and not shrunk.

 .a { display: inline-block; } .b { float: left; } .c { display: inline-table; } 
 <span class="a"> <span class="b">b</span> <span class="c">c1 c2</span> </span> <hr /> <span class="a"> <span class="b">longer</span> <span class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis diam nec ligula iaculis lacinia non ac neque. Vivamus ut condimentum enim, et sollicitudin magna. In rhoncus nisi at est rhoncus feugiat sed vitae lacus. Maecenas sed felis et libero posuere iaculis a in lacus. Quisque eleifend auctor metus, a congue sapien venenatis a. Duis mollis mauris vitae massa mollis, nec porta nulla semper. Proin fringilla et nibh ac tempor. Aenean et augue ut dui pharetra scelerisque sed sit amet dolor. Nulla posuere a lorem sit amet vehicula. Morbi nec lacinia nibh. Suspendisse lacus nulla, dignissim et mi ut, luctus lobortis nisl. </span> </span> 

Alternatively, if old browser support is not a problem, you can use flexbox. Simple #a { display: inline-flex; } #a { display: inline-flex; } will work mostly, but the following is closer to your current code.

 .a { display: inline-flex; align-items: flex-start; flex-wrap: wrap; /* Allow line breaks if #b is too wide */ } .c { flex: 1; /* Initial width of 0, then take remaining space left by #b */ } 
 <span class="a"> <span class="b">b</span> <span class="c">c1 c2</span> </span> <hr /> <span class="a"> <span class="b">longer</span> <span class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis diam nec ligula iaculis lacinia non ac neque. Vivamus ut condimentum enim, et sollicitudin magna. In rhoncus nisi at est rhoncus feugiat sed vitae lacus. Maecenas sed felis et libero posuere iaculis a in lacus. Quisque eleifend auctor metus, a congue sapien venenatis a. Duis mollis mauris vitae massa mollis, nec porta nulla semper. Proin fringilla et nibh ac tempor. Aenean et augue ut dui pharetra scelerisque sed sit amet dolor. Nulla posuere a lorem sit amet vehicula. Morbi nec lacinia nibh. Suspendisse lacus nulla, dignissim et mi ut, luctus lobortis nisl. </span> </span> 
0
source

All Articles