HuntExams Academy logo
HTML/CSSBeginner#css#layout-puzzle

How do you vertically center text inside a single-line button using CSS?

Answer

For a fixed-height single line of text, set line-height equal to the button's height, which centers text vertically without flexbox. For multi-line or icon+text buttons, flexbox with align-items: center is more robust.

Example

.btn { height: 40px; line-height: 40px; padding: 0 16px; }
/* flexbox alternative for icons+text */
.btn-icon { display: flex; align-items: center; height: 40px; }

Detailed explanation

For a button containing one line of text, a simple CSS technique is to set line-height equal to its height. For example, .btn { height: 40px; line-height: 40px; padding: 0 16px; } gives the text a 40px line box, matching the specified height. Horizontal padding creates space beside the label, while zero vertical padding avoids adding extra space above or below it. This technique does not require flexbox and is useful when the button has a predictable height and a short label.

Under the hood, line-height controls the height of the text's line box, not the size of the characters. The browser uses font metrics to position the text and distributes the additional leading above and below it. When a single line box fills the button's content height, this produces the usual vertically centred appearance. It does not guarantee exact optical centring of every font's visible glyphs, because ascenders, descenders, and other font metrics differ. Also, line-height does not centre text horizontally; use text-align: center for that separate requirement.

The box model matters when applying this shortcut. With content-box sizing, height describes the content area, and borders increase the outer height. With border-box sizing, height includes padding and borders, so a 40px button with borders has less than 40px of content height. Therefore, matching both values blindly can introduce a small offset. A controlled demonstration is .btn { box-sizing: border-box; height: 40px; line-height: 40px; padding: 0 16px; border: 0; text-align: center; }. Native button styling can also affect the result, so check the computed styles.

For wrapping labels or icon-and-text combinations, flexbox is more robust: .btn-icon { display: inline-flex; align-items: center; justify-content: center; min-height: 40px; padding: 8px 16px; gap: 8px; }. In the default row direction, align-items centres items vertically, while justify-content centres them horizontally. Keep a normal, readable line-height rather than matching it to the button height. Interviewers usually look for the simple single-line solution first, followed by awareness of its box-model assumptions and why flexible layouts handle changing content better.

Key points to remember

  • For a fixed-height, single-line label, match line-height to the content height.
  • Use zero vertical padding for the basic line-height technique.
  • Account for borders, box-sizing, and native button styles.
  • Vertical centring and horizontal centring are separate requirements.
  • Prefer flexbox for icons or wrapping text; min-height allows content to grow.

Common mistakes candidates make

  • Using vertical-align: middle on a normal button and expecting it to centre the button's text internally.
  • Matching line-height to height without accounting for vertical padding or border-box borders.
  • Applying a button-height line-height to multiline labels, creating excessive spacing and possible overflow.

Likely follow-up questions

Why does vertical-align: middle not solve this directly?

For inline-level elements, vertical-align controls alignment relative to the surrounding line, rather than centring their internal content. It can vertically align content in table cells, but a normal button does not use that layout model.

Should I use flex or inline-flex for a button?

Both create a flex layout for the button's contents. inline-flex lets the button participate in inline flow, which is often convenient for buttons placed beside text or other buttons.

What happens if the label wraps onto two lines?

Each line receives the specified line-height, so two 40px lines cannot fit inside a 40px content area. Use a readable line-height with flexbox, padding, and min-height so the button can expand.

Interview tip: Show the height-and-line-height rule first, state its single-line assumption, and then explain when you would switch to flexbox.

Related Interview Questions

1
HTML/CSSIntermediate#css#tailwind

What is the difference between a CSS framework like Bootstrap and a utility-first framework like Tailwind?

Open
2
HTML/CSSAdvanced#css#units

What is the difference between static and dynamic viewport units (vh vs dvh)?

Open
3
HTML/CSSIntermediate#css#cross-browser

How do you handle browser-specific CSS prefixes and why is Autoprefixer useful?

Open