Container Floating, Margin Collapse, and Block Formatting Contexts

To truly grasp the function of a block formatting context, I am exploring what happens when one is not created.

I found an interesting demo in the article "Everything you Know about Clearfix is Wrong:

.wrapper {
  width: 740px;
  background: #cccccc;
}
.leftSidebar {
  float: left;
  width: 200px;
}
.rightSidebar {
  float: right;
  width: 200px;
}
.mainContent {
  padding-right: 200px;
  padding-left: 200px;
}
.floatMe {
  float: left;
  background: teal;
  color: #fff;
}
<div class="wrapper">
  <div class="leftSidebar">
    <h2>Heading</h2>
    <pre>.leftSidebar {
  float:left;
  width:200px;
}</pre>
  </div>
  <div class="rightSidebar">
    <h2>Heading</h2>
    <pre>.rightSidebar {
  float:right;
  width:200px;
}</pre>
  </div>
  <div class="mainContent">
    <h2>Heading</h2>
    <pre>.mainContent {
  padding-right:200px;
  padding-left:200px;
}</pre>
    <div class="floatMe">
      <pre>.floatMe {
  float:left;
  background:teal;
  color:#fff;
}</pre>
    </div>
  </div>
</div>

The article mentioned (added emphasis):

In modern browsers:

All elements belong to the same block formatting context so adjacent margins collapse. The heading’s margin “sticks out” of the wrapper to butt against the p. Unlike in IE, it is that margin (not the one on the black box) that creates the gap above the wrapper.

What exactly does "the same block formatting context" mean? I'm curious about why such an unusual layout arises without a block formatting context.

To better visualize the layout, I added * {border: 1px solid blue;} to CSS, which caused significant changes: now the layout behaves as if wrapper is a block formatting context!

.wrapper {
  width: 740px;
  background: #cccccc;
}
.leftSidebar {
  float: left;
  width: 200px;
}
.rightSidebar {
  float: right;
  width: 200px;
}
.mainContent {
  padding-right: 200px;
  padding-left: 200px;
}
.floatMe {
  float: left;
  background: teal;
  color: #fff;
}

* {
	border: 1px solid blue;
}

<div class="wrapper">

	<div class="leftSidebar">
		<h2>Heading</h2>
		<pre>.leftSidebar {
			float: left;
			width: 200px;
		}</pre>
	</div>
	
	<div class="rightSidebar">
		<h2>Heading</h2>
		<pre>.rightSidebar {
			float: right;
			width: 200px;
		}</pre>
	</div>
	
	<div class="mainContent">
		<h2>Heading</h2>
		<pre>.mainContent {
			padding-right: 200px;
			padding-left: 200px;
		}</pre>
		
		<div class="floatMe">
			<pre>.floatMe {
				float: left;
				background: teal;
				color: #fff;
			}</pre>
		</div>
		
	</div>

</div>

Please help me understand what's happening here.

Answer №1

Great query, really got my gears turning!

There's a myriad of ideas in motion here, so I'll break them down one by one:

Quirky IE:

You can easily disregard the content of this aged article about IE if you're not focusing on designing for IE7 or IE8 compatibility mode. The odd behavior comes from IE7 utilizing the internal property known as hasLayout.

Check out this MSDN doc for more insights into IE7:

What is "HasLayout" and why is it important?

There are several bugs in Internet Explorer that can be worked around by forcing "a layout" (an IE internal data structure) on an element.

This workaround is clearly non-standard and introduces various inconsistencies. You can also read more about it here.


Block Formatting Context (BFC):

Excerpts from this MDN doc:

A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.

BFCs play a crucial role in positioning and clearing floated elements - floated elements only influence others within the same BFCs. When you utilize float on an element, it is removed from the flow and reinserted through floating.

Refer to the examples below:

  1. The interior of wrapper serves as a BFC where one div is floated left and another to the right.

  2. The floated elements are reintegrated into the BFC while adjusting around the non-floated element.

  3. Without applying clear to the floating in the BFC, the height of wrapper will expand to accommodate the unfloated element.

        body{
          margin: 0;
        }
        *{
          box-sizing: border-box;
        }
        .wrapper{
          border: 1px solid;
        }
        .wrapper > * {
          display: inline-block;
          border: 1px solid red;
          width: 33.33%;
          height: 100px;
        }
        .left{
          float: left;
        }
        .right{
          float: right;
        }
        .center{
          height: 50px;
        }
        <div class="wrapper">
          <div class="left">Left</div>
          <div class="center">Center</div>
          <div class="right">Right</div>
        </div>

  4. Observe what happens when you apply clear to the floating in the BFC - now the heights behave normally within the wrapper BFC.

        body{
          margin: 0;
        }
        *{
          box-sizing: border-box;
        }
        .wrapper{
          border: 1px solid;
        }
        .wrapper > * {
          display: inline-block;
          border: 1px solid red;
          width: 33.33%;
          height: 100px;
        }
        .left{
          float: left;
        }
        .right{
          float: right;
        }
        .center{
          height: 50px;
        }
        .wrapper:after{
          content: '';
          display: block;
          clear: both;
        }
        <div class="wrapper">
          <div class="left">Left</div>
          <div class="center">Center</div>
          <div class="right">Right</div>
        </div>


Collapsing Margins:

Vertical margins of blocks are sometimes combined (collapsed) into a single margin with a size equal to the largest of the original margins, resulting in margin collapsing.

Margin collapsing occurs between adjacent blocks, parent and first/last child, and empty blocks. Find further details on margin collapsing in this MDN doc.

It's important to note:

Margins of floated and absolutely positioned elements do not collapse.



So What's Happening Here Exactly?

  1. You should now grasp the concepts of BFCs and how floating containers operate in the initial scenario (without specified borders) - this explains why floatMe stays outside the immediate mainContent wrapper, and why the heights of wrapper and mainContent appear as they do.

  2. The mentions of Layout and IE pertain solely to IE7 and deviate from standard practices.

  3. The remaining occurrences are due to margin collapsing:

    a. The margins of h2 and pre collapse (adjacent siblings)

    b. mainContent shifts slightly upward to merge with the margin on the body (Parent and first/last child)

    c. Since wrapper adopts the height of mainContent, the height adjustment extends upwards for wrapper.

    d. Introducing borders counteracts the margin collapsing observed in (b) above! (refer to the MDN doc mentioned earlier for details)



Hopefully things are clearer now. Cheers!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Effortlessly Concealing Numerous Elements with a Single Click in Pure JavaScript

I have successfully created an HTML accordion, but I am facing an issue. I want to implement a functionality where clicking on one accordion button will expand its content while hiding all other accordion contents. For example, if I click on accordion one ...

I am trying to utilize a cookie to retrieve the current month, date, and time. Unfortunately, the information is not displaying properly and the date is showing up as

I'm facing an issue with the code snippet below. I keep receiving an undefined error in this specific line of code: `var datemsg = nameOfMonths[date.getMonth()] + " " + date.getDate();`. When I simply use var date = new Date();, the values are succes ...

Make the text within the CSS style of ".well" wrap around the width

I am looking to style the width of a .well class to be in proportion with the text inside a simple textbox that it contains. What is the best approach to achieve this sizing using CSS? ...

angularjs issue with displaying data in ui-grid

Seeking assistance on implementing data display using ui-grid. Currently facing an issue where the grid is not showing any data, although when using a table with <tr ng-repeat="transaction in savingaccountdetails.transactions>, the data is displayed ...

"Exploring the process of integrating a controller into an external HTML file using AngularJS

I'm relatively new to AngularJS. In my web app, I have a set of buttons: index.html <button class="aButton">a</button> <button class="bButton">b</button> <script> $(document).ready(function(){ $(".aButton"). ...

React Material UI Slider component

I'm currently using the react material UI slider and I'm trying to change the default blue color of the pointer to pink. I attempted to modify the thumb and finger within the withStyles object, but unfortunately, it didn't have the desired e ...

Navbar transition issue in Bootstrap

Having trouble with Bootstrap transitions not functioning correctly on my navbar. The issue is when I click the dropdown button in the navbar, the hidden elements appear abruptly without any transition effect. Below is the HTML code being used: <!do ...

Writing CSS rules for generating HTML code when sending emails through the command line in Go

When trying to compose HTML with CSS for email delivery using Go command line execution, errors related to CSS properties are popping up. For instance, it's showing "not found" error in the terminal for properties like background: rgb(255, 255, 255) o ...

Tips for aligning a radio button and label on the same line without breaking the layout in HTML and CSS

I'm encountering a problem with positioning an HTML radio button alongside its label. When the label text is too lengthy, it ends up wrapping below the radio button instead of staying on the same line. Here is the html: <div class="form-check ...

Arranging numerous Text elements within a solitary Drag and Drop container with the z-index property

I am facing a challenge with stacking twelve arguments in no particular order on a drag and drop element. The texts overlap each other, making it difficult for the end user to see them clearly when dragging and dropping. Is there a way to stack texts using ...

The Ul Li tag cannot be aligned to the right

Having trouble left aligning the logo and right aligning the ul li tag? Despite using float, the code doesn't seem to work as expected. Take a look at the issue: It's puzzling because I've used the same code elsewhere and it worked perfectl ...

Connected selection menu

I have noticed several discussions on this topic, but many of them rely on JavaScript or focus solely on a standard drop-down list. I have developed a PHP function that generates drop-down menus based on select queries in my database. Currently, this part ...

Skewed div with a stylish background image

Struggling with an issue here. I've managed to skew my div just right, but now I'm trying to get the image to fit without tiling. If anyone can offer some assistance, that would be greatly appreciated. This is what I'm aiming for: https://i ...

Steps to deactivate an HTML submission button once it has been clicked

I have encountered an issue while working on a signup page using PHP and JavaScript. After the user clicks the "submit" button, the page begins to load before redirecting. If the user clicks "submit" again, an error occurs because the data has already been ...

Altering the submit button's value following the submission of a form

My goal is to create a form with a submit button that, when clicked, will insert the value of the button into a database and change the text on the button to inserted. If the insertion violates any constraints, then the text on the button should be changed ...

Guide to configuring an x-axis scroll bar for a handsontable

Utilizing the JarvisWidget library to create widgets, I encountered an issue with a table exceeding the width of the widget when using the handsontable library. I attempted to add a scrollbar by setting the CSS width to 100% and adding overflow-x:scroll, b ...

Exploring the Differences: innerHTML versus appendChild for Loading Scripts

Struggling to dynamically load scripts onto the DOM? function addScript(fileName) { document.body.innerHTML += `<script src='components/${fileName}/${fileName}.js'></script>` } addScript('message-interface') I prefer th ...

Perform an action in Django when a button is clicked using HTML onclick event

How to integrate HTML form on Django to perform actions using buttons? Check out the HTML code snippet below: <form name="bookappointment" class="form" method="POST> {% csrf_token %} <br> <input type ...

The CSS code hides a portion of the fixed side navigation when the main content is shorter than the navigation bar

My side nav and main content are both dynamic. The issue arises when the navigation is longer than the main content, causing its height to be set to the viewport height and the rest is hidden. How can I address this problem without resorting to an unsightl ...

Steps to create a hover effect similar to that of a website (increasing grid size on hover)

Looking to create a hover effect for my boxes similar to the one on this website: I've examined the code of the website above and searched extensively for a similar feature without any luck. Could anyone offer assistance with this, please? ...