In Firefox, negative margins do not have the effect of pulling up floated siblings

I am facing an issue with a box that contains a heading and two sibling boxes. The heading has negative margin-top to render outside the box. Surprisingly, in all browsers except Firefox, the heading successfully pulls up its sibling boxes, but in Firefox, the boxes remain in their original position.

Upon removing the float property from the boxes, they do move up as expected. Is there a solution for this problem aside from giving the boxes a negative margin-top?

div {
  background: red;
  padding: 2rem;
  margin-top: 8rem;
  box-sizing: border-box;
}

div:after {
  display: table;
  content: "";
  clear: both;
}

div div {
  background: green;
  margin: 0 0 2rem;
  width: 45%;
  float: left; /* Remove this and use float: right below to make it work on FF */
}

div div + div {
  float: right;
}

h2 {
  margin-top: -8rem;
}
<div>
<h2>
Hello
</h2>
<div>
These sibling boxes also appear outside the red box.
</div>
<div>
Except in Firefox.
</div>
</div>

Answer №1

To prevent floated boxes from overlapping, consider placing them within a separate container that is not floated. (note: Each div has been assigned its own class for clarity on which styles are being applied to each div.)

.d1 {background:red; padding:2rem; margin-top:8rem; box-sizing:border-box;}
.d1:after {display:table; content:""; clear:both;}
.d3 {float:left; background:green; padding:2rem; box-sizing:border-box; width:45%;}
.d3 + .d3 {float:right;}
h2 {margin-top:-8rem;}
<div class="d1">
    <h2>Hello</h2>
    <div class="d2">
        <div class="d3">These boxes render outside the red one.</div>
        <div class="d3">In every browser.</div>
    </div>
</div>

Answer №2

Initially, I condensed the code into a more minimal example as shown below:

* {
  box-sizing: border-box;
}
body {
  margin: 0;
}
.wrapper {
  background: red;
  padding: 2rem;
  margin-top: 8rem;
}
.wrapper > div {
  background: green;
  padding: 2rem;
  float:left;
}
.wrapper:after{
  content: '';
  clear:both;
  display: table;
}
h2 {
  margin-top: -8rem;
}
<div class="wrapper">
  <h2>Hello</h2>
  <div>These boxes also render outside the red one.</div>
</div>

What is causing this?

  1. The first step was to remove the padding from wrapper to observe how margin collapsing affects the layout, which revealed that the behavior remained consistent across browsers (Firefox included). This indicates that margin collapsing is not the cause in this scenario.

        * {
          box-sizing: border-box;
        }
        body {
          margin: 0;
        }
        .wrapper {
          background: red;
          margin-top: 8rem;
        }
        .wrapper > div {
          background: green;
          padding: 2rem;
          float:left;
        }
        .wrapper:after{
          content: '';
          clear:both;
          display: table;
        }
        h2 {
          margin-top: -8rem;
        }
        <div class="wrapper">
          <h2>Hello</h2>
          <div>These boxes also render outside the red one.</div>
        </div>

  2. Subsequently, toggling the float: left property for the inner div within wrapper exposed issues with negative margins specifically in Firefox.

        * {
          box-sizing: border-box;
        }
        body {
          margin: 0;
        }
        .wrapper {
          background: red;
          padding: 2rem;
          margin-top: 8rem;
        }
        .wrapper > div {
          background: green;
          padding: 2rem;
        }
        .wrapper:after{
          content: '';
          clear:both;
          display: table;
        }
        h2 {
          margin-top: -8rem;
        }
        <div class="wrapper">
          <h2>Hello</h2>
          <div>These boxes also render outside the red one.</div>
        </div>

Is this a bug?

According to the documentation:

Negative values for margin properties are allowed, but there may be implementation-specific limits.(Source: W3C)

Furthermore, it appears that Firefox has an unresolved historic issue related to this - check out this Bugzilla link.

Solution

Avoid using floated siblings within containers with negative margins:

* {
  box-sizing: border-box;
}
body {
  margin: 0;
}
.wrapper {
  background: red;
  padding: 2rem;
  margin-top: 8rem;
}
.wrapper > .float-wrap > div {
  background: green;
  padding: 2rem;
  float:left;
}
.wrapper > .float-wrap:after{
  content: '';
  clear:both;
  display: table;
}
h2 {
  margin-top: -8rem;
}
<div class="wrapper">
  <h2>Hello</h2>
  <div class="float-wrap">
    <div>These boxes also render outside the red one.</div>
  </div>
</div>

In summary, encapsulate the floated container within your code with the following modifications:

div {
  background: red;
  padding: 2rem;
  margin-top: 8rem;
  box-sizing: border-box;
}
div:after {
  display: table;
  content: "";
  clear: both;
}
div > div > div {
  background: green;
  margin: 0 0 2rem;
  width: 45%;
  float: left;
}
div > div > div + div {
  float: right;
}
h2 {
  margin-top: -8rem;
}
div > h2 + div {
  padding: 0;
  margin: 0;
  background: none;
}
<div>
  <h2>Hello</h2>
  <div>
    <div>
      These boxes also render outside the red one.
    </div>
    <div>
      In every browser except Firefox.
    </div>
  </div>
</div>

Answer №3

It could be argued that a potential bug exists in all browsers except for Firefox.

According to the Working Draft Collapsing Margin Spec:

  • Margins of a floated box do not collapse with any other margins.
  • If a box is collapsed through and it has clearance applied to one of the collapsed margins, then those margins do not collapse with certain of the parent's margins: If clearance is applied to, respectively, the top, right or left margin, then those margins do not collapse with the parent's bottom, left or right margin, respectively.

It seems that most browsers, with the exception of Firefox, are incorrectly allowing the floated div margins to collapse. However, setting a clear property to the div div css will keep the floats within their container (Refer to the snippet below). This aligns more closely with the specifications provided.

The Recommendation for positioning of floats also suggests that what is observed in other browsers may not be the intended outcome. The Spec recommendation implies that floated items should generally remain within their parent container unless explicitly stated otherwise.

A floating box's outer top may not be higher than the top of its containing block.


Check out the demonstration below which shows that adding clearing to the floats will contain them within their parent

div {
  background: red;
  padding: 2rem;
  margin-top: 8rem;
  box-sizing: border-box;
}

div:after {
  display: table;
  content: "";
  clear: both;
}

div div {
  background: green;
  margin: 0 0 2rem;
  width: 45%;
  float: left;
  clear:right; // By including this, the floats remain inside their container
}

div div + div {
  float: right;
}

h2 {
  margin-top: -8rem;
}
<div>
<h2>
Hello
</h2>
<div>
These boxes also render outside the red one.
</div>
<div>
In every browser except Firefox.
</div>
</div>

Answer №4

The way block structure is calculated in a browser can determine the outcome. I managed to fix it by substituting margin-top with top and adjusting the position property.

div {
  background: red;
  padding: 2rem;
  margin-top: 8rem;
  box-sizing: border-box;
}

div:after {
  display: table;
  content: "";
  clear: both;
}

div div {
  position: relative;
  top: -12rem;
  background: green;
  width: 45%;
  float: left;
  /* Removing this line and using float: right below makes it work in FF */
}

div div + div {
  float: right;
}

h2 {
  margin-top: -8rem;
  position: absolute;
}

Check out the working fiddle here: https://jsfiddle.net/nobalmohan/6sjhy1q3/

I'm confident there are alternative solutions to tackle this issue as well.

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

What is the best way to use a HTML link to toggle the visibility of a <p> element using

I've been trying to figure out how to make a link show and hide a paragraph below it for some time now. I want to do this using just CSS. The paragraph should be hidden by default, then display when the link is clicked, and hide again with another cl ...

Struggling to Collaborate with External PHP File Leads to Garbled Results

Recently started learning PHP and I'm pretty sure I have it set up correctly with my local IIS as I was able to use it in a form on another local website. For this particular project, I have a basic HTML file structured like this: <!doctype html&g ...

ColorBox refuses to adjust width dynamically

Utilizing the Jquery plugin called colorbox in my HTML application has presented me with a challenge. I have two divs on my page – one positioned at the left and the other at the right. What I desire is for the right div to initially have its display set ...

What could be causing the issue with loading data into my MongoDB collection?

Here is the content from my mongo database: https://i.sstatic.net/Z5PVv.png When I use app.post to insert the data, after submitting I can see the object with the dates in the console.log. However, when I try to use create function, it only displays "nul ...

Jade: modify the text box input to show = " ..."

I am new to Jade and Html, and I am currently working on creating a form in Jade. The issue I am facing involves a simple text box that looks like this: input(type='text', name='sessionID', value = 'valueID') Whenever I want ...

Utilizing jQuery to display labels only for selected checkboxes while concealing the ones that are not checked

I currently have the following setup: <style>.selectit{display:none;}</style> <div id="foo"> <label class="selectit"> <input type="checkbox" name="one" id="one" checked> One </label> <label class="selectit"> <i ...

Enhancing HTML "range" element with mouse scroll functionality for incrementing values in step increments

I'm working on developing a scroll feature that operates independently from the main window's scrolling function. I aim to trigger specific events in the primary window based on interactions with this separate scrollbar. The only solution I coul ...

Is there a way to use prettier to format HTML codes without breaking up the tags?

As someone new to web development, I have recently encountered some challenges with coding, one of them being Prettier. This tool formats codes into parts, making it difficult for me to understand the code properly. After formatting, the code gets separat ...

Adjust the width of a jQuery Mobile control group

Having trouble resizing a control group using jQuery Mobile 1.3.0 Seeking the correct approach, currently attempting to resize the .ui-btn class with the following code: #test_1 .ui-btn { width: 200%; } The buttons are not resizing as expected; when ...

AngularJS: resolving route dependencies

I have a variable $scope.question that contains all the questions for the page. My goal is to loop through the questions page by page. To achieve this, I created a function called questionsCtrl and I am calling this function in the config while setting up ...

Incorporating OTP verification into the registration process

I'm struggling with incorporating the "send OTP" feature into my registration form. I received an API from an SMS provider, but I'm unsure how to integrate it into my form. After verifying the OTP, I need the user's data to be stored in my d ...

Ways to position an image in the middle of a Div

I am currently working with PHP and Smarty, attempting to display a slideshow's images in the center of a specific div, but I am encountering difficulties achieving this. Below you will find the code snippet. Can anyone help me figure out what I migh ...

`When utilizing $routeParams, the CSS fails to load`

Whenever I use parameters in ngRoute and go directly to the URL (without clicking a link on the site), the CSS fails to load. All my routes are functioning properly except for /chef/:id. I utilized yeoman's angular generator, and I am running everythi ...

Looking to utilize AngularJS validation in place of the default browser validation?

I am working on a form that contains two ng-forms for input validation. I have encountered two issues with my forms. 1) I am trying to implement a minlength validation for the Company input, but my current approach doesn't seem to be working. How can ...

Illustration tucked beneath the menu

I am looking to create a landing page for my project similar to the design on this website. I am using Bootstrap 4 and HTML, but struggling to hide the background image behind the navigation bar. Can anyone help with this issue? ...

Tips on concealing the visibility of a table row using PHP

My HTML table structure is quite simple: <style> .demo { width:100%; border:1px solid #C0C0C0; border-collapse:collapse; padding:5px; } .demo th { border:1px sol ...

When table cells are added dynamically, they are not encompassed by the solid fixed title bar when scrolling

My webpage has a fixed title bar with a high z-index that overlaps all other elements on the page when they are scrolled up, except for the dynamically created table cells. What attributes or styles do I need to set in order to hide the table cells behin ...

Jquery scroll animation not reaching the intended position when scrolling upwards

While developing a new feature for my music player, I encountered an issue with centering the track/div upon clicking in the scrollable parent div. Sometimes it doesn't scroll to the center as intended and instead scrolls erratically to the top of the ...

What is the best way to select an ID element using JQuery?

Everything is going smoothly, could you please assist me with a question. Here is the HTML form code I am working with: <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <scri ...

Is it possible to save the current state of an execution in JavaScript and pick up where you left off

Is there a way to accomplish this task? I am interested in developing a JavaScript application that has the ability to "pause" and then "resume" execution from a specific point, similar to a checkpoint system. For example: //code.js var abc = 13; checkpoi ...