web-dev-qa-db-ja.com

Chrome/SafariがFlexの親の100%の高さを満たしていない

特定の高さの縦型メニューが欲しいのですが。

それぞれの子供は親の身長を満たし、中央揃えのテキストを持っている必要があります。

子供の数はランダムなので、私は動的な値で作業しなければなりません。

Div .containerには、常に親の高さを埋める必要がある乱数の子(.item)が含まれています。それを達成するために私はflexboxを使いました。

テキストを中央に揃えてリンクを作成するために、私はdisplay: table-cell手法を使用しています。しかし、テーブルディスプレイを使用するには、高さ100%を使用する必要があります。

私の問題は.item-inner { height: 100% }がwebkit(Chrome)で動かないことです。

  1. この問題に対する修正はありますか?
  2. それとも、すべての.itemを親の高さいっぱいに垂直に中央揃えのテキストで埋めるという別のテクニックはありますか。

ここでの例jsFiddle、FirefoxとChromeで表示されるはずです

.container {
  height: 20em;
  display: flex;
  flex-direction: column;
  border: 5px solid black
}
.item {
  flex: 1;
  border-bottom: 1px solid white;
}
.item-inner {
  height: 100%;
  width: 100%;
  display: table;
}
a {
  background: orange;
  display: table-cell;
  vertical-align: middle;
}
<div class="container">
  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>
</div>
175

溶液

ネストされたフレックスコンテナを使用します。

パーセントの高さを取り除きます。テーブルのプロパティを取り除きます。 vertical-alignを取り除きます。絶対配置を避けてください。flexboxを最後までそのまま使用します。

display: flexをフレックスアイテム(.item)に適用し、フレックスコンテナにします。これにより、align-items: stretchが自動的に設定されます。これは、子(.item-inner)に親の全高を拡張するよう指示します。

重要:このメソッドが機能するには、指定された高さをflexアイテムから削除します。 子に高さが指定されている場合(height: 100%など)、親からのalign-items: stretchは無視されます。 stretchname__のデフォルトが機能するには、子供の身長がauto(完全な説明 )に計算される必要があります。

これを試してください(HTMLに変更はありません):

.container {
    display: flex;
    flex-direction: column;
    height: 20em;
    border: 5px solid black
}

.item {
    display: flex;                      /* new; nested flex container */
    flex: 1;
    border-bottom: 1px solid white;
}

.item-inner {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */

    /* height: 100%;                    <-- remove; unnecessary */
    /* width: 100%;                     <-- remove; unnecessary */
    /* display: table;                  <-- remove; unnecessary */  
}

a {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */
    align-items: center;                /* new; vertically center text */
    background: orange;

    /* display: table-cell;             <-- remove; unnecessary */
    /* vertical-align: middle;          <-- remove; unnecessary */
}
<div class="container">
  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>
</div>

jsFiddle demo


説明

私の問題は、.item-inner { height: 100% }がwebkit(Chrome)で機能していないことです。

仕様の従来の実装に準拠しない方法でパーセンテージの高さを使用しているため、機能していません。

10.5コンテンツの高さ:heightname__プロパティ

パーセント
高さのパーセンテージを指定します。割合は、生成されたボックスの包含ブロックの高さに対して計算されます。包含ブロックの高さが明示的に指定されておらず、この要素が絶対に配置されていない場合、値はautoname__に計算されます。

auto
高さは他のプロパティの値に依存します。

つまり、高さのパーセンテージがインフローの子で機能するためには、親のに高さを設定する必要があります。

コードでは、トップレベルコンテナの高さが定義されています:.container { height: 20em; }

第3レベルのコンテナには、定義された高さがあります:.item-inner { height: 100%; }

しかし、それらの間では、第2レベルのコンテナー-.item-にはは定義された高さを持ちません。 Webkitは、これをミッシングリンクと見なしています。

.item-innerはChromeに次のことを伝えています:height: 100%。 Chromeは、参照(.item)を参照して応答します:100%何ですか?何も表示されません(そこにあるflex: 1ルールを無視します)。その結果、仕様に従ってheight: auto(コンテンツの高さ)が適用されます。

一方、Firefoxは、子のパーセンテージの高さの参照として、親のフレックスの高さを受け入れるようになりました。 IE11およびEdgeは、フレックスの高さも受け入れます。

また、Chromeは、適切な親参照としてflex-growを受け入れますflex-basisと組み合わせて使用​​する場合(任意の数値が機能します( autoNAME _ はしません)、 flex-basis: 0を含む)。ただし、この記事の執筆時点では、このソリューションはSafariで失敗しています。

#outer {
  display: flex;
  flex-direction: column;
  height: 300px;
  background-color: white;
  border: 1px solid red;
}
#middle {
  flex-grow: 1;
  flex-basis: 1px;
  background-color: yellow;
}
#inner {
  height: 100%;
  background-color: lightgreen;
}
<div id="outer">
  <div id="middle">
    <div id="inner">
      INNER
    </div>
  </div>
</div>

4つのソリューション

1.すべての親要素の高さを指定します

信頼できるクロスブラウザソリューションは、すべての親要素の高さを指定することです。これにより、Webkitベースのブラウザーが仕様違反と見なすリンクの欠落を防ぎます。

min-heightおよびmax-heightは使用できないことに注意してください。 heightname__プロパティでなければなりません。

詳細はこちら: CSS heightname__プロパティとパーセンテージ値の操作

2. CSS相対&絶対配置

position: relativeを親に、position: absoluteを子に適用します。

height: 100%およびwidth: 100%を使用して子のサイズを設定するか、top: 0right: 0bottom: 0left: 0のオフセットプロパティを使用します。

絶対配置では、親の高さを指定しなくてもパーセント高さが機能します。

3.不要なHTMLコンテナを削除します(推奨)

buttonname__の周りに2つのコンテナが必要ですか? .itemまたは.item-inner、あるいはその両方を削除しないのはなぜですか? buttonname__要素はflex container として失敗することがありますが、それらはflexアイテムである可能性があります。 buttonname__を.containerまたは.itemの子にし、不要なマークアップを削除することを検討してください。

以下に例を示します。

.container {
    height: 20em;
    display: flex;
    flex-direction: column;
    border: 5px solid black
}

a {
    flex: 1;
    background: orange;
    border-bottom: 1px solid white;
    display: flex;                   /* nested flex container (for aligning text) */
    align-items: center;             /* center text vertically */
    justify-content: center;         /* center text horizontally */
}
<div class="container">
    <a>Button</a>
    <a>Button</a>
    <a>Button</a>
</div>

4.ネストされたFlexコンテナ(推奨)

パーセントの高さを取り除きます。テーブルのプロパティを取り除きます。 vertical-alignを取り除きます。絶対配置を避けてください。flexboxを最後までそのまま使用します。

display: flexをフレックスアイテム(.item)に適用し、フレックスコンテナにします。これにより、align-items: stretchが自動的に設定されます。これは、子(.item-inner)に親の全高を拡張するよう指示します。

重要:このメソッドが機能するには、指定された高さをflexアイテムから削除します。 子に高さが指定されている場合(height: 100%など)、親からのalign-items: stretchは無視されます。 stretchname__のデフォルトが機能するには、子供の身長がauto(完全な説明 )に計算される必要があります。

これを試してください(HTMLに変更はありません):

.container {
    display: flex;
    flex-direction: column;
    height: 20em;
    border: 5px solid black
}

.item {
    display: flex;                      /* new; nested flex container */
    flex: 1;
    border-bottom: 1px solid white;
}

.item-inner {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */

    /* height: 100%;                    <-- remove; unnecessary */
    /* width: 100%;                     <-- remove; unnecessary */
    /* display: table;                  <-- remove; unnecessary */  
}

a {
    display: flex;                      /* new; nested flex container */
    flex: 1;                            /* new */
    align-items: center;                /* new; vertically center text */
    background: orange;

    /* display: table-cell;             <-- remove; unnecessary */
    /* vertical-align: middle;          <-- remove; unnecessary */
}
<div class="container">
  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>

  <div class="item">
    <div class="item-inner">
      <a>Button</a>
    </div>
  </div>
</div>

jsFiddle

334
Michael_B

解決策: .item-inner height: 100%を削除し、 .item display: flexを追加してください。

デモ: https://codepen.io/tronghiep92/pen/NvzVoo

5
nghiepit

私はiOS 8、9および10で同様の問題を抱えていて、上記の情報はそれを修正することができませんでした、しかし私はこれに取り組んだ日の後に解決策を発見しました。それは誰にとってもうまくいかないことは確かだが、私の場合、私のアイテムは縦一列に積み上げられていて、コンテンツの高さでなければならないときには0の高さだった。 cssをrow and wrapに切り替えて問題を解決しました。これはあなたが単一のアイテムを持っていて、それらが積み重ねられている場合にのみ機能しますが、これを見つけるのに1日かかったので私は修正を共有するべきだと思いました!

.wrapper {
    flex-direction: column; // <-- Remove this line
    flex-direction: row; // <-- replace it with
    flex-wrap: wrap; // <-- Add wrapping
}

.item {
    width: 100%;
}
0
Designer023

Mobile Safariの場合ブラウザの修正があります。 iOSデバイスの場合は -webkit-box を追加する必要があります。

例.

display: flex;
display: -webkit-box;
flex-direction: column;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
align-items: stretch;

親要素にalign-items: stretch;プロパティを使用している場合は、子要素からheight : 100%を削除します。

0
Narasinghe