Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference of layout on Safari with margin-right negative

Tags:

html

css

safari

I stumbled upon a difference in layout rendering between Safari and Chrome/Firefox and I don't know which one is "right".

You can check the jsfiddle here

On Firefox/Chrome the layout is as expected, the yellow div is right after the red ones. But on Safari, the yellow div is positioned under the red ones.

After investigating what I did wrong I found out the bug comes from the CSS class E whose property margin-right (value: -11px) is bigger than the width property (value: 10px) for my div.

I think I understand why Safari renders it this way. The width of div of class B is computed as being the sum of the widths of its children as they have the property float: left;.

Here it is widthB = widthB2*2 + widthE + marginRightE + widthC or marginRightE < -widthE so widthB is not large enough to contain each div next to each other.

So my questions are:

  1. Am I right in my understanding of what Safari does?
  2. Why do Chrome and Firefox render differently? Are they just not decreasing the width of the parent div based on a negative margin-right?
  3. Would the proper correction to always have a margin-right lesser or equal to the width of a div in this case?

Thank you!

HTML:

<div class="A">
  <div class="C">
    <div class="B">
      <div class="B2"></div>
      <div class="B2"></div>
      <div class="E"></div>
      <div class="C">
        <div class="D"></div>
      </div>
    </div>
  </div>
</div>

CSS:

.A {
  background-color: blue;
  height: 200px;
}

.B {
  height:100px;
}
.B2 {
  background-color: red;
  height: 100px;
  width: 100px;
  float: left;
}
.C {
  float: left;
}
.D {
  height: 40px;
  width: 40px;
  float:left;
  background-color: yellow;
}
.E {
  height: 50px;
  width: 10px;
  position: relative;
  left: -10px;
  margin-right: -11px;
  background-color: black;
  float: left;
}
like image 644
koopajah Avatar asked Jan 16 '13 08:01

koopajah


People also ask

What does negative margin do?

It is possible to give margins a negative value. This allows you to draw the element closer to its top or left neighbour, or draw its right and bottom neighbour closer to it.

Is it good to use negative margin?

The downside of negative margins is they are difficult to debug and will make your CSS harder to read. The most often misuses of negative margins that I encounter is when it is used to make up for incorrect layouts elsewhere on the site. This is indeed bad practice.

Why might you use negative margins in your web page?

A negative margin on an element allows it to eat up the space of its parent container. Adding a (positive) margin on the bottom doesn't allow the element to do that - it only pushes back whatever element is below.

What does margin-right do?

The margin-right CSS property sets the margin area on the right side of an element. A positive value places it farther from its neighbors, while a negative value places it closer.


1 Answers

I'm not sure what you expect to happen with the CSS in the JS fiddle. You are delving into undefined behaviour. I say this because:

  • 'C' is floated but does not have a defined width. This leads to issues in various browsers depending on the complexity of the layout.

  • None of the floated elements are ever cleared. When floating it is imperative that a clearfix of some description is used, whether it is clear:both, etc.

If you tweak the mark-up and add a clear-fix, you see that the content is always 239px. See http://jsfiddle.net/eaFn9/

However, it seems like the relatively positioned item 'E' and margin is having a negative impact on the width calculation, as Chrome's web inspector seems to always report oddly for the negative margin on this element.

If you play around with this in web inspector you can see it's almost as if the negative margin is the cause of the drop. I think it may be due to a container that does not have a width, and isn't position relative in itself.

How to fix?

Personally, I would want to re-write your layout to include fixed widths on all floats, reduce nesting of floats and clear where possible. It seems overly complex but without a real world use case it's hard to rewrite.

However, It seemed to me that you can wrap 'B2' + 'E' elements in a wrapper that is floated and relatively positioned, then use absolute positioning on 'E' to give the same affect and remove the negative margin.

This is the JSFiddle I came up with: http://jsfiddle.net/jV3Ub/

like image 131
Hux Avatar answered Sep 25 '22 15:09

Hux