50 slightly incorrect, hilarious, or infuriating ways to vertically center content on a webpage
A field guide to centering vertically. The way it's done in the field. By people who are angry. Each technique is its own page. The dotted line on the preview shows where center actually is.
Technically correct, theatrically wrong
01 just a <table> (federally mandated) works
Compliant with the Department of Internet Things' IE5-compatibility mandate. We support exactly one (1) browser. It was released in 1999. We are not allowed to upgrade it.
<table border="2" cellpadding="20" cellspacing="0"
width="100%" height="100%" bgcolor="#faf6e8">
<tr><td valign="middle" align="center">
am I centered?
</td></tr>
</table>
03 works until a parent has position: relative footgun
With no positioned ancestor, an absolute + translate(-50%, -50%) child is positioned against the viewport — which centers it correctly! Until someone, anywhere up the tree, types position: relative. The preview has a button so you can watch it happen.
.parent { /* position: static — for now */ }
#centerish {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
/* one day .parent will gain position: relative
for a tooltip, an overlay, anything. That day,
the centering will move and nobody will know why... */
05 line-height = 100vh (centered when terse) wrong
One line of text inside a line box that's 100vh tall ends up vertically centered. Add a second line and each one is 100vh tall. The page becomes a stairway.
html, body { height: 100vh; }
body {
text-align: center;
line-height: 100vh;
}
/* one line: centered. two lines: 200vh of content. */
Two divs working together in cross-functional alignment. The parent owns position. The child owns offset. Together they deliver verticality at scale. Q4 OKR achieved.
Floats were designed to wrap text around images. We're using one as a 50vh-tall spacer with a negative margin equal to half the content height. Together the math cancels and the content lands centered. The content height is hardcoded.
38 WebGL: a single quad at clip-space (0,0) js crime
Compile a shader. Set up buffers. Render text as a texture. Three hundred lines. Centered.
// vertex shader: gl_Position = vec4(pos, 0, 1);
// quad spans (-0.4, -0.1) to (0.4, 0.1)
// text drawn to canvas, used as texture
// 50 LOC of WebGL boilerplate omitted
43 CSS anchor positioning (anchor placed by hand) galaxy
Place a 0×0 invisible anchor at the center using top: 50vh. Then position the content relative to the anchor with anchor(center). Two new CSS specs to do what one already did.
.anchor {
position: absolute;
top: 50vh; left: 50vw; /* anchor is centered the OLD way */
width: 0; height: 0;
anchor-name: --middle;
}
#centerish {
position: absolute;
position-anchor: --middle;
top: anchor(center); /* defer to the anchor we just placed */
left: anchor(center);
translate: -50% -50%;
}
Browsers center a <button>'s content on both axes for free, courtesy of the user-agent stylesheet. Make the button viewport-sized, strip the default chrome, and the centering happens. No flex, no grid, no place-items. Click and the text spins.
button#centerish {
width: 100vw;
height: 100vh;
appearance: none;
background: none;
border: none;
padding: 0;
font: inherit;
color: inherit;
/* the UA stylesheet does the centering */
}
45 text at 100vh, centered by being everywhere galaxy
Make the element AND its text 100vh tall. Pick a font-size that fills the viewport top to bottom. The text IS the page. Centered, by virtue of being everywhere.