Question
Why does vertical-align: middle not visually center text next to an image, while vertical-align: top appears to work?
<div>
<img src="https://via.placeholder.com/30" alt="Small placeholder image">
<span>Doesn't work.</span>
</div>
span {
vertical-align: middle;
}
How does vertical-align work in this situation, and what is the correct way to vertically center the text and image?
Short Answer
You will learn that vertical-align aligns inline content relative to a text baseline, not necessarily to an element’s visual center. You will also learn when vertical-align: middle is useful and how Flexbox provides reliable vertical centering for text beside an image.
Concept
vertical-align is commonly misunderstood because its name sounds like a general-purpose vertical-centering tool. It is not.
For inline-level elements such as text, span, and inline images, vertical-align controls how an element aligns within the current line box. A line box is the horizontal row created by a line of text.
By default, inline content aligns on the baseline: the invisible line on which most letters sit.
span {
vertical-align: middle;
}
middle does not mean “put the center of this element at the center of the image.” In CSS inline layout, it means:
- Align the vertical midpoint of the element with the parent text baseline plus half of the parent font’s x-height.
- The x-height is approximately the height of a lowercase
xin the current font.
That rule is based on typography, so it can look slightly too high or too low when placed next to an image.
vertical-align: top can appear more successful because it aligns inline elements to the top of the line box. If the image is the tallest item in that line, the text and image tops may visibly line up. This is still line-box alignment, not general layout centering.
For a UI row containing an image and text, use a layout system designed for layout—usually Flexbox.
Mental Model
Think of inline text as people standing on a painted line on the ground: the baseline. Most letters stand on that line, but parts of letters such as g and p hang below it.
An inline image also joins that same line. By default, its bottom is placed near the baseline, which may leave a small visible gap underneath it.
vertical-align: middle does not ask everyone to stand at the same visual height. Instead, it asks the element to line up with a typography-specific point near the middle of lowercase letters.
Flexbox is different: imagine putting the image and text into a tray. With align-items: center, the tray directly centers both items against each other.
Syntax and Examples
For inline elements, use vertical-align to control alignment inside a line of text.
.inline-item {
vertical-align: middle;
}
For example, an icon often looks good when aligned with nearby text:
<p>
Save
<img class="icon" src="https://via.placeholder.com/16" alt="">
changes
</p>
.icon {
vertical-align: middle;
}
Here, middle is useful because the image behaves like a small inline icon within a sentence.
For an image-and-label UI row, use Flexbox instead:
<div class="profile">
<img src="https://via.placeholder.com/30" alt="User avatar">
<span>Centered next to the image</span>
</div>
.profile {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
display: inline-flexkeeps the whole group inline with surrounding text when needed.align-items: centercenters the image and text along the vertical cross axis.gapadds consistent spacing without margins.
Use display: flex instead when the container should behave as a block-level row.
Step by Step Execution
Consider this inline-layout example:
<div>
<img class="photo" src="https://via.placeholder.com/30" alt="">
<span class="label">Hello</span>
</div>
.label {
vertical-align: middle;
}
What happens:
- The browser creates a line box for the contents of the
div. - The
imgis inline by default, so it participates in that same line box. - The
spanis also inline by default. vertical-align: middlemoves the span according to the parent font’s baseline and x-height.- The image is still aligned using its own default baseline behavior.
- Because the rule is based on font metrics rather than the image’s exact center, the two items may not look centered.
Now use Flexbox:
.profile {
display: flex;
align-items: center;
}
- The
divbecomes a flex container. - The image and span become flex items.
- The main axis is horizontal by default.
- The cross axis is vertical.
align-items: centercenters each item on that vertical cross axis.
This produces actual visual centering regardless of the image dimensions or the text’s font metrics.
Real World Use Cases
vertical-align is useful when content is genuinely part of a line of text:
- Aligning a small status icon with a label such as “Verified”.
- Aligning an inline SVG or emoji-like image in a paragraph.
- Adjusting superscript-like or subscript-like inline content.
- Aligning table cells with
vertical-align: top,middle, orbottom.
Flexbox is usually better for component layouts:
- User avatars beside names and timestamps.
- Buttons containing an icon and label.
- Navigation items with an icon and text.
- File rows with a document thumbnail and filename.
- Chat messages with an avatar beside message content.
- Product rows with an image, title, and price.
Real Codebase Usage
In modern codebases, developers usually separate typography alignment from component layout.
For a reusable icon-and-text component, Flexbox is a common pattern:
.icon-label {
display: inline-flex;
align-items: center;
gap: 0.375rem;
}
.icon-label img,
.icon-label svg {
width: 1em;
height: 1em;
flex: none;
}
Using 1em lets the icon scale with the surrounding text size.
For text inside a rich-text area, where changing the parent to flex would be inappropriate, inline alignment is useful:
.rich-text img.inline-icon {
width: 1em;
height: 1em;
vertical-align: -0.125em;
}
A small length adjustment is sometimes necessary because fonts have different metrics. Test the result with the actual font used by the application.
For table layouts, vertical-align applies to table cells and is still the standard tool:
td {
vertical-align: top;
}
Common Mistakes
Expecting middle to mean exact visual centering
span {
vertical-align: middle;
}
This is valid CSS, but middle is based on font metrics. It is not equivalent to Flexbox centering.
Avoid it: use display: flex and align-items: center for adjacent UI elements.
Applying vertical-align to a block element
/* Usually has no useful effect here */
div {
vertical-align: middle;
}
vertical-align affects inline-level elements and table cells. A normal block-level div does not align with neighboring blocks this way.
Avoid it: use Flexbox, Grid, or another layout method for block elements.
Styling only one item without understanding the other item
span {
vertical-align: middle;
}
The image remains an inline element with default baseline alignment. Styling both items makes the intention clearer when staying in inline layout:
img,
span {
vertical-align: middle;
}
This may improve an inline icon-and-text case, but it still does not guarantee component-style centering as reliably as Flexbox.
Trying to fix alignment with arbitrary margins
span {
margin-top: -4px;
}
This can break when the font, font size, line height, translated text, or image size changes.
Avoid it: choose the appropriate layout model first. Use a small optical adjustment only when inline typography truly requires it.
Forgetting the baseline gap under inline images
An inline image often appears to have space below it because it leaves room for text descenders.
img {
display: block;
}
Making an image block-level removes it from inline baseline layout. This is useful for standalone images, but if it must sit beside text, place both elements in a flex container instead.
Comparisons
| Approach | Best for | How vertical alignment works | Limitation |
|---|---|---|---|
vertical-align: middle | Small icons inside text | Uses baseline and font x-height | Not exact visual centering against arbitrary image sizes |
vertical-align: top | Inline content whose tops should share a line-box top | Aligns to the top of the line box | Depends on line-box sizing |
Flexbox align-items: center | Image-and-text UI rows | Centers flex items on the cross axis | Requires a wrapper/container |
Grid align-items: center | Two-dimensional component layouts | Centers grid items in their grid area | More structure than needed for a simple row |
line-height | Single-line text in a fixed-height area | Can make text appear centered | Fragile and unsuitable for variable or multiline content |
vertical-align and align-items have similar names but operate in different layout systems:
vertical-alignworks in inline and table-cell layout.align-itemsworks in Flexbox and Grid.
Cheat Sheet
/* Inline icon aligned with text */
.icon {
vertical-align: middle;
}
/* Text and image centered as a component */
.row {
display: flex;
align-items: center;
gap: 0.5rem;
}
/* Inline component that can appear in a sentence */
.inline-row {
display: inline-flex;
align-items: center;
gap: 0.25rem;
}
/* Remove the baseline gap from a standalone image */
img {
display: block;
}
Key rules:
vertical-alignis for inline-level elements and table cells.middleuses font metrics; it is not geometric centering.topaligns to the line box’s top, which may only appear to solve the problem.- For adjacent interface elements, prefer Flexbox with
align-items: center. - Set
alt=""for decorative images; provide meaningfulalttext for informative images.
FAQ
Why does vertical-align: middle look off next to an image?
Because CSS calculates middle from the surrounding font’s baseline and x-height, not from the image’s physical center.
Does vertical-align work on a div?
Not in normal block layout. It is mainly effective on inline-level elements and table cells.
Should I put vertical-align: middle on the image or the span?
For an inline icon within text, applying it to the image is common. If multiple inline items need matching alignment, apply it to each relevant item. For a UI row, use Flexbox instead.
Why is there a gap under my inline image?
Inline images participate in text baseline alignment, leaving room for descenders. Use display: block for a standalone image, or use a flex container when it appears beside text.
Is vertical-align: top a reliable centering solution?
No. It aligns tops rather than centers and depends on line-box dimensions. It may look correct in one font or size but not another.
Can I use align-items: center without Flexbox?
align-items works in Flexbox and Grid containers. Add display: flex or display: grid to the parent first.
What should I use for a button with an icon and text?
Use inline-flex or flex on the button and set align-items: center. This is robust for changing text and icon sizes.
Mini Project
Description
Build a compact contact row with an avatar, a name, and an online status. The project demonstrates reliable vertical alignment for interface elements using Flexbox rather than typography-based inline alignment.
Goal
Create a contact row where the avatar, text block, and status indicator remain vertically centered at different font sizes.
Requirements
Create a row containing an avatar, a name, and a status message. Use Flexbox to vertically center the avatar and text content. Add spacing between the avatar and the text block. Use a decorative status dot that stays aligned with the status text. Ensure the avatar has meaningful alternative text.
Keep learning
Related questions
Angular ngClass Conditional Class Binding Explained
Learn how to use Angular ngClass for conditional classes, fix common binding mistakes, and understand why this template error happens.
Apply CSS to an iframe: Same-Origin Styling in HTML
Learn why parent-page CSS does not style iframe content, how same-origin rules work, and practical ways to style embedded pages safely.
Apply Multiple CSS Transforms: rotate() and translate()
Learn how to combine multiple CSS transform functions such as rotate() and translate(), understand transform order, and avoid overwritten rules.