Learn CSS Transforms by Building a Penguin - Positioning Question

Why is .ground positioned below .penguin here? .ground is absolutely positioned, without a top, left, right, or bottom set, with z-index of 3 putting it in its own stacking context alone. .penguin is statically positioned. I would expect .ground to show up at the top of the body element, overlapping .left-mountain and .penguin. Any ideas?


<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="./styles.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <div class="left-mountain"></div>
    <div class="penguin"></div>
    <div class="ground"></div>


body {
  background: linear-gradient(45deg, rgb(118, 201, 255), rgb(247, 255, 222));
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100vh;
  overflow: hidden;

.left-mountain {
  width: 300px;
  height: 300px;
  background: linear-gradient(rgb(203, 241, 228), rgb(80, 183, 255));
  position: absolute;
  transform: skew(0deg, 44deg);
  z-index: 2;
  margin-top: 100px;

.penguin {
  width: 300px;
  height: 300px;
  margin: auto;
  margin-top: 75px;

.ground {
  width: 100vw;
  height: 400px;
  background: linear-gradient(90deg, rgb(88, 175, 236), rgb(182, 255, 255));
  z-index: 3;
  position: absolute;
  margin-top: -58px;

Code placement does not matter much in HTML,CSS, and JS. the code it self is being processed in micro seconds.

That’s not really what I’m asking here, perhaps I worded the question poorly, but I can’t edit the post any longer…

The div.ground element is being rendered on the page below the div.penguin element, and I cannot understand why, given how their respective position properties have been defined within the CSS (div.penguin being static by default).

What do you have posted here, it looks like fcc but from where are these little boxes coming from: div.penuin and div.ground

The link to the project is at the bottom of my post (Idk why the preview of the link doesn’t give the appropriate page title)

Not sure if I can give a great technical explanation. You would need to set the top offset to 0 to make it overlap.

  1. The penguin element comes before it and is inflow.

  2. The absolute positioned element has a height set and no offset.

  3. Any content after the absolute positioned element (siblings after the element) would be covered up by it.

Example, the nav is not covered, the inflow element after it is.

  <a href="#">1</a>
  <a href="#">2</a>
  <a href="#">3</a>

<div class="absolute"></div>
<div class="inflow">inflow</div>
.absolute {
  background-color: rgba(255 0 0 / 85%);
  height: 200px;
  width: 100%;
  position: absolute;

The specs for the layout model is not an easy read.

4. Absolute Positioning Layout Model

I guess the summary would be, the order of the elements matter.

The absolutely positioned element still has an “original insert position” after the inflow element that comes before it. That position must be changed using the offset (if you want the overlap).

Inflow element that comes after the absolutely positioned element are covered up, because the absolute position element is located in their normal inflow position and not pushing them down (so they overlap).

Not sure if that was any better, to be honest.

Thank you for your responses, and for that link. Definitely not an easy read like you said, but that combined with the MDN helped me to understand. I guess I had some false assumptions about the default behavior, basically that 'top` would be 0.

From your link:

If only one inset property in a given axis is auto, it is set to zero. If both inset properties in a given axis are auto, then, depending on the box’s self-alignment property in the relevant axis:
for self-start alignment or its equivalent:
Set its start-edge inset property to the static position, and its end-edge inset property to zero.

Here’s what really clarified this for me (regarding the ‘top’ property):

Specifies that:
For absolutely positioned elements, the position of the element is based on the bottom property, while height: auto is treated as a height based on the content; or if bottom is also auto, the element is positioned where it should vertically be positioned if it were a static element.