How to overlap elements
Short answer
Give the parent position: relative and the overlapping element position: absolute plus coordinates:
<div style="position: relative; width: 300px;">
<img src="/media/photo-400x250.jpg" alt="" style="width: 100%; display: block;">
<p style="position: absolute; left: 0; right: 0; bottom: 0; margin: 0; padding: 8px; background: rgb(0 0 0 / 60%); color: white;">Summer in the mountains</p>
</div>An absolute element counts left, bottom and the other offsets from the nearest positioned ancestor — that is why the wrapper has relative.
Without absolute positioning
In grid you can place several items in the same cell — they stack on top of each other but stay in the flow, so the parent grows to fit the tallest:
<style>
.stack { display: grid; width: 300px; }
.stack > * { grid-area: 1 / 1; }
.stack h2 { align-self: center; justify-self: center; margin: 0; color: white; }
</style>
<div class="stack">
<img src="/media/photo-400x250.jpg" alt="" style="width: 100%;">
<h2>Sale</h2>
</div>Which one is on top
Of overlapping elements, the later one in the code is on top. z-index changes the order, and it only works on elements with position or on children of a flex or grid container.
Common mistake
If you forget position: relative on the parent, the absolute element counts its offsets from the whole page and flies off to its corner.