web-dev-qa-db-ja.com

フレックスアイテムの幅と高さがフレックスアイテムのレンダリング方法に影響するのはなぜですか?

flexboxの画像にmax-heightスタイルは、heightおよびwidth属性が設定されているかどうかに応じて異なるように表示されます。

属性のあるwithは、画像の真の幅/高さに設定され、アスペクト比を保持してレンダリングされますが、属性のないものはmax-heightと押しつぶされて表示されます。

.flex-parent {
  display: flex;
  max-height: 10vh;
}
<div class="flex-parent">
  <img                          src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

これは、Chrome 58(およびFirefox 54でも同様に表示されます)に表示される方法です。

Different rendering of img in flexbox. Without width and height attributes, and with

なぜ異なるレンダリングをするのですか?この動作を支配するルールは何ですか?

私の(明らかに間違っている)理解は、高さと幅の属性が画像の読み込み時に見つかった固有の高さと幅を上書きすることであり、高さと幅の属性が画像の寸法と等しい場合、一度画像をレンダリングすると違いはないはずですロードしました。

コンテキストはレスポンシブ画像を含むページを作成しています。各画像は

  • 一意の元の寸法を持つことができます
  • ロード時にリフローは発生しません。つまり、最初のレンダリングで正しいスペースが確保されます(したがって、高さと幅の属性を使用します)
  • すべてを一度に画面に収めることができます(CSSでvhをいじります)

カエルの画像は https://en.wikipedia.org/wiki/File:Red_eyed_tree_frog_edit2.jpg からのものです

37
Michal Charemza

フレックスコンテナの初期設定は align-items: stretch です。

つまり、フレックスアイテムは、コンテナの cross axis を超えて展開されます。

問題のように、行方向のコンテナでは、交差軸は垂直です。

つまり、アイテム(この場合は画像)はコンテナの高さ全体をカバーします。

ただし、フレックスアイテムにクロスサイズが定義されている場合、stretchデフォルトがオーバーライドされます。

仕様から:

8.3。クロス軸アライメント:align-itemsおよびalign-selfプロパティ

フレックスアイテムは、justify-contentに似ていますが、垂直方向に、フレックスコンテナの現在の行の交差軸に配置できます。

stretch

フレックスアイテムのクロスサイズプロパティがautoに計算され、クロス軸マージンのいずれもautoでない場合、フレックスアイテムは引き伸ばされます。

これが主要な言語です。

フレックスアイテムのクロスサイズプロパティがautoに計算される場合

そして、これは仕様が「クロスサイズプロパティ」を定義する方法です。

フレックスアイテムの幅または高さのいずれかがクロスディメンションのいずれかである場合、アイテムのクロスサイズです。 cross size propertyは、widthまたはheightのいずれかであり、クロス次元にあります。

https://www.w3.org/TR/css-flexbox-1/#cross-size-property


そのため、仕様で定義されているとおりにコードが再生されているように見えます。

これはあなたが持っているものです:

.flex-parent {
  display: flex;
  max-height: 10vh;
}
<div class="flex-parent">
  <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>

最初の画像には、CSSまたはHTMLで定義された幅(メインサイズ)または高さ(クロスサイズ)がありません。したがって、そのクロスサイズはautoに計算されます。

この文:

フレックスアイテムのクロスサイズプロパティがautoに計算される場合

...が真であり、align-items: stretchが有効になります。

画像は、コンテナの高さである10ピクセルに拡大されます。

ただし、2番目のイメージには明示的なサイズ設定があります。クロスサイズは、HTMLで定義されています(height="240")。

今、このステートメント:

フレックスアイテムのクロスサイズプロパティがautoに計算される場合

...はfalseであり、align-items: stretchはオーバーライドされます。 HTML height属性が優先されます。

2番目の画像に関する2つのメモ:

  1. CSSの初期設定は max-height であるため、イメージはコンテナのoverflow: visible制限を無視します。
  2. HTMLのwidthおよびheight属性は、それぞれのCSSプロパティにマップします。したがって、height="240"height: autoデフォルトをオーバーライドします。仕様の参照については、以下を参照してください。*

Flexコンテナで画像をレンダリングする際に考慮すべき問題が2つあります。

  1. フレックスアイテムのデフォルトの最小サイズ。この設定により、フレックスアイテムがコンテンツのサイズ以下に縮小するのを防ぎます。詳細については、この投稿をお読みください。

  2. 主要なブラウザー間でのさまざまな動作。 Firefox、Chrome、Safari、Edge、およびIE11は、必ずしも同じ方法で画像をフレックスアイテムとしてレンダリングするとは限りません。詳細については、この投稿をお読みください。


上記のすべての要因を考慮して、ここに私の提案する解決策があります:

.flex-parent {
  display: flex;
  max-height: 50vh; /* adjusted for demo */
}

.flex-parent {
  min-width: 0;
}

img {
  width: 100%;
  height: auto;
}
<div class="flex-parent">
  <div>
    <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  </div>
  <div>
    <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  </div>
</div>

*HTML widthおよびheight属性は、それぞれのCSSプロパティにマッピングされます。したがって、指定されると、CSSのデフォルトがオーバーライドされます。 HTML5仕様から:

10.4.3埋め込みコンテンツおよび画像の属性

widthheightappletembed、またはiframeobjectおよびvideo属性要素、およびImage Button状態のinput属性を持つtype要素で、画像を表すか、またはユーザーが最終的に画像を表すと期待する次元へのマップproperties要素のwidthおよびheight

10.2 CSSユーザーエージェントスタイルシートとプレゼンテーションヒント

以下のテキストで、要素の属性がディメンションプロパティ(またはプロパティ)にマッピングされている場合、要素に属性セットがあり、-を使用してその属性の値を解析することを意味します。 ディメンション値を解析するためのルール はエラーを生成せず、ユーザーエージェントは、解析されたディメンションをプロパティの値として使用することが期待されます プレゼンテーションヒント 指定された値ディメンションが整数の場合はピクセル長として、ディメンションがパーセンテージの場合はパーセンテージで値が指定されます。

35
Michael_B

W3c flexbox specsを読んで、 this につまずいた。

各ディメンションについて、フレックスコンテナのコンテンツボックスのそのディメンションが明確なサイズである場合、それを使用します。 flexコンテナのその次元が最小または最大コンテンツ制約の下でサイズ変更されている場合、その次元で利用可能なスペースはその制約です。

それ以外の場合は、そのディメンションのフレックスコンテナで使用可能なスペースからフレックスコンテナのマージン、境界線、およびパディングを差し引き、その値を使用して、無限値になる可能性があります。

お役に立てれば。

3
Eggineer

ここでは、max-height:10vhを記述しました。vhは、最新のiOS 6以外のブラウザーではサポートしていません。これは、ビューポートに関連するすべての長さの単位に当てはまります。 Vhの代わりに他の値を使用すると、これで問題なく動作します。このブログをお読みください https://css-tricks.com/the-lengths-of-css/

.flex-parent {
  display: flex;
  max-height:  max-content;
}
<div class="flex-parent">
  <img                          src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
  <img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
2

問題は、max-heightを設定する場所です。 cssプロパティmax-heightはデフォルトでは継承されません。 css宣言は、ビューポートの高さの10%のdivを作成します。寸法が設定されていない画像は、その親寸法に基づいて縮小されます。暗黙の寸法を設定した画像は、常にそれらの寸法になります。 divのサイズによっては、オーバーフローする場合があります。最初の画像にmax-heightプロパティを設定すると、アスペクト比を同じに保ちながらサイズを変更する必要があります。

0
Philip Tinney