Flex / Grid布局不适用于按钮或字段集元素


91

我正在尝试将<button>-tag的内部元素与flexbox的居中对齐justify-content: center。但是Safari不会将它们居中。我可以将相同的样式应用于任何其他标签,并且可以按预期工作(请参见<p>-tag)。仅按钮左对齐。

尝试使用Firefox或Chrome,您会发现其中的区别。

有什么我必须覆盖的用户代理样式?或对此问题有其他解决方案?

div {
  display: flex;
  flex-direction: column;
  width: 100%;
}
button, p {
  display: flex;
  flex-direction: row;
  justify-content: center;
}
<div>
  <button>
    <span>Test</span>
    <span>Test</span>
  </button>
  <p>
    <span>Test</span>
    <span>Test</span>
  </p>
</div>

和jsfiddle:http//jsfiddle.net/z3sfwtn2/2/


Answers:


132

问题

在某些浏览器中,除了在和之间切换外,该<button>元素不接受对其display值的更改。这意味着元素不能是flex或grid容器,也不能是a 。blockinline-block<button><table>

除了<button>元素之外,您可能还会发现此约束也适用于<fieldset><legend>元素。

有关更多详细信息,请参见下面的错误报告。

注意:虽然它们不能是弹性容器,但是<button>元素可以是弹性项目。


解决方案

有一个简单易用的跨浏览器解决方案来解决此问题:

包裹的内容buttonspan,使span柔性容器。

调整后的HTML(button位于中的包装内容span

<div>
    <button>
        <span><!-- using a div also works but is not valid HTML -->
            <span>Test</span>
            <span>Test</span>
        </span>
    </button>
    <p>
        <span>Test</span>
        <span>Test</span>
    </p>
</div>

调整后的CSS(定位的span

button > span, p {
    display: flex;
    flex-direction: row;
    justify-content: center;
}

修改后的演示


参考/错误报告

Flexbox会<button>阻止内容,但不会建立Flex格式化上下文

用户(Oriol Brufau):的子级已<button>被屏蔽,因为它指定了flexbox规范。但是,<button>似乎建立了一个块格式化上下文而不是一个flex上下文。

用户(Daniel Holbert):实际上,这是HTML规范所要求的。几个HTML容器元素是“特殊的”,并且display在Gecko中有效地忽略了它们的CSS值(除了是内联级别还是块级别)。<button>是其中之一。<fieldset><legend>也是如此。

添加支持显示:内弯曲/网格和columnset布局<button>元素

用户(Daniel Holbert):

<button>不能在纯CSS中实现(通过浏览器),因此从CSS的角度来看,它们有点黑盒子。这意味着它们不一定以与例如a <div> 。相同的方式做出反应。

这不是特定于flexbox的-例如,如果您放置overflow:scroll按钮,则不会渲染滚动条,如果您放置按钮,则不会渲染为表格display:table

向后退一步,这不是特定于的<button>。考虑<fieldset><table>具有特殊的渲染行为。

而带点儿怀旧HTML元素,如<button><table><fieldset>根本不支持自定义display值,比回答的非常高级的问题的目的,其他的“是该元素的块级或行内”,该元素周围流动等内容。

另请参阅:


3
我知道为什么它可能不适用于<button>s,但为什么它实际上也不适用于s <fieldset>?不应将该元素视为对flex容器有效的常规块级元素吗?
fritzmg

3
@fritzmg。同意 该规则可能预先存在CSS3技术,例如Flex和Grid,应该重新评估。
迈克尔·本杰明

因此,我们希望防止按钮被滥用...但是仍然可以滥用其他东西并将其放置在按钮内部。听起来和其他网站一样逻辑……
Romain Vincent

1
@Michael_B考虑在创建断言的地方添加对实际文本的引用。无需回复我的评论-如果您将其添加到声明的文本中,我会给您赞成。
mikemaccana

2
Adiv不能是a的子button元素,因为如果您在老式HTML中想到它,则块级元素不能是内联级元素的子元素。但今天,随着HTML5,技术上正确的答案是,一个button元素只能接受段落式内容。Aspan表示短语内容,而adiv则不。Adiv代表流程内容更多详细信息
Michael Benjamin


1

从Chrome 83开始,button现在的工作方式为inline-grid/grid/inline-flex/flex,您可以在此处查看有关此新功能的更多信息

这是一个代码段(适用于使用Chrome 83及更高版本的用户)

button {
  display: inline-flex;
  height: 2rem;
  align-items: flex-end;
  width: 4rem;
  -webkit-appearance: none;
  justify-content: flex-end;
}
<!-- 

The align-items keyword should fail in Chrome 81 or earlier, but work in Chrome 83 or later. To see the error, the button needs styles that make it more of an extrinsic container. In other words, it needs a height or width set. 
 
-->
<button>Hi</button>
<input type="button" value="Hi">

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.