Display and positioning
Why you need this
So far elements have gone one after another from top to bottom — this is the document's normal
flow. But on real sites the menu stands in a line, a «−20%» badge hangs in the corner of a card, the
chat button doesn't move when you scroll, and the sign-in window appears on top of the page. All of
this is done with the display and position properties.
display: how an element enters the flow
.a { display: block; }
.b { display: inline; }
.c { display: inline-block; }
.d { display: none; }
| Value | How it behaves | Default for |
|---|---|---|
block |
on a new line, full width; width, height, margin work |
div, p, h1, ul, li |
inline |
inside a line, like a word; width and height don't work |
span, a, strong, img |
inline-block |
in a line like a word, but sizes and spacing work | button, input |
none |
the element is gone: not visible and takes no space | head, script |
<style>
a { display: inline-block; padding: 10px 20px; background: gold; }
</style>
<a href="#">Buy</a> <a href="#">Add to cart</a>
Result: two yellow buttons side by side. With plain inline, the top and bottom padding would overlap the neighbouring lines.
display: none is used to hide elements (the menu on a phone, a window until a button is pressed).
visibility: hidden hides an element but keeps empty space for it.
position: where an element stands
| Value | Measured from | Leaves the flow? |
|---|---|---|
static |
the normal position (the default) | no |
relative |
its own normal place | no, the space stays |
absolute |
the nearest ancestor whose position isn't static |
yes |
fixed |
the browser window; doesn't move when scrolling | yes |
sticky |
normal, but "sticks" while scrolling | no |
The position is set with top, right, bottom, left — the distance from the matching edge.
relative
.shift { position: relative; top: 10px; left: 20px; }
Result: the element is shifted 10px down and 20px right, and a "hole" stays in its old place.
On its own relative is rarely needed — it's usually set on a parent so that absolute works inside.
absolute
<style>
.photo { position: relative; width: 200px; height: 150px; background: #ddd; }
.sale { position: absolute; top: 0; left: 0; background: red; color: white; }
</style>
<div class="photo">
<span class="sale">−20%</span>
</div>
Result: a red «−20%» badge in the top left corner of the grey block.
Important: absolute looks for the nearest ancestor with position: relative (or absolute, fixed, sticky).
If there is none, it's measured from the whole page, and the badge flies off to a corner of the screen.
fixed
.up { position: fixed; right: 20px; bottom: 20px; }
Result: the button is always in the bottom right corner of the window, whatever the user scrolls. This is how «Back to top» buttons, support chats and cookie banners are made.
sticky
.header { position: sticky; top: 0; background: white; }
Result: the header moves with the page, but when it reaches the top of the window it "sticks" and stays there.
Without top, sticky doesn't work: the browser needs to know where to stick.
z-index: who is on top
When elements overlap, the one with the larger z-index is on top
(it works only on positioned elements — not static):
.modal { position: fixed; z-index: 100; }
.chat { position: fixed; z-index: 10; }
Result: the window covers the chat button. Picture a stack of sheets: z-index is the number of the sheet from the top.
How it works inside
The browser first lays out all normal-flow elements from top to bottom. It "takes out" absolute and
fixed elements from the flow — the neighbours don't see them and move into the freed space. Then the
taken-out elements are drawn at their own coordinates on top of the rest, in z-index order.
Common mistakes
widthoninline. Sizes don't work on<span>and<a>— you needinline-blockorblock.- Forgot
relativeon the parent. Theabsolutebadge flies to a corner of the page. z-index"doesn't work". The element hasposition: static— z-index has no effect. Addposition: relative.stickywithouttop. Nothing sticks.- A whole layout built on
absolute. On another screen size everything overlaps. Use Flexbox and Grid (the next topics) for layout, andabsolutefor small things like badges.
Cheat sheet
| Code | What it does |
|---|---|
display: block / inline / inline-block |
how it enters the flow |
display: none |
remove the element completely |
visibility: hidden |
hide it, keeping the space |
position: relative |
a shift from its own place; an "anchor" for absolute |
position: absolute |
from the nearest positioned ancestor |
position: fixed |
from the window, doesn't move when scrolling |
position: sticky; top: 0 |
sticks while scrolling |
top / right / bottom / left |
coordinates |
z-index |
who is on top |