Duy trì tỷ lệ khung hình của div với CSS


1058

Tôi muốn tạo một divcái có thể thay đổi chiều rộng / chiều cao của nó khi chiều rộng của cửa sổ thay đổi.

Có bất kỳ quy tắc CSS3 nào cho phép chiều cao thay đổi theo chiều rộng, trong khi vẫn duy trì tỷ lệ khung hình của nó không?

Tôi biết tôi có thể làm điều này thông qua JavaScript, nhưng tôi chỉ muốn sử dụng CSS.

div giữ tỷ lệ khung hình theo chiều rộng của cửa sổ


3
Tôi đã viết về các cách tiếp cận khác nhau trong bài viết này về CSS-Tricks về nhân rộng hoạt ảnh đáp ứng
Zach Saucier

2
Tôi đã đến hỏi đáp này rất muộn, nhưng tôi phải bình luận. Mặc dù nó rất kỷ luật và trong các quy tắc SO của mọi người khi trả lời để cố gắng hết sức để đáp ứng nhu cầu "CSS duy nhất" của câu hỏi, nhưng thật đáng ngạc nhiên là ngoại trừ câu trả lời của người dùng xuống thấp trên trang, không- người ta đã đề cập đến một điều hiển nhiên: không có giải pháp chỉ CSS đáng tin cậy tồn tại, vấn đề này yêu cầu Javascript. Một người mới đến trang này có thể lãng phí thời gian quý báu để chuyển từ một bộ ưu / nhược điểm khác trước khi bóng đèn tắt: Chỉ CSS sẽ không làm.
Theo

1
Tôi đã viết một công cụ nhỏ giúp dễ dàng xem trước và tính toán tỷ lệ khung hình, facrat.io . Nó cũng tạo ra mã CSS / Sass / Less phù hợp mà bạn có thể sao chép và dán vào các dự án của mình. Hy vọng mọi người thấy nó hữu ích.
Ryan Hefner

xem ví dụ này: w3schools.com/howto/howto_css_aspect_ratio.asp ..... điều đó đã làm việc với tôi
Cristian Agudelo

1
Câu hỏi này là để thiết lập chiều cao dựa trên chiều rộng . Nếu bạn cần ngược lại, hãy xem Cài đặt Chiều rộng phần tử dựa trên Chiều cao qua CSS .
John Mellor

Câu trả lời:


1353

Chỉ cần tạo một trình bao bọc <div>với giá trị phần trăm cho padding-bottom, như thế này:

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>

Nó sẽ dẫn đến một <div>chiều cao bằng 75% chiều rộng của thùng chứa của nó (tỷ lệ khung hình 4: 3).

Điều này phụ thuộc vào thực tế là cho phần đệm:

Tỷ lệ phần trăm được tính tương ứng với chiều rộng của khối chứa hộp được tạo [...] (nguồn: w3.org , nhấn mạnh của tôi)

Giá trị đệm dưới cho các tỷ lệ khung hình khác và chiều rộng 100%:

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

Đặt nội dung trong div:

Để giữ tỷ lệ khung hình của div và ngăn nội dung của nó kéo dài nó, bạn cần thêm một đứa trẻ có vị trí tuyệt đối và kéo dài nó ra các cạnh của trình bao bọc với:

div.stretchy-wrapper {
  position: relative;
}

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

Dưới đây là một bản demo và khác sâu hơn trong bản demo


29
@schellmax, đó là bởi vì% đệm được tính tương đối với chiều rộng của phần tử hiện tại, trong đó %% được tính tương ứng với chiều cao của phần tử cha. Hơn nữa, các vị trí tuyệt đối được tính tương đối với vùng chứa bên ngoài của một phần tử, bao gồm vùng đệm. Để biết thêm thông tin Google "Mô hình hộp CSS"
Anson Kao

11
Điều này dường như không hoạt động theo cách lồng nhau. Nó hoạt động ở cấp độ đầu tiên, nhưng khi cố gắng thực hiện điều tương tự bên trong tỷ lệ khung hình duy trì div, tỷ lệ phần trăm dưới đáy đệm dường như được áp dụng cho chiều rộng của cha mẹ. đây là một ví dụ trong đó phần đệm .stretchy-quấn.onethird dưới cùng 25% thực sự là 25% chiều rộng cha. Ai đó có thể giải thích điều này?
Misterparker

4
Hoàn toàn tuyệt vời. Nó giết tôi rằng kỹ thuật này sẽ không hoạt động khi bạn muốn cố định chiều cao ở mức 100%. @Misterparker, kỹ thuật dựa trên các tính toán chiều rộng và phần đệm được thực hiện dựa trên cùng một tham chiếu; bạn không thể sử dụng chiều rộng nhỏ hơn 100%, như trong ví dụ của bạn.
steveluscher

2
@Misterparker Có, phần trăm đệm được tính theo tỷ lệ với chiều rộng của phần tử cha. Xem ví dụ sâu hơn tôi đã đăng trong một chỉnh sửa cho câu trả lời của tôi. Bản demo được cập nhật của tôi cho thấy một "thời trang lồng nhau" như bạn đang nói.
Web_Designer

3
thực tế là ông đã chứng minh rằng tác phẩm này đủ để thuyết phục tôi rằng đây là câu trả lời hay nhất tôi từng thấy trên SO. hét to với người đàn ông của tôi @Web_Designer

410

vw các đơn vị:

Bạn có thể sử dụng vwcác đơn vị cho cả chiều rộng và chiều cao của phần tử. Điều này cho phép tỷ lệ khung hình của phần tử được giữ nguyên, dựa trên chiều rộng của khung nhìn.

vw: 1/100 chiều rộng của khung nhìn. [ MDN ]

Ngoài ra, bạn cũng có thể sử dụng vhcho chiều cao của chế độ xem hoặc thậm chí vmin/ vmaxđể sử dụng kích thước khung nhìn nhỏ hơn / lớn hơn (thảo luận tại đây ).

Ví dụ: tỷ lệ khung hình 1: 1

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

Đối với các tỷ lệ khung hình khác, bạn có thể sử dụng bảng sau để tính giá trị cho chiều cao theo chiều rộng của phần tử:

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

Ví dụ: lưới 4 x 4 của div vuông

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>

Đây là một Fiddle với bản demo này và đây là một giải pháp để tạo ra một lưới các ô vuông đáp ứng với nội dung tập trung dọc và ngang .


Hỗ trợ trình duyệt cho các đơn vị vh / vw là IE9 + xem canIuse để biết thêm thông tin


14
Đây phải là câu trả lời được chấp nhận. Có lẽ không phải bây giờ, mà là trong tương lai. Các đơn vị vw được hỗ trợ trong hầu hết các trình duyệt .
Tháng Tám

3
@vivekmaharajh cả hai kỹ thuật đều tốt, mỗi kỹ thuật đều có ưu và nhược điểm riêng. Sử dụng cái này hay cái khác phụ thuộc rất lớn vào tình huống.
web-tiki

11
@ web-tiki, bạn nói đúng. Tôi đã gặp phải một vấn đề - giả định rằng chiều rộng của phần tử tỷ lệ thuận với chiều rộng của khung nhìn, sẽ không xảy ra nếu 1) bạn có những thứ như máng xối có chiều rộng cố định hoặc 2) bạn có bộ chiều rộng tối đa cho một số yếu tố của bạn.
Vivek Maharajh

1
Có thể đó chỉ là Chrome v47beta, nhưng khi tôi đặt div thành width:50%height:50vwchiều cao cao hơn một chút so với chiều rộng, do đó, không chính xác theo tỷ lệ 1: 1. Có ý kiến ​​gì không?
thdoan

2
@ 10basetom đó là một hành vi bình thường. Các đơn vị vw chứa chiều rộng thanh cuộn trong khi% width không. Sự khác biệt giữa chiều cao và chiều rộng sẽ phụ thuộc vào kích thước của thanh cuộn khác nhau tùy thuộc vào trình duyệt.
web-tiki

26

Tôi đã tìm thấy một cách để làm điều này bằng CSS, nhưng bạn phải cẩn thận vì nó có thể thay đổi tùy thuộc vào dòng chảy của trang web của riêng bạn. Tôi đã thực hiện nó để nhúng video với tỷ lệ khung hình không đổi trong một phần chiều rộng của trang web của tôi.

Giả sử bạn có một video nhúng như thế này:

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

Sau đó, bạn có thể đặt tất cả những thứ này vào trong một div với lớp "video". Lớp video này có thể sẽ là yếu tố trôi chảy trong trang web của bạn, do đó, bản thân nó không có ràng buộc về chiều cao trực tiếp, nhưng khi bạn thay đổi kích thước trình duyệt, nó sẽ thay đổi theo chiều rộng theo dòng chảy của trang web. Đây sẽ là yếu tố mà bạn có thể đang cố gắng đưa video nhúng của mình vào trong khi duy trì tỷ lệ khung hình nhất định của video.

Để thực hiện việc này, tôi đặt một hình ảnh trước đối tượng được nhúng trong div lớp "video".

!!! Phần quan trọng là hình ảnh có tỷ lệ khung hình chính xác mà bạn muốn duy trì. Ngoài ra, hãy đảm bảo kích thước của hình ảnh là HẤP DẪN lớn nhất nhỏ nhất bạn mong đợi video (hoặc bất cứ điều gì bạn đang duy trì AR của) để có được dựa trên bố cục của bạn. Điều này sẽ tránh mọi vấn đề tiềm ẩn trong độ phân giải của hình ảnh khi nó được thay đổi tỷ lệ phần trăm. Ví dụ: nếu bạn muốn duy trì tỷ lệ khung hình 3: 2, đừng chỉ sử dụng hình ảnh 3px x 2px. Nó có thể hoạt động trong một số trường hợp, nhưng tôi đã không thử nó, và có lẽ đó là một ý tưởng tốt để tránh.

Bạn có thể đã có chiều rộng tối thiểu như thế này được xác định cho các yếu tố trôi chảy của trang web của bạn. Nếu không, đó là một ý tưởng tốt để làm như vậy để tránh cắt các phần tử hoặc có sự chồng chéo khi cửa sổ trình duyệt quá nhỏ. Nó là tốt hơn để có một thanh cuộn tại một số điểm. Chiều rộng nhỏ nhất mà một trang web sẽ nhận được là khoảng ~ 600px (bao gồm mọi cột có chiều rộng cố định) vì độ phân giải màn hình không nhỏ hơn trừ khi bạn đang xử lý các trang web thân thiện với điện thoại. !!!

Tôi sử dụng một png hoàn toàn trong suốt nhưng tôi thực sự không nghĩ nó sẽ trở nên quan trọng nếu bạn làm đúng. Như thế này:

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

Bây giờ bạn sẽ có thể thêm CSS tương tự như sau:

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%; }

Hãy chắc chắn rằng bạn cũng xóa mọi khai báo chiều cao hoặc chiều rộng rõ ràng trong đối tượng và các thẻ nhúng thường đi kèm với mã nhúng sao chép / dán.

Cách thức hoạt động tùy thuộc vào thuộc tính vị trí của thành phần lớp video và mục bạn muốn duy trì tỷ lệ khung hình nhất định. Nó lợi dụng cách hình ảnh sẽ duy trì tỷ lệ khung hình phù hợp khi được thay đổi kích thước trong một thành phần. Nó nói bất cứ điều gì khác trong phần tử lớp video để tận dụng tối đa lợi thế của bất động sản được cung cấp bởi hình ảnh động bằng cách buộc chiều rộng / chiều cao của nó thành 100% yếu tố lớp video được điều chỉnh bởi hình ảnh.

Khá tuyệt, nhỉ?

Bạn có thể phải chơi xung quanh với nó một chút để làm cho nó hoạt động với thiết kế của riêng bạn, nhưng điều này thực sự hoạt động tốt đáng ngạc nhiên đối với tôi. Khái niệm chung là có.


17

Elliot đã truyền cảm hứng cho tôi đến giải pháp này - cảm ơn:

aspectratio.png là một tệp PNG hoàn toàn trong suốt với kích thước tỷ lệ khung hình ưa thích của bạn, trong trường hợp của tôi là 30x10 pixel.

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);
}

Xin lưu ý: background-size là một tính năng css3 có thể không hoạt động với các trình duyệt mục tiêu của bạn. Bạn có thể kiểm tra khả năng tương tác (trên trang caniuse.com ).


14

Để thêm vào câu trả lời của Web_Designer, <div>sẽ có chiều cao (hoàn toàn được tạo thành từ phần đệm dưới cùng) bằng 75% chiều rộng của phần tử chứa nó . Đây là một bản tóm tắt hay: http://mattsnider.com/css-USE-percent-for-margin-and-padding/ . Tôi không chắc tại sao lại như vậy, nhưng nó là như vậy.

Nếu bạn muốn div của bạn có chiều rộng khác 100%, bạn cần một div gói khác để đặt chiều rộng:

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;
}

Gần đây tôi đã sử dụng một cái gì đó tương tự như thủ thuật hình ảnh của Elliot để cho phép tôi sử dụng các truy vấn phương tiện CSS để cung cấp một tệp logo khác tùy theo độ phân giải của thiết bị, nhưng vẫn tỷ lệ theo tỷ lệ như một cách <img>tự nhiên (tôi đặt logo làm hình nền trong suốt .png với tỷ lệ khung hình chính xác). Nhưng giải pháp của Web_Designer sẽ tiết kiệm cho tôi một yêu cầu http.


Giải pháp tuyệt vời. Trong trường hợp của tôi, tôi biết kích thước hình ảnh "tự nhiên" khi đặt nó vào DOM và tôi cần phải có một trình giữ chỗ hình ảnh với chiều cao phù hợp để ngăn cuộn thêm khi trình duyệt tải hình ảnh. Trong .ar-ngoài tôi có chiều rộng hình ảnh tính bằng pixel, trong .ar tôi có phần đệm dưới cùng được tính từ tỷ lệ khung hình ảnh thực. Thay vì ar-bên trong, tôi có hình ảnh (<img>). Tuy nhiên, tôi phải đặt chiều rộng thành 100% thay vì đặt trên cùng, dưới cùng, trái và phải. Khi tôi đặt maxWidth thành ar-outs, hình ảnh sẽ được chia tỷ lệ độc đáo khi cha mẹ nhỏ, nhưng không mở rộng thành kích thước lớn hơn kích thước tự nhiên của nó.
Mi-La

13

Như đã nêu ở đây trên w3schools.com và phần nào được nhắc lại trong câu trả lời được chấp nhận này , đệm các giá trị theo tỷ lệ phần trăm (nhấn mạnh của tôi):

Chỉ định phần đệm theo phần trăm chiều rộng của phần tử chứa

Ergo, một ví dụ chính xác về DIV đáp ứng giữ tỷ lệ khung hình 16: 9 như sau:

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>

Bản trình diễn trên JSFiddle


13

Vì @ web-tiki đã hiển thị cách sử dụng vh/ vw, tôi cũng cần một cách để căn giữa trong màn hình, đây là đoạn mã cho chân dung 9:16 .

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

translateYsẽ giữ trung tâm này trong màn hình. calc(100vw * 16 / 9)chiều cao dự kiến ​​cho ngày 16/9. (100vw * 16 / 9 - 100vh)là chiều cao tràn, vì vậy, kéo lên overflow height/2sẽ giữ nó ở giữa màn hình.

Đối với phong cảnh và giữ 16: 9 , bạn hiển thị sử dụng

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

Tỷ lệ 9/16 dễ dàng thay đổi, không cần xác định trước 100:56.25hoặc 100:75. Nếu bạn muốn đảm bảo chiều cao trước, bạn nên chuyển đổi chiều rộng và chiều cao, ví dụ như height:100vh;width: calc(100vh * 9 / 16)cho chân dung 9:16.

Nếu bạn muốn điều chỉnh cho kích thước màn hình khác nhau, bạn cũng có thể quan tâm

  • bìa / kích thước nền
    • Kiểu trên tương tự như chứa, phụ thuộc vào tỷ lệ chiều rộng: chiều cao.
  • phù hợp với đối tượng
    • bìa / chứa cho thẻ img / video
  • @media (orientation: portrait)/@media (orientation: landscape)
    • Truy vấn phương tiện cho portrait/ landscapeđể thay đổi tỷ lệ.

11

Đây là một cải tiến về câu trả lời được chấp nhận:

  • Sử dụng các phần tử giả thay vì div trình bao bọc
  • Tỷ lệ khung hình dựa trên chiều rộng của hộp thay vì mẹ của nó
  • Hộp sẽ kéo dài theo chiều dọc khi nội dung trở nên cao hơn

.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>


Làm thế nào để vô hiệu hóa kéo dài của hộp? Nói một cách nghiêm túc, một div kéo dài không duy trì tỷ lệ khung hình của nó
florian

Nếu nội dung cao hơn chiều cao dự kiến ​​thì hộp sẽ kéo dài theo chiều dọc. Ý tưởng này được sử dụng tốt nhất với nội dung có thể kéo dài để phù hợp với kích thước của cha mẹ, ví dụ như video và hình ảnh.
Salman A

10

Tôi tình cờ tìm thấy một giải pháp thông minh bằng cách sử dụng <svg>display:grid.

Phần tử lưới cho phép bạn chiếm cùng một không gian với hai (hoặc nhiều) phần tử, mà không cần chỉ định cái nào đặt chiều cao. Điều đó có nghĩa là, ngoài hộp, người cao hơn sẽ đặt tỷ lệ .

Điều này có nghĩa là bạn có thể sử dụng nó như khi bạn biết nội dung sẽ không bao giờ đủ cao để lấp đầy toàn bộ "tỷ lệ" và bạn chỉ đơn giản là tìm cách định vị nội dung trong không gian này (nghĩa là tập trung vào cả hai hướng sử dụng display:flex; align-items:center; justify-content:center).
Nó khá giống với việc sử dụng tỷ lệ trong suốt <img>với display:blockvà được xác định trước, ngoại trừ việc <svg>nhẹ hơn và dễ dàng sửa đổi hơn (để thay đổi tỷ lệ một cách đáp ứng, nếu bạn cần).

<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;
}

Tất cả bạn cần làm là thay đổi <svg>tỷ lệ s:

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

Xem nó hoạt động:


Nếu bạn cần một giải pháp trong đó phần tử nội dung không được phép đặt tỷ lệ khi nó cao hơn (bị ẩn hoặc tự động tràn), bạn cần đặt position:relativetrên lưới và position:absolute; height:100%; overflow-y: auto;trên nội dung. Thí dụ:


9

Dựa trên các giải pháp của bạn, tôi đã thực hiện một số mẹo:

Khi bạn sử dụng nó, HTML của bạn sẽ chỉ

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

Để sử dụng nó theo cách này, hãy tạo: CSS:

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

và js (jQuery)

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

Và có cái này bạn chỉ cần đặt attr data-keep-ratiothành chiều cao / chiều rộng và thế là xong.


3
bạn nên sử dụng data-keep-ratiokhông keep-ratiovà nhận được giá trị của nó sử dụng$(this).data('keep-ratio');
Robert

mã của bạn hiện đang hoạt động và có thể sẽ hoạt động mãi mãi nhưng nó không chuẩn và các trình duyệt có thể ngừng hỗ trợ nó bất cứ lúc nào trong tương lai
Robert

1
Sử dụng JS ở đây sẽ gây ra tin xấu!
Amir Hossein Ahmadi

8

Bạn có thể sử dụng một Svg. Làm cho vị trí của thùng chứa / trình bao bọc tương đối, đặt Svg đầu tiên ở vị trí tĩnh và sau đó đặt nội dung được định vị tuyệt đối (trên cùng: 0; trái: 0; phải: 0; dưới: 0;)

Ví dụ với tỷ lệ 16: 9:

image.svg: (có thể được nội tuyến trong 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>

Lưu ý rằng svg nội tuyến dường như không hoạt động, nhưng bạn có thể urlencode mã hóa Svg và nhúng nó vào thuộc tính img src như thế này:

<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%;" />

7

SCSS là giải pháp tốt nhất trong trường hợp của tôi; sử dụng thuộc tính dữ liệu:

[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%;
}

Ví dụ :

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

nguồn


15
Chỉ cần FYI ... Bạn có thể thực hiện điều chính xác này (sử dụng bộ chọn thuộc tính) với cùng một lượng dòng bằng CSS đơn giản. Bộ [data-aspect-ratio]chọn thuộc tính có sẵn cho bạn trong CSS.
rnevius

6

Mặc dù hầu hết các câu trả lời đều rất tuyệt, nhưng hầu hết chúng đều yêu cầu phải có một hình ảnh có kích thước chính xác ... Các giải pháp khác chỉ hoạt động theo chiều rộng và không quan tâm đến chiều cao có sẵn, nhưng đôi khi bạn cũng muốn phù hợp với nội dung ở một độ cao nhất định. .

Tôi đã cố gắng kết hợp chúng lại với nhau để mang đến một giải pháp hoàn toàn di động và có thể thay đổi kích thước ... Bí quyết là sử dụng để tự động thu nhỏ hình ảnh nhưng sử dụng phần tử svg nội tuyến thay vì sử dụng hình ảnh được kết xuất sẵn hoặc bất kỳ hình thức nào yêu cầu HTTP thứ hai ...

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>

Lưu ý rằng tôi đã sử dụng các giá trị lớn trong các thuộc tính chiều rộng và chiều cao của SVG, vì nó cần phải lớn hơn kích thước tối đa dự kiến ​​vì nó chỉ có thể co lại. Ví dụ này làm cho tỷ lệ div 10: 5


4

Chỉ là một ý tưởng hoặc một hack.

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>


Đây không phải là giải pháp chỉ dành cho CSS ... Bây giờ, nếu bạn đã sử dụng hình ảnh được mã hóa base64 trong phần tử giả, thì đó sẽ là một giải pháp tuyệt vời.
rnevius

1
Thực sự không có giải pháp nào chỉ có CSS. HTML là thành phần cơ bản của web. Tôi tin rằng mục đích của câu hỏi là không sử dụng JS có lẽ để tiết kiệm tài nguyên / xử lý.
orlland

Tôi không chắc chắn nếu phần tử giả sẽ hoạt động. Tôi đã sử dụng thuộc tính của phần tử img để giữ tỷ lệ khung hình của nó cho giải pháp này hoạt động.
orlland

Đẹp, nhưng nó chỉ tính chiều cao khi chiều rộng thay đổi. Nó nên làm cả hai cách, vì vậy khi tôi giảm chiều cao, chiều rộng cũng được tính toán lại. Nếu không thì nó là vô dụng ..
Ωmega

4

giả sử bạn có 2 div, div bên ngoài là một thùng chứa và bên trong có thể là bất kỳ yếu tố nào bạn cần để giữ tỷ lệ của nó (img hoặc iframe youtube hoặc bất cứ điều gì)

html trông như thế này:

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

giả sử bạn cần giữ tỷ lệ của "phần tử"

tỷ lệ => 4 đến 1 hoặc 2 đến 1 ...

Css trông như thế này

.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 */
}

phần đệm khi được chỉ định bằng%, nó được tính dựa trên chiều rộng chứ không phải chiều cao. .. về cơ bản, bạn không quan trọng chiều rộng của bạn sẽ luôn được tính dựa trên chiều rộng đó. mà sẽ giữ tỷ lệ.


4

Nếu bạn muốn đặt một hình vuông bên trong chế độ xem trên chế độ xem dọc hoặc ngang (càng lớn càng tốt, nhưng không có gì dính bên ngoài), hãy chuyển đổi giữa sử dụng vw/ vhbật hướng portrait/ landscape:

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

4

Tôi muốn chia sẻ giải pháp của mình, nơi tôi có một img-tag điền tỷ lệ khung hình nhất định. Tôi không thể sử dụng backgroundvì thiếu sự hỗ trợ của CMS và tôi không thích sử dụng thẻ kiểu như vậy : <img style="background:url(...)" />. Ngoài ra, chiều rộng là 100%, do đó không cần đặt ở kích thước cố định như trong một số giải pháp. Nó sẽ mở rộng quy mô một cách đáp ứng!

.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>


3

Tôi đã gặp vấn đề này khá nhiều lần, vì vậy tôi đã tạo ra một giải pháp JS cho nó. Điều này về cơ bản điều chỉnh chiều cao của domEuity theo chiều rộng của phần tử theo tỷ lệ bạn chỉ định. Bạn có thể sử dụng nó như sau:

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

Xin lưu ý rằng vì nó đang đặt chiều cao của phần tử, nên phần tử phải là a display:blockhoặc display:inline-block.

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


1
Mặc dù tôi chưa thấy hoặc đã thử mã của bạn (tôi đã có mã riêng của mình) Tôi đã nêu lên câu trả lời của bạn chỉ vì thực tế là bạn trình bày giải pháp đáng tin cậy duy nhất, một tập lệnh JS.
Theo

Câu hỏi đặc biệt yêu cầu một giải pháp không cần Javascript.
Flimm

2

Bạn có thể đạt được điều đó bằng cách sử dụng SVG.

Nó phụ thuộc vào một trường hợp, nhưng trong một số nó thực sự hữu ích. Ví dụ: bạn có thể đặt background-imagemà không đặt chiều cao cố định hoặc sử dụng nó để nhúng youtube <iframe>với tỷ lệ 16:9, position:absolutev.v.

Đối với 3:2tỷ lệ thiết lập viewBox="0 0 3 2"và như vậy.

Thí dụ:

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>


2

Giả sử bạn muốn duy trì Width: 100px và height: 50px (nghĩa là 2: 1) Chỉ cần làm toán này:

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

1

Bạn có thể sử dụng bố trí thông lượng (FWD).

https://en.wikipedia.org/wiki/Adaptive_web_design

Nó sẽ mở rộng và duy trì bố cục, hơi phức tạp nhưng cho phép một trang thay đổi kích thước mà không cần đẩy nội dung như (RWD).

Có vẻ như đáp ứng nhưng nó đang mở rộng. https://www.youtube.com/watch?v=xRcBMLI4jbg

Bạn có thể tìm thấy công thức chia tỷ lệ CSS tại đây:

http://plugnedit.com/pnew/928-2/


Làm thế nào để trả lời câu hỏi này?
Flimm

1

Một cách đơn giản để duy trì tỷ lệ khung hình, sử dụng phần tử canvas.

Hãy thử thay đổi kích thước div bên dưới để xem nó hoạt động.

Đối với tôi, phương pháp này hoạt động tốt nhất, vì vậy tôi đang chia sẻ nó với những người khác để họ cũng có thể hưởng lợi từ nó.

.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>

Cũng hoạt động với chiều cao năng động!

.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>


yup đã giúp tôi, giờ tôi có thể sử dụng nó để thiết lập hình ảnh div chiều cao cha mẹ)
Alex

0

Tôi đã sử dụng một giải pháp mới.

.squares{
  width: 30vw
  height: 30vw

Tỷ lệ khung hình chính

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

Tuy nhiên, điều này là liên quan đến toàn bộ khung nhìn. Vì vậy, nếu bạn cần một div chiếm 30% chiều rộng khung nhìn, bạn có thể sử dụng 30vw thay vào đó và vì bạn biết chiều rộng, bạn sử dụng lại chúng theo chiều cao bằng cách sử dụng đơn vị calc và vw.


7
Đây không phải là chính xác những gì câu trả lời được xếp hạng cao thứ hai đã được nêu ra?
rnevius


-4

Nếu toàn bộ cấu trúc container dựa trên tỷ lệ phần trăm, đây sẽ là hành vi mặc định, bạn có thể cung cấp một ví dụ cụ thể hơn không?

Dưới đây là một ví dụ về ý tôi muốn nói, nếu toàn bộ hệ thống phân cấp cha mẹ của bạn dựa trên%, mọi điều chỉnh cửa sổ trình duyệt sẽ hoạt động mà không cần thêm js / css, đây có phải là khả năng với bố cục của bạn không?

<div style="width: 100%;">
   <div style="width: 50%; margin: 0 auto;">Content</div>
</div>

1
Xem chỉnh sửa của tôi cho câu hỏi ban đầu. Tôi không thấy kỹ thuật này sẽ giữ tỷ lệ khung hình ở đâu, chiều cao sẽ không thay đổi.
jackb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.