フレックス/グリッドレイアウトがボタンまたはフィールドセット要素で機能しない


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/


回答:


132

問題

一部のブラウザでは、<button>要素はとのdisplay切り替え以外に、値の変更を受け入れません。これは、要素がフレックスまたはグリッドコンテナ、あるいはのいずれにもなり得ないことを意味します。blockinline-block<button><table>

加え<button>要素は、これに適用する制約見つけること<fieldset><legend>同様に、要素を。

詳細については、以下のバグレポートを参照してください。

注:フレックスコンテナにすることはできませんが、<button>要素はフレックスアイテムにすることができます。


ソリューション

この問題には、シンプルで簡単なクロスブラウザーの回避策があります。

内容ラップ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;
}

改訂されたデモ


参考資料/バグレポート

ブロック上の<button>Flexboxはコンテンツをブロックしますが、フレックスフォーマットコンテキストを確立しません

ユーザー(Oriol Brufau):フレックスボックスの仕様に応じて、の子<button>はブロックされます。ただし、は<button>フレックスコンテキストではなくブロックフォーマットコンテキストを確立しているようです。

ユーザー(Daniel Holbert):それは事実上HTML仕様が要求するものです。いくつかのHTMLコンテナ要素は「特別」でありdisplay、GeckoでのCSS値を事実上無視します[インラインレベルかブロックレベルかは別として]。<button>これらの1つです。<fieldset><legend>も同様です。

<button>要素内のdisplay:flex / gridおよびcolumnsetレイアウトのサポートを追加します

ユーザー(Daniel Holbert):

<button>純粋なCSSでは(ブラウザーでは)実装できないため、CSSの観点からは少しブラックボックスになっています。これは、彼らが必ずしも同じように反応するとは限らないことを意味し<div> ます。

これはフレックスボックスに固有のものではありません。たとえばoverflow:scroll、ボタンを配置した場合はスクロールバーをレンダリングせず、ボタンを配置した場合はテーブルとしてレンダリングしませんdisplay:table

さらに一歩下がると、これはに固有のものではありません<button>。考えてみましょう<fieldset><table>これも特殊なレンダリング挙動を有します。

など古いtimey HTML要素<button><table>し、<fieldset>単にカスタムサポートしていないdisplay要素の周りに他のコンテンツを流すため、「この要素をブロックレベルやインラインレベルである」のは非常に高レベルの質問に答えるの目的以外の値を、 。

参照:


3
なぜそれが<button>sで機能し<fieldset>ないのかわかりますが、一体なぜそれも機能しないのですか?その要素は、フレックスコンテナに有効な通常のブロックレベルの要素と見なされるべきではありませんか?
fritzmg 2018

3
@fritzmg。同意しました。このルールは、おそらくFlexやGridなどのCSS3テクノロジーがすでに存在しているため、再評価する必要があります。
Michael Benjamin

そのため、ボタンの誤用を防ぎたいのですが、それでも他の何かを誤用してボタンの内側に配置する可能性があります。ウェブの他の部分とロジックの約音...
ロマン・ヴィンセント

1
@Michael_Bアサーションを作成する実際のテキストへの参照を追加することを検討してください。私のコメントに返信する必要はありません-あなたが主張をするテキストにそれを追加するならば、私はあなたに賛成票を与えます。
mikemaccana

2
div子になることはできませんbuttonあなたは古い学校のHTMLでそれを考える場合には、ブロックレベル要素がインラインレベル要素の子になることはできません、ので。しかし、今日のHTML5では、技術的に正しい答えはbutton要素はフレーズコンテンツのみを受け入れることができるということです。Aspanフレーズコンテンツを表しますが、adivはそうではありません。Adivフローコンテンツを表します。詳細
マイケル・ベンジャミン


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">

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.