Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding CSS border changes positioning in HTML5 webpage

Tags:

html

css

position

I'm having a problem with the page elements moving when I add a border in a HTML 5 document.

I expected the containing header element (grey) to appear at the top of the screen, but it seems to take the margin from the inner div (red). However if I add a border to the header it appears where I expect and the red inner div only moves slightly!

(1st image: without border; 2nd image: with border)

No borderwith border

I have tried setting relative or absolute positioning, using a div instead of the header element, setting margins & padding to 0, using a HTML4 doctype etc. The HTML validates. This is the HTML stripped of everything and still doesn't work. Its happening in latest Chrome & FF.

HELP!! What have I missed?? Or any workarounds (other than keeping the border)?

HTML:

<!DOCTYPE HTML>
<html>
<head>
<title>Test</title>
</head>
<body>
    <header><div id="mydiv"></div></header>
    <div id="content"><p>hello</p></div>
</body>
</html>

CSS:

header {background-color:#CCCCCC; width:960px; height:430px;}
#mydiv {width:960px; height:320px; margin:80px 0px 0px 0px; background-color:#CC0000; }
like image 342
FluffyKitten Avatar asked Jul 26 '12 01:07

FluffyKitten


People also ask

Which of these CSS elements can you use to change the border of webpage?

The border shorthand CSS property sets an element's border. It sets the values of border-width , border-style , and border-color .

What CSS property and value let you position an element anywhere on the screen?

The absolute value positions the element absolutely relative to its container. With absolute positioning, you can place an element anywhere on a page.


1 Answers

The issue comes from something called "margin collapsing". It's simple: 2 adjoining margins collapse to the highest of the two (I say two, but it could be more).

In your case, '#mydivs' margin-top - 80px - is touching the 'header's margin-top - 0px. They're adjoining - there's no element between them, nor padding, nor border.

The margins collapse, therefore, to the highest of the two (80px), and it is then applied on the highest of the elements in the parent-child hierarchy - that's the header in this case.

One solution to this problem is to put something between the margins; either of some padding, or a border on the header works fine.

header {
  border-top: 0.1em solid rgba(0,0,0,0);
}

A second solution (my preferred one), is to make the parent element create a new block formatting context. That way, its margins simply won't collapse with that of its child.

How do you create a block formatting context? There are four possible ways.

  1. by floating it.
  2. "position absoluting it".
  3. adding one of these displays: “table-cell”, “table-caption”, or “inline-block".
  4. adding an overflow other than visible.

To prevent the margins from collapsing you could do any of these 4. I usually go for number 4) - set overflow to auto, as it's only side affect... well it's improbably likely to become a problem.

header {
  overflow: auto;
}

That's basically it for parent-child margin collapsing. There's also margin collapsing between siblings and the rule is pretty much the same: 2 adjoining margins collapse to the highest of the two. It's the solutions that are not.

Here's a great explanation of margin-collapsing - http://www.howtocreate.co.uk/tutorials/css/margincollapsing

like image 73
João Paulo Macedo Avatar answered Nov 11 '22 18:11

João Paulo Macedo