Alignment basics: what CSS “align” really means
“Alignment” sounds like one thing, but in CSS it depends on what you’re aligning:
- Text and inline content (words, inline links, inline icons) → usually
text-alignorvertical-align. - Boxes (divs, cards, layouts) → usually
margin: auto, flexbox, or grid. - Single elements that should be perfectly centered → grid/flex centering, or absolute+transform tricks.
One beginner rule that explains 80% of “why won’t this align?”: alignment needs extra space. If the container is only as big as the thing inside it, there’s nothing to “center within”.
Text-align: aligning inline content
text-align aligns inline content inside a block container: text, inline links, inline icons, and also
inline-level elements like img (by default).
text-align: left / center / right / justify
.demo { text-align: left; }
*, ::before, ::after { box-sizing: border-box; } .demo { border: 3px solid #111; padding: 18px; max-width: 560px; font-family: ui-monospace, system-ui; line-height: 1.45; } .demo a { text-decoration: underline; }
This is a paragraph with a link and some text. Try switching text-align values.
Notice how we didn’t align the .demo box itself, only the content inside it. If you want to center the
whole box, that’s a different technique (we’ll do that soon).
Centering images and buttons with text-align
A very common beginner trick: if an element is inline (or inline-block), text-align can center it.
Images are inline by default, buttons are often inline-block-ish.
.demo { text-align: center; }
*, ::before, ::after { box-sizing: border-box; } .demo { border: 3px solid #111; padding: 18px; max-width: 560px; font-family: system-ui, ui-monospace; } .demo img { width: 220px; height: auto; } .button { display: inline-block; margin-top: 14px; padding: 10px 14px; border: 2px solid #111; text-decoration: none; font-family: ui-monospace, system-ui; }
Centering block elements with auto margins
To center a block element horizontally, the classic move is: margin-inline: auto. But
it only works when the block has a constrained width (like width or max-width).
margin-inline: auto (the classic “center a box”)
.card { margin-inline: auto; }
.card { margin-inline: auto; max-width: 410px; }
.card { margin-inline: auto; width: 320px; }
*, ::before, ::after { box-sizing: border-box; } .wrap { border: 3px dashed #111; padding: 18px; font-family: ui-monospace, system-ui; } .card { border: 3px solid #111; padding: 16px; background: #f2f2f2; }
Centered card (when it has a width or max-width).
Try the different snippets.
If the element is naturally width: 100%, there is nothing to “center” because it already fills the row.
That’s why adding max-width or width makes the centering visible.
vertical-align: inline alignment and baselines
vertical-align is often misunderstood because it does not vertically center block
elements. It aligns inline or inline-block elements relative to the line box (baseline, middle, top, etc.).
Fixing the “icon sits too low” problem
.icon { vertical-align: baseline; }
*, ::before, ::after { box-sizing: border-box; } .demo { border: 3px solid #111; padding: 18px; font-family: system-ui, ui-monospace; font-size: 20px; } .icon { display: inline-block; width: 22px; height: 22px; border: 2px solid #111; background: #f2f2f2; margin-right: 8px; }
Icon next to text
For inline icons/images next to text, vertical-align: middle is a very common “feels right” choice.
Flexbox alignment: the layout workhorse
Flexbox aligns items inside a flex container. It has two axes:
- Main axis (default: horizontal) → controlled by
justify-content. - Cross axis (default: vertical) → controlled by
align-items.
If you change flex-direction, the axes swap. (Sneaky, but useful.)
justify-content (main axis)
.flex { display: flex; justify-content: flex-start; }
*, ::before, ::after { box-sizing: border-box; } .flex { border: 3px solid #111; padding: 12px; font-family: ui-monospace, system-ui; } .item { border: 2px solid #111; padding: 10px 12px; background: #f2f2f2; }
OneTwoThreeFour
align-items (cross axis)
To see cross-axis alignment clearly, we need the container to have some height.
.flex { display: flex; align-items: stretch; }
*, ::before, ::after { box-sizing: border-box; } .flex { border: 3px solid #111; padding: 12px; height: 160px; font-family: ui-monospace, system-ui; gap: 10px; } .item { border: 2px solid #111; padding: 10px 12px; background: #f2f2f2; } .item.tall { padding-top: 22px; padding-bottom: 22px; font-size: 22px; }
SmallTallerSmall
stretch is the default for align-items. It stretches items to fill the container’s
cross size when the item’s cross size is auto.
align-content (only when wrapping)
This one gets people: align-content does nothing unless there are multiple flex lines.
That means you need flex-wrap: wrap and enough items to wrap.
.flex { display: flex; flex-wrap: wrap; align-content: flex-start; }
*, ::before, ::after { box-sizing: border-box; } .flex { border: 3px solid #111; height: 220px; padding: 12px; gap: 10px; font-family: ui-monospace, system-ui; } .item { border: 2px solid #111; background: #f2f2f2; padding: 10px 12px; width: 120px; }
12345678
Flexbox perfect centering (two lines)
The famous recipe: justify-content: center and align-items: center.
.center { display: flex; justify-content: center; align-items: center; }
.center { display: flex; justify-content: center; align-items: center; flex-direction: column; }
*, ::before, ::after { box-sizing: border-box; } .center { border: 3px solid #111; height: 200px; font-family: ui-monospace, system-ui; background: #f2f2f2; gap: 10px; padding: 10px; } .badge { border: 2px solid #111; padding: 8px 10px; background: #fff; }
CenteredAlso centered
Flexbox trick: push one item to the end with auto margins
A practical pattern for headers/nav bars: put margin-left: auto on the item you want to “push right”.
.bar .spacer { margin-left: auto; }
.bar { justify-content: space-between; }
*, ::before, ::after { box-sizing: border-box; } .bar { display: flex; align-items: center; gap: 10px; border: 3px solid #111; padding: 12px; font-family: ui-monospace, system-ui; } .pill { border: 2px solid #111; padding: 8px 10px; background: #f2f2f2; }
Both snippets work, but auto margin is amazing when you want “these stay left, that one goes right” without calculating spacing.
Grid alignment: precise two-dimensional control
Grid is like flexbox’s more structured cousin. Flex is great for one-dimensional flow. Grid shines when you care about both rows and columns.
Aligning items inside their cells
Use justify-items (inline direction) and align-items (block direction), or the shorthand
place-items.
.grid { display: grid; place-items: start; }
.grid { display: grid; place-items: center; }
.grid { display: grid; place-items: end; }
*, ::before, ::after { box-sizing: border-box; } .grid { border: 3px solid #111; padding: 12px; height: 220px; font-family: ui-monospace, system-ui; background: #f2f2f2; grid-template-columns: repeat(3, 1fr); gap: 10px; } .item { border: 2px solid #111; background: #fff; padding: 10px 12px; width: 90px; }
ABCDEF
The grid cells are bigger than the items, so you can really see the alignment.
Aligning the whole grid inside its container
This is a different concept: justify-content and align-content control how the entire
grid sits inside the container when the container is bigger than the grid tracks.
.grid { display: grid; place-content: start; }
*, ::before, ::after { box-sizing: border-box; } .grid { border: 3px solid #111; padding: 12px; height: 260px; font-family: ui-monospace, system-ui; background: #f2f2f2; grid-template-columns: repeat(2, 140px); grid-auto-rows: 60px; gap: 10px; } .item { border: 2px solid #111; background: #fff; display: grid; place-items: center; }
1234
Aligning a single item with *-self
Grid gives each item its own “override”: justify-self and align-self (or
place-self).
.featured { place-self: center; }
.featured { justify-self: end; align-self: start; }
*, ::before, ::after { box-sizing: border-box; } .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; border: 3px solid #111; padding: 12px; height: 220px; font-family: ui-monospace, system-ui; background: #f2f2f2; } .item { border: 2px solid #111; background: #fff; padding: 10px 12px; width: 90px; }
ABCDEF
Absolute positioning: old-school centering (still useful)
Sometimes you don’t want layout rules; you want one thing floating on top of another. That’s where absolute positioning shines.
Center with top/left + translate(-50%, -50%)
This is the classic: set top: 50% and left: 50%, then pull back by half the element’s own
size with transform: translate(-50%, -50%).
.stage { position: relative; }
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.stage { position: relative; } .modal { position: absolute; inset: 0; margin: auto; height: 130px;}
*, ::before, ::after { box-sizing: border-box; } .stage { border: 3px solid #111; height: 240px; background: url("https://picsum.photos/900/260") center / cover no-repeat; font-family: ui-monospace, system-ui; overflow: hidden; } .modal { width: min(360px, 85%); border: 3px solid #111; background: rgba(255, 255, 255, 0.92); padding: 14px; } .modal p { margin: 0; }
Centered overlay
Absolute positioning style.
The second snippet (inset: 0; margin: auto;) is a neat alternative when the element has a known size.
The translate version works great even when the size changes.
The easy button: place-items: center
If you can use grid, place-items: center is the “I want this centered, please and thank you” option.
.center { display: grid; place-items: center; }
.center { display: grid; place-items: center; text-align: center; }
*, ::before, ::after { box-sizing: border-box; } .center { border: 3px solid #111; height: 220px; font-family: ui-monospace, system-ui; background: #f2f2f2; padding: 12px; } .card { border: 2px solid #111; background: #fff; padding: 14px; width: min(410px, 90%); }
Centered card
Grid makes centering almost suspiciously easy.
Real-world alignment patterns
Pattern: centered page content with max-width
This is the classic blog/article layout: the page is wide, but the content is comfortable to read.
.container { max-width: 680px; margin-inline: auto; padding-inline: 16px; }
.container { max-width: 680px; margin-inline: auto; padding-inline: 16px; text-align: center; }
*, ::before, ::after { box-sizing: border-box; } .page { border: 3px solid #111; padding: 18px; font-family: system-ui, ui-monospace; line-height: 1.5; background: #f2f2f2; } .container { border: 2px dashed #111; padding-block: 12px; } h4 { margin: 0 0 10px; font-family: ui-monospace, system-ui; }
Reading width content
This container is centered with margin-inline: auto. The page can be huge, but this stays readable.
Pattern: icon + text perfectly aligned (row)
Use flexbox for little UI rows. It’s clean and predictable.
.row { display: flex; align-items: center; gap: 10px; }
.row { display: flex; align-items: baseline; gap: 10px; }
*, ::before, ::after { box-sizing: border-box; } .row { border: 3px solid #111; padding: 14px; font-family: system-ui, ui-monospace; } .avatar { width: 52px; height: 52px; border: 2px solid #111; background: url("https://picsum.photos/120/120") center / cover no-repeat; border-radius: 50%; flex: 0 0 auto; } .name { font-family: ui-monospace, system-ui; font-size: 18px; } .meta { opacity: 0.8; }
Alex
Pattern: centered modal with backdrop
Grid centering is a great “modal overlay” pattern: the backdrop is the container, the modal is the child.
.backdrop { display: grid; place-items: center; }
.backdrop { display: flex; justify-content: center; align-items: center; }
*, ::before, ::after { box-sizing: border-box; } .backdrop { border: 3px solid #111; height: 260px; font-family: ui-monospace, system-ui; background: rgba(0, 0, 0, 0.18); padding: 14px; } .modal { width: min(410px, 90%); border: 3px solid #111; background: #fff; padding: 14px; } .modal .actions { display: flex; gap: 10px; margin-top: 12px; } .modal a { display: inline-block; padding: 8px 10px; border: 2px solid #111; text-decoration: none; }
Troubleshooting: why alignment doesn’t work
Why text-align “does nothing”
- You’re trying to align a block element, not inline content. Use
margin-inline: auto, flex, or grid. - Your “thing” is 100% width, so centering looks identical.
Why margin: auto doesn’t center
- The element has no width constraint. Add
widthormax-width. - You’re centering vertically with margins, but the layout doesn’t create extra vertical space.
Why align-items doesn’t seem to work
- The container has no height (or no extra space). Give it height, or let it be taller than its children.
- You forgot
display: flexordisplay: gridon the container. - You used
align-contentwithout wrapping (flex) or without extra track space (grid).
Why translate(-50%, -50%) sometimes feels weird
- Transforms can affect subpixel rendering and create slightly blurry text on some screens.
- If you need pixel-crisp UI, consider grid/flex centering instead (when possible).
Quick cheatsheet: CSS alignment
- Center text / inline stuff:
text-align: center - Center a block horizontally:
max-width: ...; margin-inline: auto - Center in flex:
display: flex; justify-content: center; align-items: center - Center in grid:
display: grid; place-items: center - Push one flex item right:
margin-left: auto - Align inline icon with text:
vertical-align: middle - Absolute center (overlay):
top: 50%; left: 50%; transform: translate(-50%, -50%)
Conclusion: you now have CSS alignment superpowers
Alignment in CSS isn’t one feature, it’s a toolbox. Use text-align and vertical-align for
inline content, use margin-inline: auto when you’re centering a block with a constrained width, and
reach for flexbox or grid when you want layout-level control (especially for vertical centering). When you need
overlays, absolute positioning with transform: translate(-50%, -50%) is still a perfectly valid
classic.
Most alignment bugs come down to one thing: there’s no extra space to align within. So whenever something “refuses” to center, check the container size, the element’s width/height, and whether you’re using the right alignment system for the job. Once you get that habit, alignment stops being mysterious and starts being… quite satisfying.
You can learn even more in our Centering With CSS Interactive Tutorial.
