Pertahankan rasio aspek div dengan CSS

1059

Saya ingin membuat divyang dapat mengubah lebar / tingginya saat lebar jendela berubah.

Apakah ada aturan CSS3 yang akan memungkinkan ketinggian berubah sesuai dengan lebar, sambil mempertahankan rasio aspeknya ?

Saya tahu saya bisa melakukan ini melalui JavaScript, tetapi saya lebih suka menggunakan CSS saja.

rasio aspek penyimpanan div menurut lebar jendela

jackb
sumber
3
Saya menulis tentang pendekatan berbeda untuk ini dalam artikel Trik CSS-saya tentang penskalaan animasi responsif
Zach Saucier
2
Saya sudah datang ke T&J ini sangat terlambat, tetapi saya harus berkomentar. Meskipun sangat disiplin dan dalam aturan SO dari semua orang yang menjawab untuk mencoba yang terbaik untuk memenuhi permintaan "hanya CSS" dari pertanyaan, cukup mengejutkan bahwa dengan pengecualian dari jawaban oleh user007 rendah di halaman, tidak ada satu telah menyebutkan yang jelas: tidak ada solusi hanya CSS yang dapat diandalkan, masalah ini membutuhkan Javascript. Seorang pemula yang datang ke halaman ini dapat membuang waktu yang berharga untuk beralih dari satu set pro / kontra ke yang lain sebelum bola lampu padam: Hanya CSS tidak akan berfungsi.
Theo d'Or
1
Saya menulis alat kecil yang membuatnya mudah untuk melihat pratinjau dan menghitung rasio aspek, aspekrat.io . Ini juga menghasilkan kode CSS / Sass / Less yang sesuai yang dapat Anda salin dan tempel ke proyek Anda. Semoga orang merasakan manfaatnya.
Ryan Hefner
lihat contoh ini: w3schools.com/howto/howto_css_aspect_ratio.asp ..... itu berhasil saya
Cristian Agudelo
1
Pertanyaan ini untuk mengatur ketinggian berdasarkan lebar . Jika Anda membutuhkan yang sebaliknya, lihat Mengatur Elemen Lebar Berdasarkan Tinggi Via CSS .
John Mellor

Jawaban:

1353

Buat saja pembungkus <div>dengan nilai persentase untuk padding-bottom, seperti ini:

div {
  width: 100%;
  padding-bottom: 75%;
  background: gold; /** <-- For the demo **/
}

/* demonstration purposed only : non-essential */
.demoWrapper {
  padding: 10px;
  background: white;
  box-sizing: border-box;
  resize: horizontal;
  border: 1px dashed;
  overflow: auto;
  max-width: 100%;
  height: calc(100vh - 16px);
}
<div class="demoWrapper">
  <div></div>
</div>

Ini akan menghasilkan <div>dengan tinggi sama dengan 75% dari lebar wadahnya (rasio aspek 4: 3).

Ini bergantung pada fakta bahwa untuk pengisi:

Persentase dihitung sehubungan dengan lebar blok berisi kotak yang dihasilkan [...] (sumber: w3.org , penekanan tambang)

Nilai padding-bottom untuk rasio aspek lainnya dan lebar 100%:

aspect ratio  | padding-bottom value
--------------|----------------------
    16:9      |       56.25%
    4:3       |       75%
    3:2       |       66.66%
    8:5       |       62.5%

Menempatkan konten di div:

Untuk menjaga rasio aspek div dan mencegah kontennya melebar, Anda perlu menambahkan anak yang benar-benar diposisikan dan merentangkannya ke tepi pembungkus dengan:

div.stretchy-wrapper {
  position: relative;
}

div.stretchy-wrapper > div {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
}

Berikut adalah demo dan lain lebih mendalam demo

Desainer web
sumber
29
@ schellmax, itu karena padding% dihitung relatif terhadap lebar elemen saat ini, sedangkan tinggi% dihitung relatif terhadap tinggi elemen induk. Selanjutnya, posisi absolut dihitung relatif terhadap wadah luar elemen, yang meliputi area padding. Untuk informasi lebih lanjut Google "Model Kotak CSS"
Anson Kao
11
Ini tampaknya tidak berfungsi secara bersarang. Ini bekerja pada level pertama, tetapi ketika mencoba melakukan hal yang sama di dalam aspek rasio pemeliharaan div, persentase padding-bottom tampaknya diterapkan pada lebar induk. di sini adalah contoh di mana padding-bottom .stretchy-wrap.onethird dari 25% sebenarnya 25% dari lebar induk. Adakah yang bisa menjelaskan hal ini?
Misterparker
4
Sangat luar biasa. Ini membunuh saya bahwa teknik ini tidak akan berfungsi ketika Anda ingin memperbaiki ketinggian 100%. @ Masterparker, teknik ini mengandalkan perhitungan lebar dan padding yang dilakukan terhadap referensi yang sama; Anda tidak dapat menggunakan lebar lebih kecil dari 100%, seperti yang Anda miliki dalam contoh Anda.
steveluscher
2
@ Masterparker Ya, persentase bantalan dihitung secara proporsional dengan lebar elemen induk. Lihat contoh lebih mendalam yang saya poskan di edit untuk jawaban saya. Demo saya yang diperbarui menunjukkan 'mode bersarang' saat Anda berbicara tentang.
Web_Designer
3
fakta bahwa ia telah menunjukkan bahwa ini cukup untuk meyakinkan saya bahwa ini adalah jawaban terbaik yang pernah saya lihat di SO. berteriak kepada pria saya @Web_Designer
410

vw unit:

Anda bisa menggunakan vwsatuan untuk lebar dan tinggi elemen. Ini memungkinkan rasio aspek elemen dipertahankan, berdasarkan lebar viewport.

vw: 1/100 dari lebar viewport. [ MDN ]

Atau, Anda juga dapat menggunakan vhuntuk ketinggian viewport, atau bahkan vmin/ vmaxuntuk menggunakan dimensi viewport yang lebih kecil / lebih besar (diskusi di sini ).

Contoh: rasio aspek 1: 1

div {
  width: 20vw;
  height: 20vw;
  background: gold;
}
<div></div>

Untuk rasio aspek lainnya, Anda dapat menggunakan tabel berikut untuk menghitung nilai ketinggian sesuai dengan lebar elemen:

aspect ratio  |  multiply width by
-----------------------------------
     1:1      |         1
     1:3      |         3
     4:3      |        0.75
    16:9      |       0.5625

Contoh: grid 4x4 divs persegi

body {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
div {
  width: 23vw;
  height: 23vw;
  margin: 0.5vw auto;
  background: gold;
}
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>

Berikut ini adalah Fiddle dengan demo ini dan di sini adalah solusi untuk membuat kotak persegi yang responsif dengan konten yang terpusat secara vertikal dan horizontal .


Dukungan browser untuk unit vh / vw adalah IE9 + lihat canIuse untuk info lebih lanjut

web-tiki
sumber
14
Ini harus menjadi jawaban yang diterima. Mungkin tidak sekarang, tetapi di masa depan. unit vw didukung di sebagian besar browser sekarang .
Agustus
3
@vivekmaharajh kedua teknik itu bagus, masing-masing punya kelebihan dan kekurangannya sendiri. Menggunakan satu atau yang lain sangat tergantung pada situasi.
web-tiki
11
@ web-tiki, Anda benar. Saya telah mengalami satu masalah - ini mengasumsikan bahwa lebar elemen sebanding dengan lebar viewport, yang tidak akan terjadi jika 1) Anda memiliki hal-hal seperti talang lebar tetap, atau 2) Anda memiliki set lebar-max untuk beberapa elemen Anda.
Vivek Maharajh
1
Mungkin itu hanya Chrome v47beta, tetapi ketika saya mengatur div ke width:50%dan height:50vwtingginya sedikit lebih tinggi dari lebar, jadi tidak tepat proporsi 1: 1. Ada ide?
thdoan
2
@ 10basetom itu adalah perilaku normal. unit vw berisi lebar scrollbar sedangkan% width tidak. Perbedaan antara tinggi dan lebar akan tergantung pada ukuran scrollbar yang berbeda tergantung pada browser.
web-tiki
26

Saya telah menemukan cara untuk melakukan ini menggunakan CSS, tetapi Anda harus berhati-hati karena dapat berubah tergantung pada aliran situs web Anda sendiri. Saya sudah melakukannya untuk menanamkan video dengan rasio aspek konstan dalam porsi lebar cairan situs web saya.

Katakanlah Anda memiliki video yang disematkan seperti ini:

<object>
     <param ... /><param ... />...
     <embed src="..." ...</embed>
</object>

Anda kemudian dapat menempatkan ini semua di dalam div dengan kelas "video". Kelas video ini mungkin akan menjadi elemen cair di situs web Anda sedemikian rupa sehingga, dengan sendirinya, ia tidak memiliki batasan ketinggian langsung, tetapi ketika Anda mengubah ukuran peramban itu akan berubah lebarnya sesuai dengan aliran situs web. Ini akan menjadi elemen yang mungkin Anda coba masukkan video tertanam Anda sambil mempertahankan rasio aspek tertentu dari video.

Untuk melakukan ini, saya meletakkan gambar sebelum objek tertanam dalam div kelas "video".

!!! Bagian yang penting adalah gambar memiliki rasio aspek yang benar yang ingin Anda pertahankan. Juga, pastikan ukuran gambar SETIDAKNYA sebesar yang terkecil yang Anda harapkan video (atau apa pun yang Anda mempertahankan AR) didasarkan pada tata letak Anda. Ini akan menghindari potensi masalah dalam resolusi gambar ketika ukurannya diubah. Misalnya, jika Anda ingin mempertahankan rasio aspek 3: 2, jangan hanya menggunakan gambar 3px x 2px. Ini mungkin berhasil dalam beberapa keadaan, tapi saya belum mengujinya, dan mungkin itu ide yang baik untuk dihindari.

Anda mungkin harus sudah memiliki lebar minimum seperti ini yang ditetapkan untuk elemen cairan situs web Anda. Jika tidak, sebaiknya lakukan hal itu untuk menghindari pemotongan elemen atau tumpang tindih saat jendela browser terlalu kecil. Lebih baik memiliki bilah gulir di beberapa titik. Lebar terkecil yang harus dimiliki halaman web adalah sekitar ~ 600px (termasuk kolom dengan lebar tetap) karena resolusi layar tidak menjadi lebih kecil kecuali Anda berurusan dengan situs ramah-ponsel. !!!

Saya menggunakan png yang benar-benar transparan, tetapi saya pikir itu tidak penting jika Anda melakukannya dengan benar. Seperti ini:

<div class="video">
     <img class="maintainaspectratio" src="maintainaspectratio.png" />
     <object>
          <param ... /><param ... />...
          <embed src="..." ...</embed>
     </object>
</div>

Sekarang Anda harus dapat menambahkan CSS yang mirip dengan yang berikut:

div.video { ...; position: relative; }
div.video img.maintainaspectratio { width: 100%; }
div.video object { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
div.video embed {width: 100%; height: 100%; }

Pastikan Anda juga menghapus deklarasi tinggi atau lebar eksplisit di dalam objek dan tag embed yang biasanya datang dengan copy / paste kode embed.

Cara kerjanya bergantung pada properti posisi elemen kelas video dan item yang Anda inginkan mempertahankan rasio aspek tertentu. Itu mengambil keuntungan dari cara gambar akan mempertahankan rasio aspek yang tepat ketika diubah ukurannya dalam suatu elemen. Ini memberitahu apa pun yang ada dalam elemen kelas video untuk mengambil keuntungan penuh dari real estat yang disediakan oleh gambar dinamis dengan memaksa lebar / tinggi hingga 100% elemen kelas video yang disesuaikan oleh gambar.

Cukup keren, eh?

Anda mungkin harus bermain-main dengannya sedikit agar bisa bekerja dengan desain Anda sendiri, tetapi ini sebenarnya bekerja sangat baik bagi saya. Konsep umum ada di sana.

meninggalkan kebiasaan
sumber
17

Elliot mengilhami saya untuk solusi ini - terima kasih:

aspectratio.png adalah file PNG yang benar-benar transparan dengan ukuran rasio aspek pilihan Anda, dalam kasus saya 30x10 piksel.

HTML

<div class="eyecatcher">
  <img src="/img/aspectratio.png"/>
</div>

CSS3

.eyecatcher img {
  width: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url(../img/autoresized-picture.jpg);
}

Harap dicatat: background-size adalah fitur css3 yang mungkin tidak berfungsi dengan browser target Anda. Anda dapat memeriksa interoperabilitas (fe di caniuse.com ).

Florian Breisch
sumber
14

Untuk menambahkan jawaban Web_Designer, <div>akan memiliki tinggi (seluruhnya terdiri dari padding bawah) sebesar 75% dari lebar elemen yang mengandungnya . Berikut ringkasan yang bagus: http://mattsnider.com/css-using-percent-for-margin-and-padding/ . Saya tidak yakin mengapa harus begitu, tapi memang begitu.

Jika Anda ingin div Anda menjadi lebar selain 100%, Anda perlu div pembungkus lain untuk mengatur lebar:

div.ar-outer{
    width: 60%; /* container; whatever width you want */
    margin: 0 auto; /* centered if you like */
}
div.ar {
    width:100%; /* 100% of width of container */
    padding-bottom: 75%; /* 75% of width of container */
    position:relative;
}
div.ar-inner {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
}

Saya menggunakan sesuatu yang mirip dengan trik gambar Elliot baru-baru ini untuk memungkinkan saya menggunakan kueri media CSS untuk menyajikan file logo yang berbeda tergantung pada resolusi perangkat, tetapi masih skala secara proporsional seperti yang <img>biasa dilakukan (saya mengatur logo sebagai gambar latar belakang menjadi .png transparan. dengan rasio aspek yang benar). Tetapi solusi Web_Designer akan menyelamatkan saya permintaan http.

tidak tertangkap
sumber
Solusi bagus Dalam kasus saya, saya tahu ukuran gambar "alami" ketika menempatkannya ke DOM dan saya harus memiliki placeholder gambar dengan ketinggian yang tepat untuk mencegah pengguliran lebih lanjut begitu browser memuat gambar. Di .ar-outer saya memiliki lebar gambar dalam piksel, di .ar saya memiliki padding-bottom yang dihitung dari rasio aspek gambar nyata. Alih-alih ar-inner saya memiliki gambar itu sendiri (<img>). Namun saya harus mengatur lebar ke 100% daripada mengatur atas, bawah, kiri dan kanan. Ketika saya mengatur maxWidth ke ar-outer, gambar berskala baik ketika orang tua kecil, tetapi tidak skala ke ukuran lebih besar dari ukuran aslinya.
Mi-La
13

Seperti yang dinyatakan di sini di w3schools.com dan agak mengulangi dalam jawaban yang diterima ini , menambahkan nilai sebagai persentase (penekanan milik saya):

Menentukan bantalan dalam persen dari lebar elemen yang mengandung

Ergo, contoh yang benar dari DIV responsif yang menjaga rasio aspek 16: 9 adalah sebagai berikut:

CSS

.parent {
    position: relative;
    width: 100%;
}
.child {
    position: relative;
    padding-bottom: calc(100% * 9 / 16);
}
.child > div {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

HTML

<div class="parent">
    <div class="child">
        <div>Aspect is kept when resizing</div>
    </div>
</div>

Demo di JSFiddle

Marc A
sumber
13

Karena @ web-tiki sudah menunjukkan cara untuk menggunakan vh/ vw, saya juga perlu cara untuk memusatkan di layar, di sini ada kode snippet untuk potret 9:16 .

.container {
  width: 100vw;
  height: calc(100vw * 16 / 9);
  transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}

translateYakan menjaga pusat ini di layar. calc(100vw * 16 / 9)diharapkan tinggi untuk 9/16. (100vw * 16 / 9 - 100vh)tinggi meluap, jadi, tarik ke atas overflow height/2akan membuatnya tetap di tengah layar.

Untuk lansekap, dan tetap 16: 9 , Anda menunjukkan penggunaan

.container {
  width: 100vw;
  height: calc(100vw * 9 / 16);
  transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}

Rasio 9/16 mudah diubah, tidak perlu ditentukan sebelumnya 100:56.25atau 100:75. Jika Anda ingin memastikan ketinggian terlebih dahulu, Anda harus mengganti lebar dan tinggi, misalnya height:100vh;width: calc(100vh * 9 / 16)untuk potret 9:16.

Jika Anda ingin beradaptasi untuk ukuran layar yang berbeda, Anda mungkin juga tertarik

  • penutup / isi ukuran latar belakang
    • Gaya di atas mirip mengandung, tergantung pada rasio lebar: tinggi.
  • objek-fit
    • sampul / isi untuk tag img / video
  • @media (orientation: portrait)/@media (orientation: landscape)
    • Permintaan media untuk portrait/ landscapeuntuk mengubah rasio.
Wener
sumber
11

Ini adalah peningkatan pada jawaban yang diterima:

  • Menggunakan elemen semu sebagai ganti div pembungkus
  • Rasio aspek didasarkan pada lebar kotak, bukan induknya
  • Kotak akan meregang secara vertikal saat konten menjadi lebih tinggi

.box {
  margin-top: 1em;
  margin-bottom: 1em;
  background-color: #CCC;
}

.fixed-ar::before {
  content: "";
  float: left;
  width: 1px;
  margin-left: -1px;
}
.fixed-ar::after {
  content: "";
  display: table;
  clear: both;
}

.fixed-ar-16-9::before {
  padding-top: 56.25%;
}
.fixed-ar-3-2::before {
  padding-top: 66.66%;
}
.fixed-ar-4-3::before {
  padding-top: 75%;
}
.fixed-ar-1-1::before {
  padding-top: 100%;
}

.width-50 {
  display: inline-block;
  width: 50%;
}
.width-20 {
  display: inline-block;
  width: 20%;
}
<div class="box fixed-ar fixed-ar-16-9">16:9 full width</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-3-2 width-20">3:2</div>
<div class="box fixed-ar fixed-ar-4-3 width-20">4:3</div>
<div class="box fixed-ar fixed-ar-1-1 width-20">1:1</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>

Salman A
sumber
cara menonaktifkan peregangan vertikal kotak? Sebenarnya, stretching div tidak mempertahankan rasio aspeknya
florian
Jika konten lebih tinggi dari ketinggian yang diharapkan maka kotak akan meregang secara vertikal. Ide ini paling baik digunakan dengan konten yang dapat disesuaikan dengan dimensi orang tuanya, misalnya video dan gambar.
Salman A
10

Saya menemukan solusi cerdas menggunakan <svg>dan display:grid.

Elemen Grid memungkinkan Anda untuk menempati ruang yang sama dengan dua (atau lebih) elemen, tanpa harus menentukan yang mana yang mengatur ketinggian. Yang berarti bahwa, di luar kotak, yang lebih tinggi menetapkan rasio .

Ini berarti Anda dapat menggunakannya seperti ketika Anda tahu konten tidak akan pernah cukup tinggi untuk mengisi seluruh "rasio" dan Anda hanya mencari cara untuk memposisikan konten di ruang ini (yaitu untuk memusatkannya di kedua arah gunakan display:flex; align-items:center; justify-content:center ).
Ini hampir sama dengan menggunakan transparan <img>dengan display:blockdan rasio yang telah ditentukan, kecuali yang <svg>lebih ringan dan jauh lebih mudah untuk dimodifikasi (untuk mengubah rasio secara responsif, jika Anda perlu).

<div class="ratio">
  <svg viewBox="0 0 1 1"></svg>
  <div>
    I'm square
  </div>
</div>
.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

Yang perlu Anda lakukan adalah mengubah <svg>rasio:

  • <svg viewBox="0 0 4 3"></svg>
  • <svg viewBox="0 0 16 9"></svg>

Lihat itu berfungsi:


Jika Anda memerlukan solusi di mana elemen konten tidak diizinkan untuk mengatur rasio ketika itu lebih tinggi (dengan overflow tersembunyi atau otomatis), Anda perlu mengatur position:relative di grid dan position:absolute; height:100%; overflow-y: auto;pada konten. Contoh:

tao
sumber
9

Mendasarkan pada solusi Anda, saya telah membuat beberapa trik:

Saat Anda menggunakannya, HTML Anda hanya akan

<div data-keep-ratio="75%">
    <div>Main content</div>
</div>

Untuk menggunakannya dengan cara ini: CSS:

*[data-keep-ratio] {
    display: block;
    width: 100%;
    position: relative;
}
*[data-keep-ratio] > * {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

dan js (jQuery)

$('*[data-keep-ratio]').each(function(){ 
    var ratio = $(this).data('keep-ratio');
    $(this).css('padding-bottom', ratio);
});

Dan setelah ini, Anda hanya mengatur attr data-keep-ratioke tinggi / lebar dan hanya itu.

pie6k
sumber
3
Anda harus menggunakan data-keep-ratiotidak keep-ratiodan dapatkan nilainya menggunakan$(this).data('keep-ratio');
Robert
kode Anda berfungsi sekarang dan mungkin akan berfungsi selamanya tetapi ini bukan standar dan browser dapat berhenti mendukungnya kapan saja di masa mendatang
Robert
1
Menggunakan JS di sini akan menyebabkan berita buruk!
Amir Hossein Ahmadi
8

Anda dapat menggunakan svg. Buat posisi wadah / pembungkus relatif, letakkan svg pertama sebagai posisi statis dan kemudian letakkan konten yang benar-benar diposisikan (atas: 0; kiri: 0; kanan: 0; bawah: 0;)

Contoh dengan proporsi 16: 9:

image.svg: (dapat diuraikan dalam src)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 9" width="16" height="9"/>

CSS:

.container {
  position: relative;
}
.content {
  position: absolute;
  top:0; left:0; right:0; bottom:0;
}

HTML:

<div class="container">
  <img style="width: 100%" src="image.svg" />
  <div class="content"></div>
</div>

Perhatikan bahwa inline svg tampaknya tidak berfungsi, tetapi Anda dapat urlencode svg dan menyematkannya dalam atribut img src seperti ini:

<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2016%209%22%20width%3D%2216%22%20height%3D%229%22%2F%3E" style="width: 100%;" />
Maciej Krawczyk
sumber
7

SCSS adalah solusi terbaik dalam kasus saya; menggunakan atribut data:

[data-aspect-ratio] {
    display: block;
    max-width: 100%;
    position: relative;

    &:before {
        content: '';
        display: block;
    }

    > * {
        display: block;
        height: 100%;
        left: 0;
        position: absolute;
        top: 0;
        width: 100%;
    }
}
[data-aspect-ratio="3:1"]:before {
    padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
    padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
    padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
    padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
    padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
    padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
    padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
    padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
    padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
    padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
    padding-top: 300%;
}

Sebagai contoh :

<div data-aspect-ratio="16:9"><iframe ...></iframe></div>

sumber

tuan
sumber
15
Hanya FYI ... Anda dapat melakukan hal yang tepat ini (menggunakan pemilih pemilih) dengan jumlah baris yang persis sama menggunakan CSS biasa. The [data-aspect-ratio]selector atribut tersedia untuk Anda di CSS.
rnevius
6

Meskipun sebagian besar jawaban sangat keren, sebagian besar dari mereka memerlukan gambar yang sudah berukuran benar ... Solusi lain hanya berfungsi untuk lebar dan tidak peduli dengan ketinggian yang tersedia, tetapi kadang-kadang Anda ingin menyesuaikan konten dengan ketinggian tertentu juga .

Saya sudah mencoba untuk menyatukan mereka bersama-sama untuk membawa solusi yang sepenuhnya portabel dan dapat di-ukuran-ulang ... Triknya adalah menggunakan penskalaan otomatis suatu gambar tetapi menggunakan elemen svg sebaris daripada menggunakan gambar yang telah dirender sebelumnya atau bentuk apa pun dari permintaan HTTP kedua ...

div.holder{
  background-color:red;
  display:inline-block;
  height:100px;
  width:400px;
}
svg, img{
  background-color:blue;
  display:block;
  height:auto;
  width:auto;
  max-width:100%;
  max-height:100%;
}
.content_sizer{
  position:relative;
  display:inline-block;
  height:100%;
}
.content{
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:0;
  background-color:rgba(155,255,0,0.5);
}
<div class="holder">
  <div class="content_sizer">
    <svg width=10000 height=5000 />
    <div class="content">
    </div>
  </div>
</div>

Perhatikan bahwa saya telah menggunakan nilai besar pada atribut lebar dan tinggi SVG, karena harus lebih besar dari ukuran maksimum yang diharapkan karena hanya bisa menyusut. Contohnya membuat rasio div 10: 5

Salketer
sumber
4

Hanya ide atau retasan.

div {
  background-color: blue;
  width: 10%;
  transition: background-color 0.5s, width 0.5s;
  font-size: 0;
}

div:hover {
  width: 20%;
  background-color: red;
}
  
img {
  width: 100%;
  height: auto;
  visibility: hidden;
}
<div>
  <!-- use an image with target aspect ratio. sample is a square -->
  <img src="http://i.imgur.com/9OPnZNk.png" />
</div>

orlland
sumber
Ini bukan solusi CSS saja ... Sekarang, jika Anda akan menggunakan gambar yang disandikan base64 dalam elemen pseudo, itu akan menjadi solusi keren.
rnevius
1
Benar-benar tidak ada solusi hanya CSS. HTML adalah komponen dasar web. Saya percaya tujuan dari pertanyaan ini adalah untuk tidak menggunakan JS mungkin untuk menghemat sumber daya / pemrosesan.
orlland
Saya tidak yakin apakah elemen semu akan berfungsi. Saya menggunakan properti elemen img untuk menjaga rasio aspeknya agar solusi ini berfungsi.
orlland
Bagus, tetapi menghitung ketinggian hanya ketika lebar berubah. Ini harus dilakukan dua arah, jadi ketika saya mengurangi ketinggian, lebar juga dihitung ulang. Kalau tidak, itu tidak berguna ..
Ωmega
4

katakanlah Anda memiliki 2 div, div outher adalah sebuah wadah dan bagian dalamnya bisa berupa elemen apa pun yang Anda perlukan untuk mempertahankan rasio (img atau iframe youtube atau apa pun)

html terlihat seperti ini:

<div class='container'>
  <div class='element'>
  </div><!-- end of element -->

katakanlah Anda perlu menjaga rasio "elemen"

rasio => 4 banding 1 atau 2 banding 1 ...

css terlihat seperti ini

.container{
  position: relative;
  height: 0
  padding-bottom : 75% /* for 4 to 3 ratio */ 25% /* for 4 to 1 ratio ..*/

}

.element{
  width : 100%;
  height: 100%;
  position: absolute; 
  top : 0 ;
  bottom : 0 ;
  background : red; /* just for illustration */
}

padding bila dispesifikasikan dalam% dihitung berdasarkan lebar bukan tinggi. .. jadi pada dasarnya Anda tidak masalah berapa lebar Anda tinggi akan selalu dihitung berdasarkan itu. yang akan menjaga rasio.

Ahmed Eid
sumber
4

Saya telah mengalami masalah ini beberapa kali, jadi saya membuat solusi JS untuk itu. Ini pada dasarnya menyesuaikan ketinggian domElement sesuai dengan lebar elemen dengan rasio yang Anda tentukan. Anda dapat menggunakannya sebagai berikut:

<div ratio="4x3"></div>

Perlu diketahui bahwa karena mengatur ketinggian elemen, elemen tersebut harus berupa a display:blockataudisplay:inline-block .

https://github.com/JeffreyArts/html-ratio-component

pengguna007
sumber
1
Walaupun saya belum melihat atau mencoba kode Anda (saya sudah memiliki kode saya sendiri), saya telah meningkatkan jawaban Anda hanya karena Anda menghadirkan satu-satunya solusi yang dapat diandalkan, sebuah skrip JS.
Theo d'Or
Pertanyaan khusus meminta solusi yang tidak memerlukan Javascript.
Flimm
4

Jika Anda ingin memasukkan kotak di dalam viewport pada tampilan portrait atau landscape (sebesar mungkin, tetapi tidak ada yang menempel di luar), beralih antara menggunakan vw/ vhpada orientasi portrait/ landscape:

@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
} 
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
} 
MoonLite
sumber
4

Saya ingin membagikan solusi saya, di mana saya memiliki imgtag -t mengisi rasio aspek tertentu. Saya tidak bisa menggunakan backgroundkarena kurangnya dukungan dari CMS dan saya tidak akan memilih untuk menggunakan tag gaya seperti: <img style="background:url(...)" />. Selain itu, lebarnya adalah 100%, sehingga tidak perlu diatur pada ukuran tetap seperti pada beberapa solusi. Ini akan skala responsif!

.wrapper {
  width: 50%;
}

.image-container {
  position: relative;
  width: 100%;
}

.image-container::before {
  content: "";
  display: block;
}

.image-container img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ratio-4-3::before {
  padding-top: 75%;
}

.ratio-3-1::before {
  padding-top: calc(100% / 3);
}

.ratio-2-1::before {
  padding-top: 50%;
}
<div class="wrapper"> <!-- Just to make things a bit smaller -->
  <p>
  Example of an 4:3 aspect ratio, filled by an image with an 1:1 ratio.
  </p>
  <div class="image-container ratio-4-3"> <!-- Lets go for a 4:3 aspect ratio -->
    <img src="https://placekitten.com/1000/1000/" alt="Kittens!" />
  </div>
  <p>
  Just place other block elements around it; it will work just fine.
  </p>
</div>

LaVomit
sumber
3

Anda dapat mencapainya dengan menggunakan SVG.

Tergantung pada suatu kasus, tetapi dalam beberapa hal ini sangat berguna. Sebagai contoh - Anda dapat mengatur background-imagetanpa mengatur ketinggian tetap atau menggunakannya untuk menanamkan youtube <iframe>dengan rasio 16:9danposition:absolute lain lain

Untuk 3:2rasio yang ditetapkanviewBox="0 0 3 2" dan sebagainya.

Contoh:

div{
    background-color:red
}
svg{
    width:100%;
    display:block;
    visibility:hidden
}

.demo-1{width:35%}
.demo-2{width:20%}
<div class="demo-1">
  <svg viewBox="0 0 3 2"></svg>
</div>

<hr>

<div class="demo-2">
  <svg viewBox="0 0 3 2"></svg>
</div>

Jakub Muda
sumber
3

Cara sederhana mempertahankan rasio aspek, menggunakan elemen kanvas.

Coba ubah ukuran div di bawah ini untuk melihatnya beraksi.

Bagi saya, pendekatan ini bekerja paling baik, jadi saya membaginya dengan orang lain sehingga mereka bisa mendapat manfaat darinya.

.cont {
  border: 5px solid blue;
  position: relative;
  width: 300px;
  padding: 0;
  margin: 5px;
  resize: horizontal;
  overflow: hidden;
}

.ratio {
  width: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

Juga berfungsi dengan ketinggian dinamis!

.cont {
  border: 5px solid blue;
  position: relative;
  height: 170px;
  padding: 0;
  margin: 5px;
  resize: vertical;
  overflow: hidden;
  display: inline-block; /* so the div doesn't automatically expand to max width */
}

.ratio {
  height: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

Gbr22
sumber
yup membantu saya, sekarang saya dapat menggunakannya untuk mengatur tinggi gambar induk div)
Alex
2

Katakan bahwa Anda ingin mempertahankan Lebar: 100px dan Tinggi: 50px (yaitu, 2: 1) Lakukan saja perhitungan ini:

.pb-2to1 {
  padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}
Syed
sumber
0

Saya menggunakan solusi baru.

.squares{
  width: 30vw
  height: 30vw

Untuk rasio aspek utama

.aspect-ratio
  width: 10vw
  height: 10vh

Namun, ini relatif terhadap seluruh viewport. Jadi, jika Anda membutuhkan div yang 30% dari lebar viewport, Anda dapat menggunakan 30vw sebagai gantinya, dan karena Anda tahu lebarnya, Anda menggunakannya kembali dengan ketinggian menggunakan unit calc dan vw.

Eshwaren Manoharen
sumber
7
Bukankah ini persis seperti yang dijabarkan oleh jawaban berperingkat tertinggi kedua?
rnevius
-4

Jika seluruh struktur kontainer berdasarkan persentase, ini akan menjadi perilaku default, dapatkah Anda memberikan contoh yang lebih spesifik?

Di bawah ini adalah contoh dari apa yang saya maksud, jika seluruh hierarki induk Anda berdasarkan%, penyesuaian jendela browser apa pun akan berfungsi tanpa js / css tambahan, apakah ini tidak mungkin dengan tata letak Anda?

<div style="width: 100%;">
   <div style="width: 50%; margin: 0 auto;">Content</div>
</div>
Nick Craver
sumber
1
Lihat hasil edit saya ke pertanyaan awal. Saya tidak melihat di mana teknik ini akan menjaga rasio aspek, ketinggian tidak akan berubah.
jackb