我知道这已经有几年的历史了,但我会在为项目编写重置样式表时对问题进行一些调查后添加我的想法。
注意**这是基于浏览 Firefox 源代码,因为它是最容易获得和阅读的。但是,基于其他浏览器中的类似行为,实现可能是相似的。
首先,这里的主要问题是 <button> 元素 - 至少在 Firefox 中 - 是在 <button> 标记和它的子标记之间使用内部元素构建的。在 Firefox 中,它被称为 moz-button-content,它不是 CSS 可以达到的,并且已设置为显示块而不继承按钮的高度,您可以在 useragent stylesheet 中看到此样式声明:
来自“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;
}
因为你不能影响这个元素的任何样式,你不得不在<button>标签上添加你的样式。这就引出了第二个问题——浏览器是hard coded to vertically position按钮的内容。
来自“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);
鉴于这两个问题,您可以开始了解按钮如何强制内容居中,请考虑:
<button> tag
+------------------------+ ^
| button extra space | |
| | |
+------------------------+ |
|| ::moz-button-content || | button height
|| display: block; || |
+------------------------+ |
| | |
| button extra space | |
+------------------------+ v
如果你给button 一个高度 - 就像你的小提琴中的48px 一样,文本将居中,因为moz-button-content 元素是显示块并且只有内容的高度(很可能是行- 默认情况下内容的高度),当放在另一个元素旁边时,您会得到这种行为:
* {
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>
Firefox 问题跟踪器中的This bug 和this bug 几乎接近我可以找到的任何实际记录的错误。但是线程给人的印象是,尽管这没有出现在任何实际规范中,但浏览器只是以这种方式实现了它,“因为其他浏览器正在这样做”
如果您确实想更改默认行为,可以解决此问题,但它并不能完全解决问题和 YMMV,具体取决于您的实现。
如果您插入一个包装器<span> 并将display: block 作为按钮的唯一子级并将所有内容放入其中,您可以使用它来跳过moz-button-content 元素。
您需要使这个<span> 元素具有height: inherit,以便它正确地填充按钮的高度,然后将您的正常按钮样式添加到<span>,您将获得您想要的基本行为。
* {
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;
}
button::-moz-focus-inner {
border: 0;
padding: 0;
outline: 0;
}
button > span {
display: block;
height: inherit;
}
a {
display:inline-block;
background: green;
}
button.styled > span , a.styled{
padding: 10px;
background: yellow;
}
<button><span>Button content</span></button>
<a><span>Link Content<span></a><br/>
<button class="styled"><span>Button content</span></button>
<a class="styled"><span>Link Content<span></a>
还值得一提的是appearance CSS4 规则(尚不可用):
虽然这不是一个可行的选择(截至 1 月 5 日)。有一个提议重新定义 CSS4 草案中的appearance 规则,这实际上可能会做正确的事情,即删除浏览器所做的所有假设。我只是为了完整性而提及它,因为它将来可能会变得有用。
更新 - 2016 年 8 月 30 日
您实际上应该使用<span> 而不是<div>,因为div 不是<button> 元素的有效子代。我已经更新了答案以反映这一点。