Yüksekliği değiştirirken görüntünün en boy oranını koruyun


114

CSS esnek kutu modelini kullanarak bir görüntüyü en boy oranını korumaya nasıl zorlayabilirim?

JS Fiddle: http://jsfiddle.net/xLc2Le0k/2/

Kabın genişliğini doldurmak için görüntülerin uzadığına veya küçüldüğüne dikkat edin. Sorun değil, ancak görüntü oranlarını korumak için yüksekliği uzatabilir veya kısaltabilir miyiz?

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
Bildiğim kadarıyla en iyi çözüm <div>CSS ile a kullanmaktırbackground-image: url(...);background-size:contain; background-repeat:no-repeat
Blazemonger

1
Burada bazı ilginç ipuçları var, peki ya görüntüler zaten aynı oranda değilse? Eklemek ve 'ekstra' div, endişelenmemiz gereken son şeydir. Artık şöyle bir test vakası kullanmayın Neden: jsfiddle.net/sheriffderek/999Lg9qv
sheriffderek

Yanıtlar:


68

İmg etiketleri için bir tarafı tanımlarsanız, en boy oranını korumak için diğer taraf yeniden boyutlandırılır ve varsayılan olarak resimler orijinal boyutlarına genişler.

Bu gerçeği kullanarak, her img etiketini div etiketine sararsanız ve genişliğini üst div'in% 100'ü olarak ayarlarsanız, yükseklik, istediğiniz en boy oranına göre olacaktır.

http://jsfiddle.net/0o5tpbxg/

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

2
Div kullanımını öneren iki yanıt olduğunu biliyorum, ancak bu yanıtı doğru olarak işaretliyorum çünkü görüntü yüksekliklerinin neden beklediğimden farklı olduğunu açıklıyor . Aslında, bu normal ve doğru bir davranıştır ve bir hata olmadığı için "düzeltilmesi" olası değildir.
coderMe

18
Ancak bu cevap flexbox hakkında hiçbir şey söylemiyor, çünkü resimler flexbox konteyner içinde farklı davranıyor. Bir tarafın ayarlanması diğerini orantılı olarak yeniden boyutlandırmaz. Bunları flexbox olmayan bir konteynere sarmak yardımcı olur, ancak bu anlamsallığı yitiren gereksiz işaretleme ekler.
Robert Koritnik

3
Bunun işe yaraması
Rick Strahl

4
Peki ya bu? jsfiddle.net/xLc2Le0k/15 Bu çözümün sadece görüntülerin hepsi aynı oranda olduğu için çalışan bir şans olduğunu düşünüyorum. yan not: özellikle duyarlı görüntülerle uğraşırken / özellikle duyarlı görüntülerle uğraşırken, bir görüntüyü konumlandırma için bir div'e yerleştirerek 'anlamsallık' kaybı olmaz.
sheriffderek

1
Cidden en temiz çözüm ve resimle çalışıyor!
shaneonabike

64

Görüntülerin bir flex üst öğe içinde her iki eksende uzamasını önlemek için birkaç çözüm buldum.

Görüntü üzerinde nesne sığdırmayı deneyebilirsiniz, örneğin

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

Ya da bazı durumlarda daha iyi çalışabilecek esnek özel kurallar ekleyebilirsiniz.

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

4
Nesne uyumu, Edge 14'e kadar IE ve Edge'de destek eksik olmasaydı iyi bir çözüm olabilirdi
daniels


Ben de bu geri dönüşü kullanıyorum, çok iyi çalışıyor.
Matty Balaam

1
@daniels Edge artık geliştirmede nesne uyumuna sahip: developer.microsoft.com/en-us/microsoft-edge/platform/status/…
AMDG

1
object-fit: contain;benim için hile yaptı, sadece kromda sorun yaşadığımda, ff iyiydi.
Benjamin Peter

53

İçeren bir div eklemeye gerek yok.

Css "align-items" özelliği için varsayılan "streç" dir, bu da resimlerinizin tam orijinal yüksekliğine uzatılmasına neden olur. Css "align-items" özelliğini "flex-start" olarak ayarlamak sorununuzu düzeltir.

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

3
Ahh ... Aslında işleri desteklenen şekilde yaptığınız için teşekkürler. O zamana kadar cevapları okuyordum ve sahip olduğumuz tek şeyin kirli hackerlar olduğuna inanamadım ..
Félix Gagnon-Grenier

35

İç boyutları olan , yani bir jpeggörüntü gibi doğal boyuttaki görüntülerin çoğu . Belirtilen boyut hem genişlik hem de yükseklikten birini tanımlıyorsa, eksik değer iç oran kullanılarak belirlenir ... - MDN'ye bakın .

Ancak, bildiğim kadarıyla , mevcut Esnek Kutu Düzeni Modülü Seviye 1 ile doğrudan esnek öğeler olarak ayarlanan resimler beklendiği gibi çalışmıyor .

Bu tartışmalara bakın ve hata raporları ilgili olabilir:

  • Flexbugs # 14 - Chrome / Flexbox Intrinsic Sizing doğru şekilde uygulanmadı.
  • Firefox Bug 972595 - Flex kapsayıcıları, esnek öğelerin iç genişliklerini hesaplamak için "genişlik" yerine "esnek tabanlı" kullanmalıdır
  • Chromium Issue 249112 - Flexbox'ta, iç en boy oranlarının ana boyut hesaplamasını bilgilendirmesine izin verin.

Geçici bir çözüm olarak, her birini <img>a <div>veya a ile sarmalayabilirsiniz <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 Zımni Minimum Esnek Öğe Boyutu

Esnek öğeler için daha makul bir varsayılan minimum boyut sağlamak için , bu belirtim CSS 2.1'de tanımlanan minimum genişlik ve minimum yükseklik özelliklerinin başlangıç ​​değeri olarak yeni bir otomatik değer sunar .


Alternatif tableolarak flexbox, IE8 için bile daha fazla tarayıcıda çalışacağı için benzer sonuçlar elde edeceğiniz CSS düzenini kullanabilirsiniz .

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>


İlk parçacığın .slider > div{min-width:0}, destekleyen yeni tarayıcılarda olması gerekir min-width: auto.
Oriol

3
FlexBox Spec yeni tanıtılan autoiçin varsayılan değer olarak değerini min-widthve min-height(daha önce öyleydi 0). Chrome bunu henüz uygulamadığından ilk snippet'iniz çalışıyor. Ancak, esnek öğelerin resimlerin varsayılan genişliğinden daha küçük küçülmesine izin vermek için yeni tarayıcılar buna ihtiyaç duyar.
Oriol

2
+1 bu cevap kabul edilmelidir çünkü bu durumda asıl sorun olan flexbox modelindeki resimlerden bahsediyor ...
Robert Koritnik

Düzeniniz çeşitli kırılma noktalarında değişmezse tablo harika, ancak bu günlerde pek olası değil.
sheriffderek

1
Görüntülerin hepsi aynı oranda olmadığında ne olacak? jsfiddle.net/sheriffderek/5u7y21we
sheriffderek

6

Son zamanlarda flexbox ile oynuyordum ve bunun için deneyler ve aşağıdaki mantıkla çözüme ulaştım. Ancak gerçekte tam olarak bunun olup olmadığından emin değilim.

Gerçek genişlik flex sistemden etkileniyorsa. Dolayısıyla, elemanların genişliği ebeveynin maksimum genişliğine ulaştıktan sonra, css'de ayarlanan ekstra genişlik yok sayılır. O zaman genişliği% 100 olarak ayarlamak güvenlidir.

İmg etiketinin yüksekliği resmin kendisinden türetildiği için, yüksekliğin% 0 olarak ayarlanması bir şeyler yapabilir. (burası ne olduğundan emin değilim ... ama düzeltmesi bana mantıklı geldi)

DEMO

(önce burada gördüğünü hatırla!)

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

Henüz yalnızca Chrome'da çalışıyor


İlginç, ama bir hata gibi görünüyor. Spesifikasyona göre , " Yüzde, oluşturulan kutunun içeren bloğunun yüksekliğine göre hesaplanır. İçeren bloğun yüksekliği açıkça belirtilmezse (yani, içerik yüksekliğine bağlıdır) ve bu öğe mutlak olarak konumlandırılmamışsa , değerauto "olarak hesaplanır . Firefox'ta olan budur.
Oriol

jsfiddle.net/xLc2Le0k/8 , ff ve chrome'daki farkı açıklar. bunun için
Muhammad Umer

genişlik, kromda yükseklik ne yapıyor gibi görünüyor.
Muhammad Umer

İlginç, ancak korkarım ki yalnızca X tarayıcı çözümleri gerçekten çözüm değil. Yorumladığınız keman, burada: jsfiddle.net/xLc2Le0k/8 , yine de FF'de kesinlikle büyüleyici . Bu, eğer gerçekten% 100 ise, FF'nin görüntü yüksekliğini görüntünün yüksekliğiyle "orantılı" hale getirdiğini gösteriyor gibi görünüyor. Başka bir deyişle, img kabın ekranından "haberdar değildir": flex Bu, neden FF'de img genişliğini% 100 olarak ayarlarsanız, görüntünün genişliği otomatik olarak ayarlamanıza göre neden daha uzun olduğunu açıklar.
coderMe

Bu tür yakın ... ama sadece Chrome'da çalışır: jsfiddle.net/sheriffderek/xLc2Le0k/270
sheriffderek

2

Bu davranış bekleniyor. flex container, varsayılan olarak tüm alt öğelerini uzatır . Görüntünün istisnası yoktur. (yani, ebeveynin align-items: stretchmülkü olacaktır )

En boy oranını korumak için iki çözümümüz var:

  1. Varsayılan align-items: stretchözelliği, align-items: flex-startveya align-self: centervb. İle değiştirin , http://jsfiddle.net/e394Lqnt/3/

veya

  1. Münhasıran çocuğa kendisine Seti align özelliği: gibi, align-self: centerya da align-self: flex-startvb http://jsfiddle.net/e394Lqnt/2/

-1

Aslında, görüntünün oranını korumak için görüntü etiketinin kapsayıcısının bir yüksekliğe sahip olması gerektiğini öğrendim. örneğin>

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

sonra html'nizde, kapsayıcınız etiket resmini saracaktır

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

bu, IE ve diğer tarayıcılar için çalışır


-1

Ben de aynı sorunu yaşadım. Öğelerinizi ortalamak için esnek hizalamayı kullanın. Bunun align-items: centeryerine kullanmanız gerekir align-content: center. Bu, en boy oranını korurken, hizalama içeriği en boy oranını korumaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.