一尘不染

是什么使文字在 元素垂直居中?

css

似乎有一些<button>我不了解的魔术。

考虑以下标记:

<button class="button">Some Text</button>
<div class="button">Some Text</div>

而这个CSS:

.button{
    background: darkgrey;
    height: 40px;
    border: 2px solid grey;
    width: 100%;
    box-sizing: border-box;
    font-size: 14px;
    font-family: helvetica;
    text-align: center;
    margin-bottom: 20px;

    /*I'm aware I could use this to center it*/
    /*line-height: 40px;*/
}

是什么使按钮元素中的文本垂直居中?Webkit似乎预定义了-webkit-box- align一个值为center<button>元素。如果我将其设置为initial文本不再与中心对齐。但这似乎并不是全部的魔术,因为另一方面,我没有运气使用该-webkit-box-align属性将文本放在div的中心。


阅读 239

收藏
2020-05-16

共1个答案

一尘不染

我知道这已经有两年的历史了,但是我会在编写项目的重置样式表时进行一些调查后发表自己的看法。

注意**这是基于浏览Firefox源代码的,因为它是最容易获得和阅读的。 但是,基于其他浏览器中的相似行为,实现方式可能相似。

首先,这里的主要问题是,<button>至少在Firefox中的元素是使用<button>标记及其子元素之间的内部元素构建的。在Firefox中,它被称为moz-button-content并且不是CSS所能达到的,并且已设置为不继承按钮高度而显示为块,您可以在useragent样式表中看到此样式声明:

来自“ 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>标签上添加样式。这导致了第二个问题- 浏览器被
硬编码为垂直
放置
按钮的内容

来自“源/布局/表单/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>

此bug和这个bug在Firefox的问题跟踪是关于一个接近我能找到任何实际记录的缺陷。但是线程给人的印象是,尽管这在任何实际规范中都没有出现,但是浏览器只是以这种方式实现了“因为其他浏览器都以这种方式”


如果您确实要更改默认行为,则有一个解决方法,但是它不能完全解决问题,具体取决于您的实现。

如果插入的包装<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>

还值得一提的是CSS4 外观规则(尚不可用 ):

尽管这不是一个可行的选择(截至1月5日)。有人提议重新定义appearanceCSS4草案中的规则,该规则实际上可能会做正确的事情,从而消除浏览器所做的所有假设。我之所以仅提及完整性,是因为它将来可能会变得有用。

更新-30/08/2016 您实际上应该使用a <span>而不是a<div>,因为divs不是<button>元素的有效子代。我已经更新了答案以反映这一点。

2020-05-16