【问题标题】:Flex / Grid layouts not working on button or fieldset elementsFlex / Grid 布局不适用于按钮或字段集元素
【发布时间】:2016-05-29 14:12:30
【问题描述】:

我正在尝试将 <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/

【问题讨论】:

标签: html css safari flexbox css-grid


【解决方案1】:

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

这是一个 sn-p(适用于使用 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">

【讨论】:

    【解决方案2】:

    问题

    在某些浏览器中,&lt;button&gt; 元素不接受对其display 值的更改,除了在blockinline-block 之间切换。这意味着 &lt;button&gt; 元素不能是 flex 或网格容器,也不能是 &lt;table&gt;

    除了&lt;button&gt; 元素之外,您可能会发现此约束也适用于&lt;fieldset&gt;&lt;legend&gt; 元素。

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

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


    解决方案

    有一个简单易用的跨浏览器解决方法:

    button 的内容包装在span 中,并使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;
    }
    

    Revised Demo


    参考/错误报告

    Flexbox on a &lt;button&gt; blockifies the contents but doesn't establish a flex formatting context

    用户(Oriol Brufau):&lt;button&gt; 的子代被阻塞,正如 flexbox 规范所规定的那样。但是,&lt;button&gt; 似乎建立了块格式化上下文而不是弹性上下文。

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

    Add support for display:flex/grid and columnset layout inside &lt;button&gt; elements

    用户(丹尼尔·霍尔伯特):

    &lt;button&gt; 不能在纯 CSS 中实现(由浏览器实现),因此从 CSS 的角度来看,它们有点像黑盒子。这意味着 他们不一定以相同的方式做出反应,例如&lt;div&gt; 会。

    这不是 flexbox 特有的——例如如果您将overflow:scroll 放在按钮上,我们不会渲染滚动条,并且我们不会将其渲染为 如果你把display:table放在桌子上。

    退一步说,这并不特定于&lt;button&gt;。考虑&lt;fieldset&gt;&lt;table&gt;,它们也有特殊的渲染 行为。

    &lt;button&gt;&lt;table&gt;&lt;fieldset&gt; 这样的老式 HTML 元素根本不支持自定义 display 值,除了 为了回答“这是 元素块级或内联级”,用于流动其他内容 元素。

    另见:

    【讨论】:

    • 我明白为什么它可能不适用于&lt;button&gt;s,但到底为什么它也不适用于&lt;fieldset&gt;?该元素不应该被视为对弹性容器有效的常规块级元素吗?
    • @fritzmg。同意。该规则可能预先存在 CSS3 技术,例如 Flex 和 Grid,应该重新评估。
    • 所以我们想防止按钮被误用......但仍然可能误用其他东西并将其放在按钮内。听起来和网络的其他部分一样合乎逻辑......
    • @Michael_B 考虑添加对您做出断言的实际文本的引用。无需回复我的评论 - 如果您将其添加到您做出断言的文本中,我会给您一个赞成票。
    • A div 不能是 button 的子元素,因为如果您在老式 HTML 中考虑它,块级元素不能是内联元素的子元素级元素。但是今天,对于 HTML5,技术上正确的答案是 a button element can only accept Phrasing Contentspan 代表 短语内容,但 div 不代表。 div 代表 流内容More details
    【解决方案3】:

    这是我最简单的 hack。

    button::before,
    button::after {
        content: '';
        flex: 1 0 auto;
    }
    

    【讨论】:

    猜你喜欢
    相关资源
    最近更新 更多