The Question
You have a parent container with two children, and you want both children to completely overlap — same position, same size, stacked like cards in a deck:
<div class="container">
<div class="foo"></div>
<div class="bar"></div>
</div>
So we need to pull .foo and .bar out of the normal document flow so they both sit in the exact same spot inside .container.
Solution 1: Absolute Positioning
The classic answer. Make the parent a positioning context, then absolutely position the children to fill it.
.container {
width: 100px;
height: 100px;
position: relative; /* establishes the positioning context */
background-color: #eee;
}
.foo, .bar {
position: absolute; /* removes them from the flow */
inset: 0; /* shorthand for top/right/bottom/left: 0 */
}
.foo {
background-color: rgba(255, 0, 0, 0.5);
z-index: 1;
}
.bar {
background-color: rgba(0, 0, 255, 0.5);
z-index: 2; /* sits above .foo */
}
Why this works
-
position: relativeon the parent — without it, the children would anchor to the nearest positioned ancestor (or the viewport). This line locks them to.container. -
inset: 0— a modern shorthand that stretches the child to fill the parent. No need to hard-codewidthandheight. -
z-index— when elements overlap, the later one wins by default. Usez-indexwhen you want explicit control over stacking order.
Solution 2: CSS Grid
If you'd rather not reach for position: absolute, CSS Grid has an elegant trick: put every child into the same grid cell.
.container {
display: grid;
width: 100px;
height: 100px;
}
.foo, .bar {
/* everyone claims row 1, column 1 */
grid-area: 1 / 1;
}
That's it. Both children occupy the same cell and stretch to fill it. No absolute positioning, no z-index required (though you can still use it if you need to reorder).
This is often the cleaner choice when you want the overlap to participate in normal layout flow — for example, when the container's size should be driven by its children's intrinsic size.
When to Use Which
| Situation | Reach for |
|---|---|
| Overlaying a loading spinner, tooltip, or tag on a fixed-size box | Absolute positioning |
| Layering content where the tallest child should define the container height | CSS Grid |
You already have a position: relative parent for other reasons |
Absolute positioning |
| You want the most modern, least-surprising solution | CSS Grid |
Conclusion
Two tools, one problem. Absolute positioning is the battle-tested approach every frontend developer should know. CSS Grid's single-cell trick is the modern alternative that keeps children in the layout flow.
Next time you reach for position: absolute out of habit, ask yourself whether grid-area: 1 / 1 would be cleaner.
Top comments (0)