Pertahankan rasio aspek gambar saat mengubah ketinggian

114

Dengan menggunakan model kotak fleksibel CSS, bagaimana cara memaksa gambar untuk mempertahankan rasio aspeknya?

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

Perhatikan bahwa gambar melebar atau menyusut untuk mengisi lebar wadah. Tidak apa-apa, tetapi dapatkah kita juga membuatnya meregangkan atau mengecilkan ketinggian untuk mempertahankan proporsi gambar?

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;
}
coderMe
sumber
1
Sejauh yang saya tahu, solusi terbaik adalah menggunakan a <div>dengan CSSbackground-image: url(...);background-size:contain; background-repeat:no-repeat
Blazemonger
1
Ada beberapa petunjuk menarik di sini, tetapi bagaimana jika rasio gambarnya belum sama? Menambahkan div 'ekstra', adalah hal terakhir yang perlu kita khawatirkan. Mengapa tidak menggunakan kasus uji seperti ini sebagai gantinya: jsfiddle.net/sheriffderek/999Lg9qv
sheriffderek

Jawaban:

68

Untuk tag img jika Anda menentukan satu sisi maka sisi lainnya diubah ukurannya untuk menjaga rasio aspek dan secara default gambar diperluas ke ukuran aslinya.

Menggunakan fakta ini jika Anda membungkus setiap tag img ke dalam tag div dan menyetel lebarnya menjadi 100% dari div induk, maka tingginya akan sesuai dengan rasio aspek yang Anda inginkan.

http://jsfiddle.net/0o5tpbxg/

* {
    margin: 0;
    padding: 0;
}
.slider {
    display: flex;
}
.slider .slide img {
    width: 100%;
}
Muhammad Umer
sumber
2
Saya tahu ada dua jawaban yang menyarankan penggunaan div, tetapi saya menandai jawaban ini dengan benar karena menjelaskan mengapa ketinggian gambar berbeda dari yang saya harapkan. Faktanya, ini adalah perilaku normal & benar, dan tidak mungkin untuk "diperbaiki", karena ini bukan bug.
coderMe
18
Tetapi jawaban ini tidak berbicara apa-apa tentang flexbox, karena gambar berperilaku berbeda dalam container flexbox. Menyetel satu sisi tidak akan mengubah ukuran sisi lainnya secara proporsional. Membungkusnya dalam wadah non flexbox membantu tetapi itu menambahkan markup yang tidak perlu kehilangan semantik.
Robert Koritnik
3
Sepertinya Anda tidak memerlukan div pembungkus untuk membuat ini berfungsi: jsfiddle.net/xLc2Le0k/120
Rick Strahl
4
Tapi, bagaimana dengan ini? jsfiddle.net/xLc2Le0k/15 Saya pikir solusi ini kebetulan yang hanya berfungsi karena gambar semua rasio yang sama. catatan samping: tidak ada 'semantik' yang hilang dengan menempatkan gambar di div untuk pemosisian / terutama saat menangani gambar responsif.
sheriffderek
1
Serius solusi terbersih dan bekerja dengan gambar!
shaneonabike
64

Untuk menjaga agar gambar tidak meregang di salah satu sumbu di dalam induk fleksibel, saya telah menemukan beberapa solusi.

Anda dapat mencoba menggunakan object-fit pada gambar yang, mis

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

Atau Anda dapat menambahkan aturan flex-specfic yang mungkin bekerja lebih baik dalam beberapa kasus.

align-self: center;
flex: 0 0 auto;
Matty Bileam
sumber
4
object-fit bisa menjadi solusi yang baik jika tidak kehilangan dukungan di IE dan Edge bahkan hingga Edge 14
daniels
1
Lihat fallback objek-fit ini untuk Edge an IE .
Andrei Telteu
Saya sendiri telah menggunakan fallback itu, bekerja dengan sangat baik.
Matty Balaam
1
@daniels Edge sekarang memiliki objek yang sesuai dalam pengembangan: developer.microsoft.com/en-us/microsoft-edge/platform/status/…
AMDG
1
object-fit: contain;melakukan trik untuk saya, ketika saya hanya memiliki masalah di chrome, ff baik-baik saja.
Benjamin Peter
53

Tidak perlu menambahkan div yang mengandung.

Default untuk properti css "align-items" adalah "stretch" yang menyebabkan gambar Anda ditarik hingga ketinggian aslinya. Menyetel properti css "align-items" ke "flex-start" akan memperbaiki masalah Anda.

.slider {
    display: flex;
    align-items: flex-start;  /* ADD THIS! */
}
Marvin Herbold
sumber
3
Ahh ... terima kasih telah melakukan hal-hal dengan cara yang didukung. Saya membaca jawaban sampai yang satu itu dan tidak percaya semua yang kami miliki adalah peretasan kotor ..
Félix Gagnon-Grenier
35

Sebagian besar gambar dengan dimensi intrinsik , yaitu ukuran yang wajar, seperti jpeggambar. Jika ukuran yang ditentukan menentukan salah satu dari lebar dan tinggi, nilai yang hilang ditentukan dengan menggunakan rasio intrinsik ... - lihat MDN .

Tapi itu tidak berfungsi seperti yang diharapkan jika gambar yang disetel sebagai item flex langsung dengan Modul Tata Letak Kotak Fleksibel Level 1 , sejauh yang saya tahu.

Lihat diskusi ini dan laporan bug mungkin terkait:

  • Flexbugs # 14 - Ukuran Intrinsik Chrome / Flexbox tidak diterapkan dengan benar.
  • Bug Firefox 972595 - Wadah fleksibel harus menggunakan "basis-fleksibel" daripada "lebar" untuk menghitung lebar intrinsik item fleksibel
  • Masalah Chromium 249112 - Di Flexbox, izinkan rasio aspek intrinsik untuk menginformasikan penghitungan ukuran utama.

Sebagai solusinya, Anda bisa membungkus masing <img>- masing dengan a <div>atau a <span>, atau lebih.

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 Ukuran Minimum Tersirat dari Item Fleksibel

Untuk memberikan ukuran minimum default yang lebih masuk akal untuk item fleksibel , spesifikasi ini memperkenalkan nilai otomatis baru sebagai nilai awal properti min-width dan min-height yang ditentukan dalam CSS 2.1.


Atau, Anda dapat menggunakan tabletata letak CSS sebagai gantinya, yang akan Anda dapatkan hasil yang serupa flexbox, ini akan berfungsi di lebih banyak browser, bahkan untuk 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>

Stiker
sumber
Potongan pertama membutuhkan .slider > div{min-width:0}browser baru yang mendukung min-width: auto.
Oriol
3
Spesifikasi flexbox memperkenalkan autonilai baru sebagai nilai default min-widthdan min-height(sebelumnya 0). Chrome belum menerapkannya, jadi cuplikan pertama Anda berfungsi. Tetapi browser baru membutuhkannya untuk memungkinkan item flex menyusut lebih kecil dari lebar default gambar.
Oriol
2
+1 ini harus menjadi jawaban yang diterima karena berbicara tentang gambar dalam model flexbox yang merupakan akar masalah dalam kasus ini ...
Robert Koritnik
Tabel bagus jika tata letak Anda tidak berubah di berbagai break-point, tetapi itu tidak mungkin terjadi hari ini.
sheriffderek
1
Bagaimana jika gambar tidak semuanya memiliki rasio yang sama? jsfiddle.net/sheriffderek/5u7y21we
sheriffderek
6

Saya telah bermain-main dengan flexbox akhir-akhir ini dan saya menemukan solusi untuk ini melalui eksperimen dan alasan berikut. Namun, pada kenyataannya saya tidak yakin apakah ini yang sebenarnya terjadi.

Jika lebar nyata dipengaruhi oleh sistem fleksibel. Jadi setelah lebar elemen mencapai lebar maksimal induk, lebar ekstra yang disetel di css diabaikan. Maka aman untuk menyetel lebar ke 100%.

Karena tinggi tag img berasal dari gambar itu sendiri, maka mengatur tinggi ke 0% bisa melakukan sesuatu. (Di sinilah saya tidak jelas tentang apa ... tetapi masuk akal bagi saya bahwa itu harus memperbaikinya)

DEMO

(ingat pernah melihatnya di sini dulu!)

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

Hanya bekerja di chrome

Muhammad Umer
sumber
Menarik, tapi sepertinya bug. Menurut spesifikasi , " Persentase dihitung sehubungan dengan tinggi blok penampung kotak yang dihasilkan. Jika tinggi blok penampung tidak ditentukan secara eksplisit (yaitu, tergantung pada ketinggian konten), dan elemen ini tidak diposisikan secara mutlak , nilai dihitung menjadiauto ". Itulah yang terjadi di Firefox.
Oriol
jsfiddle.net/xLc2Le0k/8 menjelaskan perbedaan ff dan chrome. untuk ini
Muhammad Umer
width tampaknya melakukan di ff apa yang tinggi lakukan di chrome.
Muhammad Umer
Ini menarik, tetapi saya khawatir solusi khusus browser X bukanlah solusi yang sebenarnya. Biola komentar Anda, di sini: jsfiddle.net/xLc2Le0k/8 benar-benar menarik , meskipun, di FF. Hal ini tampaknya menunjukkan bahwa FF membuat tinggi gambar "proporsional" dengan tinggi gambar jika benar-benar 100%. Dengan kata lain, img tidak "tahu" tentang penampung display: flex. Ini menjelaskan mengapa, di FF, jika Anda menyetel lebar img menjadi 100%, gambar akan lebih tinggi daripada jika Anda menyetel lebarnya ke otomatis.
coderMe
Ini agak dekat ... tetapi hanya berfungsi di Chrome: jsfiddle.net/sheriffderek/xLc2Le0k/270
sheriffderek
2

Perilaku ini diharapkan. flex container akan meregangkan semua anaknya secara default. Gambar tidak terkecuali. (yaitu, orang tua akan memiliki align-items: stretchproperti)

Untuk menjaga rasio aspek, kami memiliki dua solusi:

  1. Ganti align-items: stretchproperti default ke align-items: flex-startatau align-self: centerdll., Http://jsfiddle.net/e394Lqnt/3/

atau

  1. Setel properti align secara eksklusif ke anak itu sendiri: suka, align-self: centeratau align-self: flex-startdll. Http://jsfiddle.net/e394Lqnt/2/
Asim KT
sumber
-1

Sebenarnya saya menemukan bahwa wadah dari tag gambar harus memiliki ketinggian untuk menjaga rasio gambar. misalnya>

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

kemudian di html Anda, penampung Anda akan membungkus gambar tag

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

ini berfungsi untuk IE dan browser lain

kengreg
sumber
-1

Saya baru saja mengalami masalah yang sama. Gunakan flex align untuk menengahkan elemen Anda. Anda perlu menggunakan align-items: centerbukan align-content: center. Ini akan mempertahankan rasio aspek, sedangkan perataan-konten tidak akan mempertahankan rasio aspek.

Clinton Green
sumber