Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS negative margin overlap not working on child elements

I'm struggling with some basic CSS layout flow. If I have two divs one after another, where the second div has a negative top margin, I'd expect it to overlap the preceding div.

However, I'm finding that while the first div is indeed overlapped, its contents are not.

<div style="background:green;height:20px;">
  <span style="background:red;display:inline-block;padding:2px;">HELLO</span>
  <span style="background:red;display:inline-block;padding:2px;">HELLO</span>
  <span style="background:red;display:inline-block;padding:2px;">HELLO</span>
</div>
<div style="background:yellow;height:20px;margin-top:-10px;">
</div> 

enter image description here

https://jsfiddle.net/xwghd5r2/


This seems to run counter to the principles of the basic stacking order:

From https://css-tricks.com/almanac/properties/z/z-index/:

Without any z-index value, elements stack in the order that they appear in the DOM (the lowest one down at the same hierarchy level appears on top). Elements with non-static positioning will always appear on top of elements with default static positioning.

Also note that nesting plays a big role. If an element B sits on top of element A, a child element of element A can never be higher than element B.


NOTE: I'm not looking for a fix by changing the position attribute- I'm just trying to understand why this current flow is happening with the default static positioning.

like image 783
Yarin Avatar asked Nov 25 '25 18:11

Yarin


2 Answers

The painting order is defined in Appendix E.

When the browser paints these contents, it will first paint background of the blocks

  1. For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item, or other block equivalent:

    1. background color of element.

And backgrounds of inline-blocks will be painted in front of the ones from the blocks:

  1. Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:

    1. Otherwise, for each line box of that element:

      1. For each box that is a child of that element, in that line box, in tree order:

        1. background color of element.

Note that the contents of the second block will still be painted in front of the inline-blocks:

div {
  height: 20px;
  background: green;
}
div + div {
  background: yellow;
  margin-top: -10px;
  color: #0ff;
}
span {
  background: red;
  display: inline-block;
  padding: 2px;
}
<div>
  <span>HELLO</span>
  <span>HELLO</span>
  <span>HELLO</span>
</div>
<div>█ █ █ █ █ █ █ █ █</div>
like image 81
Oriol Avatar answered Nov 27 '25 08:11

Oriol


Use position: relative, and research position and z-index.

https://jsfiddle.net/xwghd5r2/1/

like image 41
Artem Gorlachev Avatar answered Nov 27 '25 10:11

Artem Gorlachev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!