In CSS, Why Does the Combination of "Float: Left; Display:Table; Margin: X" on Multiple Elements Make the Margins Decrease

In CSS, why does the combination of float: left; display:table; margin: x on multiple elements make the margins decrease?

This should not happen. Horizontal margins on block-level tables should be calculated in the same way as with any other block-level non-replaced elements, as described in section 10.3.3 of the CSS2.1 spec, regardless of which table layout algorithm is used. In particular, percentages values for margins should be calculated based on the width of the containing block of the element that you're displaying as a table; since all your elements are siblings that share the same parent and the same margin percentage value, they should be equidistant as long as they are floating block boxes.

In all browsers except Google Chrome, the elements are equidistant, as expected. So my best guess is that this is another Chrome bug.

If you comment out the display: table declaration — which as you say causes the behavior to return to normal — browsers will still generate anonymous block table boxes within your floats to contain the table cells. This should not adversely affect the layout, but if it does, I can't comment further as I'm not intimately familiar with how table layout works in terms of CSS.

Why does this CSS margin-top style not work?

You're actually seeing the top margin of the #inner element collapse into the top edge of the #outer element, leaving only the #outer margin intact (albeit not shown in your images). The top edges of both boxes are flush against each other because their margins are equal.

Here are the relevant points from the W3C spec:

8.3.1 Collapsing margins


In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

Adjoining vertical margins collapse [...]

Two margins are adjoining if and only if:

  • both belong to in-flow block-level boxes that participate in the same block formatting context
  • no line boxes, no clearance, no padding and no border separate them
  • both belong to vertically-adjacent box edges, i.e. form one of the following pairs:

    • top margin of a box and top margin of its first in-flow child

You can do any of the following to prevent the margin from collapsing:

  • Float either of your div elements
  • Make either of your div elements inline blocks
  • Set overflow of #outer to auto (or any value other than visible)

The reason the above options prevent the margin from collapsing is because:

  • Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children).
  • Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
  • Margins of inline-block boxes do not collapse (not even with their in-flow children).

The left and right margins behave as you expect because:

Horizontal margins never collapse.

Why top margins are collapsing but bottom margins are not?

Using "clearfix" with display: table will keep the bottom margin, display: block will not.

Src: http://cssmojo.com/the-very-latest-clearfix-reloaded/

Update: Why the top margin collapse is because of no BFC is estabished on its immediate parent


To make the margins not collapse, add a BFC, in this case on the p parent, like in below sample, by adding for example overflow: auto.

More to read: Mastering margin collapsing

Update: Why doesn't a <table>'s margin collapse with an adjacent <p>

.left-column,

.right-column {

background-color: orange;

width: 150px;

}

.left-column {

float: left;

}

.right-column {

float: right;

}

.clearfix-using_display-table,

.clearfix-using_display-block {

background-color: yellow;

width: 125px;

overflow: auto; /* establish BFC */

}

.clearfix-using_display-table p,

.clearfix-using_display-block p {

background-color: silver;

width: 100px;

}

.clearfix-using_display-table:after,

.clearfix-using_display-block:after {

content: " ";

clear: both;

}

.clearfix-using_display-table:after {

display: table;

}

.clearfix-using_display-block:after {

display: block;

}
<div class="wrapper">

<div class="left-column">

<h3>Table</h3>

<div class="clearfix-using_display-table">

<p>Lorem Ipsum...</p>

<p>Lorem Ipsum...</p>

</div>

</div>

<div class="right-column">

<h3>Block</h3>

<div class="clearfix-using_display-block">

<p>Lorem Ipsum...</p>

<p>Lorem Ipsum...</p>

</div>

</div>

</div>

What does this combination of :before, :after and display:table do?

It is part of a micro clearfix hack described in details here: nicolasgallagher.com: A new micro clearfix hack

The clearfix hack is a popular way to contain floats without resorting to using presentational markup.[...]

The complete clearfix is:

/**
* For modern browsers
* 1. The space content is one way to avoid an Opera bug when the
* contenteditable attribute is included anywhere else in the document.
* Otherwise it causes space to appear at the top and bottom of elements
* that are clearfixed.
* 2. The use of `table` rather than `block` is only necessary if using
* `:before` to contain the top-margins of child elements.
*/
.cf:before,
.cf:after {
content: " "; /* 1 */
display: table; /* 2 */
}

.cf:after {
clear: both;
}

/**
* For IE 6/7 only
* Include this rule to trigger hasLayout and contain floats.
*/
.cf {
*zoom: 1;
}

[...]This “micro clearfix” generates pseudo-elements and sets their display to table. This creates an anonymous table-cell and a new block formatting context that means the :before pseudo-element prevents top-margin collapse. The :after pseudo-element is used to clear the floats. As a result, there is no need to hide any generated content and the total amount of code needed is reduced.[...]

Why is float:left required in navigation to keep text center when position:absolute applied to header?

The position: absolute applied to the header makes the div FIXED while all other divs become relatively MOVABLE. So, to make the others also fixed, we give them some other properties like display:inline-block, float:left etc.

Also, need to give a margin-top to the div below the absolute div to offset the collapsing margin

Please see working code with these fixes applied and which has all the divs at https://codepen.io/anon/pen/QqRgRB

The snippet is as follows -

div.header {

position: absolute;

left: 0%;

top: 0%;

width: 100%;

height: auto;

text-align: center;

color: #EE82EE;

background-color: grey;

}

.menu {

text-align: center;

width:100%;

margin:0;

margin-top: 72px;

color:black;

height: 100px;

background-color: red;

float: left;

padding:0px;

display: inline-block;

}

.submenu {

text-align: center;

width:100%;

margin:0;

margin-top: 0px;

color:black;

height: 100px;

background-color: yellow;

display:inline-block;

padding:0px;

}

@media screen and (max-width: 766px){

.menu {

float:none;

}

}

body {

margin:0px;

}
<div class="header">

<h1>HEADER </h1>

</div>

<div class="menu">

<h1>MENU</h1>



</div>

<div class="submenu">

<h1>SUBMENU</h2>

</div>

How do I keep two side-by-side div elements the same height?

Flexbox

With flexbox it's a single declaration:

.row {
display: flex; /* equal height of the children */
}

.col {
flex: 1; /* additionally, equal width */

padding: 1em;
border: solid;
}
<div class="row">
<div class="col">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</div>
<div class="col">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad omnis quae expedita ipsum nobis praesentium velit animi minus amet perspiciatis laboriosam similique debitis iste ratione nemo ea at corporis aliquam.</div>
</div>

HTML 5 strange img always adds 3px margin at bottom

This problem is caused by the image behaving like a character of text (and so leaving a space below it where the hanging part of a "y" or "g" would go), and is solved by using the vertical-align CSS property to indicate that no such space is needed. Almost any value of vertical-align will do; I'm fond of middle, personally.

img {
vertical-align: middle;
}

jsFiddle: http://jsfiddle.net/fRpK6/1/



Related Topics



Leave a reply



Submit