Overflow and layers
Sometimes the content is bigger than its block: long text in a card of fixed height, a wide table on a narrow screen. The overflow property decides what to do with the excess. And when elements overlap, z-index decides which of them is seen on top.
Overflow
Overflow is the situation when the content does not fit into the size of a block. By default the excess simply sticks out and runs over the neighbours:
<style>
.box { width: 260px; height: 50px; border: 2px solid crimson; margin-bottom: 40px; }
</style>
<div class="box">This text does not fit into a block 50 pixels tall. It goes on below the frame and sticks out of it, running over whatever comes next.</div>
<p>The next paragraph</p>The overflow property
| Value | What happens to the excess |
|---|---|
visible | Sticks out (the default) |
hidden | Is cut off and not visible |
auto | A scrollbar appears, only when needed |
scroll | Scrollbars are always there |
<style>
.box { width: 260px; height: 60px; border: 2px solid seagreen; overflow: auto; }
</style>
<div class="box">This text does not fit either, but the block got its own scrolling. Scroll it with the mouse wheel or a finger to read to the end. And here is the end.</div>Most often you need auto: the scrollbar appears only when it is really needed.
Horizontal scrolling
overflow-x and overflow-y control the directions separately. A wide table is wrapped in a block with overflow-x: auto — the table scrolls, not the whole page:
<style>
.scroll { overflow-x: auto; border: 1px solid silver; }
table { border-collapse: collapse; }
td { padding: 6px 12px; border: 1px solid silver; white-space: nowrap; }
</style>
<div class="scroll">
<table>
<tr><td>January</td><td>February</td><td>March</td><td>April</td><td>May</td><td>June</td><td>July</td><td>August</td><td>September</td><td>October</td></tr>
</table>
</div>An ellipsis
To cut a line and put "…" at the end, three properties are needed together: no wrapping, clipping and the ellipsis itself:
<style>
.title { width: 220px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
</style>
<p class="title">A very long article title that does not fit on one line</p>z-index: who is on top
When elements overlap, the one that comes later in the HTML is on top. z-index changes this order: the bigger the number, the higher the layer. It works on elements whose position is not static, and also on flex and grid items:
<style>
.stack { position: relative; height: 110px; }
.stack div { position: absolute; width: 100px; height: 70px; padding: 6px; }
.a { top: 0; left: 0; background: lightskyblue; z-index: 2; }
.b { top: 30px; left: 50px; background: gold; z-index: 1; }
</style>
<div class="stack">
<div class="a">z-index: 2</div>
<div class="b">z-index: 1</div>
</div>The blue block comes earlier in the HTML, but lies on top thanks to its bigger z-index.
Stacking context
An element with a position and a z-index creates a stacking context — a separate pile of layers. Its children are compared only with each other: a child with z-index: 999 will not rise above its parent's neighbour if the parent itself lies lower. That is why huge numbers do not help — look at which ancestors have a z-index.
Common mistake
z-index on an element without position in the normal flow has no effect. However big the number, the block stays below:
<style>
.a { background: lightskyblue; padding: 12px; z-index: 10; }
.b { background: gold; padding: 12px; margin-top: -20px; position: relative; }
</style>
<div class="a">z-index: 10, but no position</div>
<div class="b">I am on top</div>Give the blue block position: relative — and it ends up on top.