What specific CSS property creates the distinction in text vertical alignment between a <button> and a <div>?

I recently discovered that the text inside a <button> is automatically vertically centered, whereas the text inside a <div> is aligned to the top.

Despite my best efforts, I couldn't determine which CSS rule was responsible for this distinction.

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
}

div {
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}
<div>text text</div>
<button>text text</button>

<div>text text text text</div>
<button>text text text text</button>

<div>text text text text text text</div>
<button>text text text text text text</button>

In the example provided above, after comparing all computed CSS rules in Chrome, I could only spot one difference - align-items: stretch for <div> and align-items: flex-start for <button>.

Even though assigning align-items: flex-start didn't resolve the issue. This left me completely perplexed.

What baffles me is that the vertical text alignment differs between <div> and <button> even when all CSS rules are set with corresponding identical values. Essentially, with matching CSS rules, <div> and <button> behave dissimilarly. Why?

What is the underlying magic at play here?


I have managed to centralize the text vertically inside a <div> (as seen below). However, I am simply intrigued by what causes the discrepancy in text alignment.

Perhaps it's not due to a specific CSS rule, but rather because the layout algorithms for these two elements differ within the browser?

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
}

div { /* basic CSS rules to button-fy  */
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}

/* Magic */
div, button {
  vertical-align: middle;
}

div span {
  display: inline-block;
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
}
<div><span>text text</span></div>
<button>text text</button>

<div><span>text text text text</span></div>
<button>text text text text</button>

<div><span>text text text text text text</span></div>
<button>text text text text text text</button>

Answer №1

When utilizing the inline-block property, it is important to adjust the vertical-align as the default setting is baseline:

Handy CSS Tip:

vertical-align: middle;

The code above will resolve the issue:

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
  vertical-align: middle;
}

div {
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}
<div>text</div>
<button>text</button>

To center the text within the div, you can set the line-height equal to the height of the div.

Nifty CSS Move:

line-height: 4em;

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;

font-family: Arial;
  vertical-align: middle;

line-height: 4em;
}

div {
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}
<div>text</div>
<button>text</button>

Answer №2

By examining the Chrome source code, one can get a glimpse of how it operates, particularly for Chrome itself. It appears that there is an unidentified flex box created with a particular style being applied to it. Although not entirely straightforward — at least in my opinion — one can infer the style that is being applied to this mysterious element by looking at the following link:

The intriguing aspect:

void LayoutButton::updateAnonymousChildStyle(const LayoutObject& child,
                                             ComputedStyle& childStyle) const {
  ASSERT(!m_inner || &child == m_inner);

  childStyle.setFlexGrow(1.0f);
  // min-width: 0; is needed for correct shrinking.
  childStyle.setMinWidth(Length(0, Fixed));
  // Use margin:auto instead of align-items:center to get safe centering, i.e.
  // when the content overflows, treat it the same as align-items: flex-start.
  childStyle.setMarginTop(Length());
  childStyle.setMarginBottom(Length());
  childStyle.setFlexDirection(style()->flexDirection());
  childStyle.setJustifyContent(style()->justifyContent());
  childStyle.setFlexWrap(style()->flexWrap());
  // TODO (lajava): An anonymous box must not be used to resolve children's auto
  // values.
  childStyle.setAlignItems(style()->alignItems());
  childStyle.setAlignContent(style()->alignContent());
}

This results in something like the following :

div span {
  display: flex;
  text-align: center; 
  min-width: 0px;
  flex-grow: 1;
  justify-content: center;
  cursor: default;
  margin: 0 auto;
  height: 100%;
  align-items: center;
  align-content: center;
}

Once you encapsulate the div content within that span and implement the style, you should achieve the desired effect. While all these rules may not be essential or completely accurate, the outcome seems satisfactory:

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
  float: left;
}
div span {
  display: flex;
  text-align: center;
  min-width: 0px;
  flex-grow: 1;
  justify-content: center;
  cursor: default;
  margin: 0 auto;
  width: 100%;
  height: 100%;
  align-items: center;
  align-content: center;
}
<div><span>text text</span>
</div>
<button>text text</button>

<div><span>text text text text</span>
</div>
<button>text text text text</button>

<div><span>text text text text text text</span>
</div>
<button>text text text text text text</button>

Answer №3

Consider the options below for a possible solution:

Potential Solution #1

To center text vertically, add the following to the div style:

display: table-cell;

vertical-align: middle;

If you prefer using inline-block display, create a nested div structure with the parent div as (inline-block) and the child div as (table-cell) for centering the text.

Potential Solution #2

You can dynamically adjust the div padding and line height using jQuery to accommodate different content sizes within the div at runtime. For more information, refer to this question jquery set line-height equal to parent container height

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Propelling Information using the Chakra-UI Drawer Element

I've been exploring the features of the Chakra-UI drawer component and you can find more information about it here. Overall, the functionality aligns with my needs, except for one particular aspect - instead of pushing the content to the side, the dra ...

Update the division by clicking the button with a randomly generated JavaScript string element

Trying to solve a unique problem here as none of the proposed solutions on similar questions have worked for me. Apologies if I'm missing something, I'm new at this. The issue is with loading an empty div on my page using javascript and strings ...

Enhancing CSS with Additional Properties

As a web developer, I recently had the opportunity to explore the new LOGIN PAGE preview of GMAIL and was very impressed with the Sign In button's UI. After examining the Page's CSS, I discovered some interesting properties, such as: **backgroun ...

Form tag abruptly disappears in Chrome inspector

As I delved into someone's .asp code, I stumbled upon a concerning discovery - an unclosed HTML tag. To unravel this mystery, I turned to Chrome and its inspector tool only to find the missing tag right there in front of me! Puzzled, I returned to th ...

Ways to display an image overlay on hover using sprite sheets

Is there a way to make a line appear, around 10px in size, when hovering over an image at the bottom of that image? I came across this effect on MTV's website within their "You would also like these" section below each post. They utilized css-backgro ...

`The logo does not dim when the popup is displayed`

I'm currently experiencing an issue with pop-ups on my page - when they appear, they create a shade over all elements of the page except for my two logos and are displayed with a border around them. Here's what my page looks like before the popu ...

Participants will utilize functions to predict a number between 1 and 1000

I am currently working on a project that involves creating a number guessing game for the user. The idea is to have the program generate a random number between 1 and 1000, and then prompt the user to guess the number. If the guess is too low or too high ...

Ionic app encounters issue fetching local JSON data

I have been working on my Ionic application and I encountered an issue when trying to load local JSON data into it. I set up a http.get in my javascript to retrieve the data, but for some reason it's not showing up in the application. It seems like th ...

What is the best way to use HTML and CSS to center images and headings on a webpage?

This task is really testing my patience... I'm attempting to create a layout that resembles the following: Logo img|h1|img The horizontal lines flanking the subtitle serve as a visual guide, like this --- Subtitle --- Below is the snippet of H ...

Guide to declaring variables using jQuery

Currently tackling a school project, I stumbled upon some online example solutions and managed to decipher most of the code. However, there is one line that has me puzzled. var $newTweet = $('<div class=tweet></div>'); My assumption ...

In the event of a 404 error, simply direct the user to the pageNotFound before ultimately guiding them back

I'm developing a website with Node JS and I want to implement a feature where if the user attempts to navigate to a non-existent page, they are redirected to a "Page Not Found" message before being automatically taken back to the home page after a few ...

How come certain rectangles vanish when one rectangle completely fills the space?

Currently, I am encountering an issue with CSS paint worklet and I am trying to determine if it's a browser bug or an error on my end. In the worklet, I am drawing multiple rectangles. Strangely, when one rectangle covers the entire area, the others s ...

What is the best way to incorporate text animation into a website using Cascading Style Sheets (CSS)?

Is there a way to make my text flash twice per second? I attempted to create animated text, but it didn't work out! ...

Front Page Luma Design for Magento Platform

As a newcomer to Magento, I am currently using the Luma Home Page which appears blank. My goal is to incorporate an image that spans the entire browser viewport. Is it possible to achieve this through the admin panel by adjusting the CSS within the home pa ...

Hover effect on a single cell in a Bootstrap table

As I was working on creating a calendar design, I found myself pondering how to incorporate a hover effect using Bootstrap 4 for the cells. Here is a preview of the current calendar design I am aiming to achieve a hover effect similar to Bootstrap's ...

Encountering the error message "Unable to access property 'addEventListener' of null while trying to manipulate innerHTML"

Currently, I am utilizing innerHTML to include certain elements and a wrapper around them. for (i = 0; i < arr.length; i++) { b.innerHTML += "<div class='wrapper'><div class='col-4'>" + arr[i].storeID + "</div> ...

How can you trigger an event when a table cell is selected and a key is pressed?

In my project, I have some td elements with a class name assigned to them. My goal is to trigger a pop-up window when one of these td elements is in focus and the F9 key is pressed. Here's what I've attempted so far: $(document.body).keypress(fu ...

A concise way to write an else if statement in Javascript and jQuery

Is there a way to make this code more concise? It works perfectly fine, but it's too lengthy. Basically, the code involves two dropdown lists where the user selects options, and based on their selection, values appear in two textboxes. The catch is th ...

resizing videos in wordpress

Similar Question: How to Resize Embedded Videos Using PHP I am looking to adjust the dimensions of videos to be 280 pixels in height and 520 pixels in width on my WordPress homepage. Currently, the code is using the original YouTube dimensions: ...

The issue with height percentages being ineffective in CSS

My goal is to utilize the height property with percentages, however it seems to be ineffective. I desire to use percentages so that the layout appears well in various resolutions. <div id="bloque_1" style="height: 80%;background: red"> </div> ...