I have a div
(parent) that contains another div
(child). Parent is the first element in body
with no
Use the following code to prepend a contentless first-child to the unintentionally moving div:
.parent:before
{content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
The advantage of this method is that you do not need to change the CSS of any existing element, and therefore has minimal impact on design. Next to this, the element that is added is a pseudo-element, which is not in the DOM-tree.
Support for pseudo-elements is wide-spread: Firefox 3+, Safari 3+, Chrome 3+, Opera 10+, and IE 8+. This will work in any modern browser (be careful with the newer ::before
, which is not supported in IE8).
If the first child of an element has a margin-top
, the parent will adjust its position as a way of collapsing redundant margins. Why? It's just like that.
Given the following problem:
<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
</style>
<div class="parent"><!--This div moves 40px too-->
<div class="child">Hello world!</div>
</div>
You can fix it by adding a child with content, such as a simple space. But we all hate to add spaces for what is a design-only issue. Therefore, use the white-space
property to fake content.
<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
.fix {position: relative;white-space: pre;height: 0px;width: 0px;overflow: hidden;}
</style>
<div class="parent"><!--This div won't move anymore-->
<div class="fix"></div>
<div class="child">Hello world!</div>
</div>
Where position: relative;
ensures correct positioning of the fix. And white-space: pre;
makes you not having to add any content - like a white space - to the fix. And height: 0px;width: 0px;overflow: hidden;
makes sure you'll never see the fix.
You might need to add line-height: 0px;
or max-height: 0px;
to ensure the height is actually zero in ancient IE browsers (I'm unsure). And optionally you could add <!--dummy-->
to it in old IE browsers, if it does not work.
In short, you can do all this with only CSS (which removes the need to add an actual child to the HTML DOM-tree):
<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
.parent:before {content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
</style>
<div class="parent"><!--This div won't move anymore-->
<div class="child">Hello world!</div>
</div>
interestingly my favorite solution to this problem isn't yet mentioned here: using floats.
html:
<div class="parent">
<div class="child"></div>
</div>
css:
.parent{width:100px; height:100px;}
.child{float:left; margin-top:20px; width:50px; height:50px;}
see it here: http://codepen.io/anon/pen/Iphol
note that in case you need dynamic height on the parent, it also has to float, so simply replace height:100px;
by float:left;