高さを変更しても画像のアスペクト比を維持する


114

CSSフレックスボックスモデルを使用して、画像の縦横比を維持するにはどうすればよいですか?

JSフィドル:http : //jsfiddle.net/xLc2Le0k/2/

コンテナの幅を満たすために、画像が伸縮することに注意してください。それは問題ありませんが、画像の縦横比を維持するために高さを伸縮させることもできますか

HTML

<div class="slider">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
</div>

CSS

.slider {
    display: flex;
}
.slider img {
    margin: 0 5px;
}

1
私の知る限り、最良の解決策は<div>CSSで使用することですbackground-image: url(...);background-size:contain; background-repeat:no-repeat
Blazemonger

1
ここにはいくつかの興味深いリードがありますが、画像がまだ同じ比率でない場合はどうでしょうか?追加および「追加」divは、私たちが心配する必要がある最後の事柄です。なぜ、代わりにこのようなテストケースを使用しない: jsfiddle.net/sheriffderek/999Lg9qv
sheriffderek

回答:


68

imgタグの場合、一方を定義すると、もう一方のサイズが変更されてアスペクト比が維持され、デフォルトで画像が元のサイズに拡大されます。

この事実を使用して、各imgタグをdivタグにラップし、その幅を親divの100%に設定すると、高さは希望どおりのアスペクト比になります。

http://jsfiddle.net/0o5tpbxg/

* {
    margin: 0;
    padding: 0;
}
.slider {
    display: flex;
}
.slider .slide img {
    width: 100%;
}

2
私はdivの使用を提案する2つの答えがあることを知っています、画像の高さが予想と異なる理由を説明しているので、この答えを正しくマークしています。実際、これは正常で正しい動作であり、バグではないため「修正」されることはほとんどありません。
coderMe 2015年

18
しかし、この答えはflexboxについては何も述べていません。これは、フレックスボックスコンテナ内では画像の動作が異なるためです。一方を設定しても、もう一方は比例してサイズ変更されません。それらを非flexboxコンテナーでラップすることは役立ちますが、不要なマークアップが追加され、セマンティクスが失われます。
Robert Koritnik 2016

3
これを機能させるためにラッピングdivが必要なようではありません:jsfiddle.net/xLc2Le0k/120
Rick Strahl

4
しかし、これはどうですか?jsfiddle.net/xLc2Le0k/15 このソリューションは、画像がすべて同じ比率であるためにのみ機能するフルークだと思います。補足:配置のために、特にレスポンシブな画像を扱う場合、画像をdivに配置することによって失われる「セマンティクス」はありません。
sheriffderek

1
真剣に最もクリーンなソリューションであり、それは画像で動作します!
shaneonabike

64

フレックスペアレント内のいずれかの軸で画像が伸びないようにするために、いくつかの解決策を見つけました。

たとえば、画像にオブジェクトフィットを使用してみることができます。

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

または、フレックス固有のルールを追加して、場合によってはより適切に機能するようにすることもできます。

align-self: center;
flex: 0 0 auto;

4
IEとEdgeでEdge 14までのサポートが欠けていなければ、object-fitは良いソリューションになる可能性があります
daniels


私はそのフォールバックを自分で使用しており、非常にうまく機能しています。
Matty Balaam

1
@danielsエッジは、現在開発中のオブジェクトフィットを持っていますdeveloper.microsoft.com/en-us/microsoft-edge/platform/status/...
AMDG

1
object-fit: contain;私のためにトリックをしました、私がクロムでのみ問題を抱えていたとき、ffは大丈夫でした。
ベンジャミンピーター

53

含まれるdivを追加する必要はありません。

cssの "align-items"プロパティのデフォルトは "stretch"で、これにより画像が元の高さまで完全に引き伸ばされます。CSSの「align-items」プロパティを「flex-start」に設定すると、問題が解決します。

.slider {
    display: flex;
    align-items: flex-start;  /* ADD THIS! */
}

3
ああ...実際にサポートされた方法で物事をやってくれてありがとう。私はそれまで答えを読んでいて、私たちが持っていたすべてが汚いハックであるとは信じられませんでした。
FélixGagnon-Grenier

35

画像のように、本来のサイズ、つまり自然なサイズの画像のほとんどjpeg。指定されたサイズが幅と高さの両方を定義している場合、欠損値は固有の比率を使用して決定されます...-MDNを参照してください。

ただし、現在のフレキシブルボックスレイアウトモジュールレベル1で直接フレックスアイテムとして設定されている画像の場合、期待どおりに動作しません私の知る限りで。

これらのディスカッションとバグレポートが関連している可能性があることを確認してください。

  • フレックスバグ#14 -Chrome / Flexbox固有のサイズ設定が正しく実装されていません。
  • Firefoxバグ972595フレックスアイテムの固有の幅を計算するために、フレックスコンテナーは「幅」ではなく「フレックスベース」を使用する必要があります
  • Chromium Issue 249112 -Flexboxで、固有のアスペクト比がメインサイズの計算に通知できるようにします。

回避策として、それぞれ<img><div>や、<span>などでラップすることができます。

jsFiddle

.slider {
  display: flex;
}

.slider>div {
  min-width: 0; /* why? see below. */
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

4.5 Flexアイテムの暗黙の最小サイズ

フレックスアイテムにより適切なデフォルトの最小サイズを提供するために、この仕様では、CSS 2.1で定義されているmin-widthおよびmin-heightプロパティの初期値として新しいauto値を導入しています。


または、table代わりにCSS レイアウトを使用することもできます。これによりflexbox、IE8でも、より多くのブラウザーで動作します。

jsFiddle

.slider {
  display: table;
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.slider>div {
  display: table-cell;
  vertical-align: top;
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>


最初のスニペットは.slider > div{min-width:0}、をサポートする新しいブラウザで必要min-width: autoです。
Oriol

3
flexbox仕様では、and autoのデフォルト値として新しい値が導入されました(以前はでした)。Chromeではまだ実装されていないため、最初のスニペットが機能します。ただし、新しいブラウザでは、フレックスアイテムを画像のデフォルトの幅よりも小さく縮小できるようにするために必要です。min-widthmin-height0
Oriol

2
それがフレックスボックスモデルの画像について語っので+1これは答えを受け入れられるべき根本的な問題 ...この場合は
ロバートKoritnikを

レイアウトがさまざまなブレークポイントで変更されない場合、テーブルは素晴らしいですが、最近はそうではありません。
sheriffderek

1
画像がすべて同じ比率ではない場合はどうですか? jsfiddle.net/sheriffderek/5u7y21we
sheriffderek

6

私は最近flexboxをいじっており、実験と以下の推論を通じてこれを解決するようになりました。しかし、実際には、これが正確に何が起こるかはわかりません。

実際の幅がフレックスシステムの影響を受ける場合。したがって、要素の幅が親の最大幅に達した後、CSSで設定された余分な幅は無視されます。次に、幅を100%に設定しても安全です。

imgタグの高さは画像自体から取得されるため、高さを0%に設定すると、何かを実行できます。(これは私が何について明確でないところです...しかしそれはそれを修正するべきであることが私には理にかなっています)

デモ

(最初にここで見たことを忘れないでください!)

.slider {
    display: flex;
}
.slider img {
    height: 0%;
    width: 100%;
    margin: 0 5px;
}

まだクロムでのみ動作します


興味深いですが、バグのようです。仕様によると、「パーセンテージは、生成されたボックスの包含ブロックの高さを基準に計算されます。包含ブロックの高さが明示的に指定されていない場合(つまり、コンテンツの高さに依存します)、この要素が完全に配置されていない場合、値はauto "に計算されます。それがFirefoxで起こっていることです。
Oriol

jsfiddle.net/xLc2Le0k/8は、ffとchromeの違いを説明しています。このため
Muhammad Umer

幅はffで、高さはchromeでやっているようです。
Muhammad Umer 2015年

興味深いですが、Xブラウザーのみのソリューションは実際にはソリューションではないのではないかと思います。あなたのコメントされたフィドルは、ここにあります:jsfiddle.net/xLc2Le0k/8は、FFで、しかし、本当に魅力的です。これは、FFが画像の高さを本当に100%にした場合、画像の高さに「比例」させていることを示しているようです。つまり、imgはコンテナの表示について「認識」していません:flex。これは、FFでimgの幅を100%に設定すると、幅をautoに設定した場合よりも画像が高くなる理由を説明しています。
coderMe 2015年

これはちょっと近いです...だけChromeで動作します。 jsfiddle.net/sheriffderek/xLc2Le0k/270
sheriffderek

2

この動作は予期されたものです。flexコンテナはデフォルトですべての子をストレッチします。画像に例外はありません。(つまり、親はalign-items: stretchプロパティを持ちます)

アスペクト比を維持するために、2つのソリューションがあります。

  1. デフォルトのalign-items: stretchプロパティをalign-items: flex-startまたはalign-self: centerなどに置き換えるか、 http://jsfiddle.net/e394Lqnt/3/

または

  1. 子供自身に独占的にalignプロパティを設定します。のような、align-self: centerまたはalign-self: flex-startなど http://jsfiddle.net/e394Lqnt/2/

-1

実際、画像の比率を保つためには、画像タグのコンテナに高さを設定する必要があることがわかりました。例>

.container{display:flex; height:100%;} img{width:100%;height:auto;}

次に、htmlでコンテナがタグ画像をラップします

<div class="container"><img src="image.jpg" alt="image" /></div>

これはIEや他のブラウザで動作します


-1

私は同じ問題を抱えていました。flex alignを使用して、要素を中央揃えにします。のalign-items: center代わりに使用する必要がありますalign-content: center。これはアスペクト比を維持しますが、align-contentはアスペクト比を維持しません。

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