What makes the text on a button element vertically centered?
I know this is a couple of years old, but I'll add my thoughts after some investigation in to issue while writing a reset stylesheet for a project.
NOTE** This is based on looking through the Firefox source because it was the easiest to obtain and read through. However, based on similar behaviour in other browsers the implementation is probably similar.
Firstly, the main issue here is that <button>
elements - atleast in Firefox - are built with an internal element between the <button>
tag and it's children. In Firefox it's called moz-button-content
and isn't something that can be reached with CSS and has been set to display block without inheriting the height of the button, you can see this style declaration in the useragent stylesheet:
From "source/layout/style/res/forms.css"
*|*::-moz-button-content {
display: block;
/* Please keep the Multicol/Flex/Grid/Align sections below in sync with
::-moz-scrolled-content in ua.css and ::-moz-fieldset-content above. */
/* Multicol container */
-moz-column-count: inherit;
-moz-column-width: inherit;
-moz-column-gap: inherit;
-moz-column-rule: inherit;
-moz-column-fill: inherit;
/* Flex container */
flex-direction: inherit;
flex-wrap: inherit;
/* -webkit-box container (aliased from -webkit versions to -moz versions) */
-moz-box-orient: inherit;
-moz-box-direction: inherit;
-moz-box-pack: inherit;
-moz-box-align: inherit;
/* Grid container */
grid-auto-columns: inherit;
grid-auto-rows: inherit;
grid-auto-flow: inherit;
grid-column-gap: inherit;
grid-row-gap: inherit;
grid-template-areas: inherit;
grid-template-columns: inherit;
grid-template-rows: inherit;
/* CSS Align */
align-content: inherit;
align-items: inherit;
justify-content: inherit;
justify-items: inherit;
}
Because you can't affect any of the styles on this element, you are forced to add you styling on the <button>
tags. This leads into the second issue - The browser is hard coded to vertically position the content of the button.
From "source/layout/forms/nsHTMLButtonControlFrame.cpp"
// Center child in the block-direction in the button
// (technically, inside of the button's focus-padding area)
nscoord extraSpace =
buttonContentBox.BSize(wm) - contentsDesiredSize.BSize(wm);
childPos.B(wm) = std::max(0, extraSpace / 2);
// Adjust childPos.B() to be in terms of the button's frame-rect:
childPos.B(wm) += clbp.BStart(wm);
nsSize containerSize = (buttonContentBox + clbp.Size(wm)).GetPhysicalSize(wm);
// Place the child
FinishReflowChild(aFirstKid, aPresContext, contentsDesiredSize,
&contentsReflowInput, wm, childPos, containerSize,
ReflowChildFlags::Default);
Given these two issues you can start to see how the button force the content to be centered, consider:
<button> tag
+------------------------+ ^
| button extra space | |
| | |
+------------------------+ |
|| ::moz-button-content || | button height
|| display: block; || |
+------------------------+ |
| | |
| button extra space | |
+------------------------+ v
If you give the button
a height - like the 48px
from your fiddle, the text will be centered because the moz-button-content
element is display block and will only have the height of the content (most likely the line-height of the content by default) and when put next to another element you get this behaviour:
* { box-sizing: border-box; margin: 0; border: 0; padding: 0; font-family: san-serif; background: none; font-size: 1em; line-height:1; vertical-align: baseline; }
button, a { height: 3em;}
button { background: red;}
a { display:inline-block; background: green; }
<button>Button content</button><a>Link Content</a>
Why is the text in a button always centered vertically?
TL;DR: It is not possible to recreate the layout created by a <button>
element using CSS. Or at least it is hidden really well.
I tested this by changing the display value to flex on a <button>
and it affected the vertical alignment. Other values like display:block
did not have an effect. It seems that there is no css value for this, it just is the default behavior and there is no way to do it for a div.
Like you, I was looking for an answer to this question. I was trying to find css property which centers vertically content in button. When I almost gave up I decided to leaf through html specification and this is what I found:
If the element is an input element, or if it is a button element and
its computed value for 'display' is not 'inline-grid', 'grid',
'inline-flex', or 'flex', then the element's box has a child anonymous
button content box with the following behaviors:
- The box is a block-level block container that establishes a new
block formatting context (i.e., 'display' is 'flow-root').- If the box does not overflow in the horizontal axis, then it is
centered horizontally.- If the box does not overflow in the vertical axis, then it is
centered vertically. Otherwise, there is no anonymous button content box.
https://html.spec.whatwg.org/multipage/rendering.html#button-layout
How to make the text vertical center in the button?
Since button
element does that by default, just drop the line-height
.
why the text don't locate in the vertical center
If you are gonna use line height, and as the button have a 2px border and not using border-box, the line height needs to be 36px.
I also added an anchor a
element as a comparison.
.content { width: 900px; margin: 0 auto; text-align: center; margin-bottom: 10px;}.content .btn { width: 120px; height: 40px; color: white;}
.content .btn2 { width: 120px; height: 40px; line-height: 36px; color: white;}
.content a.btn { display: inline-block; width: 120px; height: 36px; line-height: 36px; border: 2px outset; color: white;}
.content .btn-teacher { background-color: rgb(120, 144, 156);}.content .btn-student { background-color: rgb(255, 112, 67);}
<body> <div class="content"> <button class="btn btn-teacher">I am a teacher</button> <button class="btn btn-student">I am a student</button> </div>
<div class="content"> <button class="btn2 btn-teacher">I am a teacher</button> <button class="btn2 btn-student">I am a student</button> </div>
<div class="content"> <a class="btn btn-teacher">I am a teacher</a> <a class="btn btn-student">I am a student</a> </div></body>
How to vertically center a button and text inside a div
Weave: http://kodeweave.sourceforge.net/editor/#0def3ea11664636810328b98a8780ed2
You didn't post your css so I don't know what you're working with. So here's a quick note:
NOTE: vertical-align
only works for display: table-cell;
and display: inline;
elements (It also applies to ::first-letter and ::first-line).
Here's a simple solution using display: table;
on the parent and display: table-cell;
for what you want vertically centered.
If you want your button centered you have to remove the pull-right
class, or you can add another class after it and then override it's css. (Simple solution, just remove the pull-right
class.
Edit: So you want the button in the same line as your h3 tag right?
Well before I show you how to solve this remember that h1-h5 tags are all display: block;
elements meaning they will always embed as a new line. (Like a paragraph <p> tag) So you need to tell the h3 tag to display either inline
or inline-block
.
Here is my revised weave: http://kodeweave.sourceforge.net/editor/#7b9839fb7971df2a27b7af895169ad8a
html, body { height: 100%;}
.table { display: table; width: 100%; height: 100%;} .cell { display: table-cell; vertical-align: middle;}
h3 { display: inline-block;}
.btn { margin-top: 15px;}
<script src="http://code.jquery.com/jquery.min.js"></script><script src="http://getbootstrap.com/dist/js/bootstrap.js"></script><link rel="stylesheet" href="http://getbootstrap.com/dist/css/bootstrap.css"/>
<div class="container table"> <div class="page-header cell"> <h3>HEADING</h3> <button class="btn btn-danger pull-right">Button</button> </div></div>
Which magic CSS causes the difference of text-vertical-align between button and div ?
If you look at Chrome source code you can kind of see how it works, at least for Chrome. It seems there's an anonymous flex box created with a specific style applied. It's not that straightforward — at least not for me — but still, you can deduce what style is applied to this anonymous element. You can see here:
https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/layout/LayoutButton.cpp?sq=package:chromium
The interesting part:
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 gives something like this :
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;
}
Then you just need to wrap the div content in that span and apply the style. All these rules are probably not all necessary or accurate but the result seems ok:
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>
Related Topics
How to Make a Chevron Arrow Using CSS
Why Does Overflow Hidden Stop Floating Elements Escaping Their Container
Audio Tag Autoplay Not Working in Mobile
How to Convert Screen Coordinates to Document Space in a Scaled Svg
How to Create a Hidden Div That Doesn't Create a Line Break or Horizontal Space
How to Hide Drop Down Arrow in IE8 & IE9
How to Force a Download File Prompt Instead of Displaying It In-Browser with HTML
Webgl: Prevent Color Buffer from Being Cleared
Html5 - Mp4 Video Does Not Play in IE9
Why Should I Not Use HTML Frames
Pure CSS Chessboard with Div & No Classes or Ids, Is It Possible
How to Remove Focus Around Buttons on Click
How to Show Multiline Text in a Table Cell
File Url "Not Allowed to Load Local Resource" in the Internet Browser