Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Stacking order of <img> and elements with negative margin

I tried putting a <div> below an <img> with a negative margin, but the <img> ended up covering the <div>. I am confused because the <img> is not positioned, and is not creating a stacking context, so there seems to have no reason for the <img> to go against the natural rendering order of HTML.

When I used display: flex, everything worked as expected, which makes me even more confused. Can someone explain this to me? Are there any specs that outline this behavior?

.img {
  display: block;
}

.square {
  height: 100px;
  margin-top: -30px;
  background-color: green;
}

#flex {
  display: flex;
  flex-direction: column;
}

#container {
  display: flex;
  gap: 20px;
}

#container > * {
  width: 100px;
}
<div id="container">
  <div>
    <img class="img" src="https://placehold.co/100">
    <div class="square"></div>
  </div>

  <div id="flex">
    <img class="img" src="https://placehold.co/100">
    <div class="square"></div>
  </div>
</div>

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Both behaviors are correct. In a normal flow (your first example), the content always have the priority over the background of adjacent elements so the image will get painted above the background.

Here is a relevant question with full detail: Why the content is not covered by the background of an overlapping element?

When you make the container a flexbox one, the painting algorithm is modified because flex items behave differently

Flex items paint exactly the same as inline blocks ref

inline block elements are painted as a whole element like the ones that create stacking context so no more interaction with the content of sibling elements

For inline-block and inline-table elements:

1 For each one of these, treat the element as if it created a new stacking context, ref


Here is another example with text content on the second div to better understand the first case:

.img {
  display: block;
}

.square {
  height: 100px;
  margin-top: -30px;
  background-color: green;
}

#flex {
  display: flex;
  flex-direction: column;
}

#container {
  display: flex;
  gap: 20px;
}

#container > * {
  width: 100px;
}
<div id="container">
  <div>
    <img class="img" src="https://placehold.co/100">
    <div class="square"> text content</div>
  </div>

  <div id="flex">
    <img class="img" src="https://placehold.co/100">
    <div class="square"> text content</div>
  </div>
</div>

The text is always painted above the image and only the background is behind. By making the container a flexbox one, you change this behavior.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading