รักษาอัตราส่วนภาพของ div ด้วย CSS


1058

ฉันต้องการสร้าง divที่สามารถเปลี่ยนความกว้าง / ความสูงได้เมื่อความกว้างของหน้าต่างเปลี่ยนไป

มีกฎ CSS3 ใด ๆ ที่จะช่วยให้ความสูงในการเปลี่ยนแปลงตามความกว้างในขณะที่รักษาอัตราส่วน ?

ฉันรู้ว่าฉันสามารถทำได้ผ่าน JavaScript แต่ฉันต้องการใช้ CSS เท่านั้น

div รักษาอัตราส่วนตามความกว้างของหน้าต่าง


2
ฉันเขียนเกี่ยวกับวิธีการต่าง ๆ ในบทความ CSS-Tricks ของฉันเกี่ยวกับการปรับขนาดของภาพเคลื่อนไหวที่ตอบสนองได้ดี
Zach Saucier

2
ฉันมาถามคำถามนี้ช้ามาก แต่ฉันต้องแสดงความคิดเห็น แม้ว่ามันจะถูกลงโทษทางวินัยมากและภายใต้กฎ SO ของทุกคนที่พยายามตอบสนองอย่างดีที่สุดเพื่อตอบสนองความต้องการของ "CSS เท่านั้น" ของคำถามมันค่อนข้างน่าแปลกใจที่มีข้อยกเว้นของคำตอบของ user007ต่ำลงบนหน้า หนึ่งได้กล่าวถึงชัดเจน: ไม่มีวิธีแก้ปัญหา CSS เท่านั้นที่เชื่อถือได้ปัญหานี้ต้องใช้ Javascript มือใหม่ที่มาที่หน้านี้อาจเสียเวลาอันมีค่าในการเปลี่ยนจากข้อดี / ข้อเสียหนึ่งชุดไปอีกชุดหนึ่งก่อนที่หลอดไฟจะดับลง: CSS-only จะไม่ทำ
Theo d'Or

1
ผมเขียนเป็นเครื่องมือเล็ก ๆ น้อย ๆ ที่ทำให้มันเป็นเรื่องง่ายที่จะแสดงตัวอย่างและด้านการคำนวณอัตราส่วนaspectrat.io นอกจากนี้ยังสร้างรหัส CSS / Sass / Less ที่เหมาะสมที่คุณสามารถคัดลอกและวางในโครงการของคุณ หวังว่าผู้คนจะพบว่ามันมีประโยชน์
Ryan Hefner

ดูตัวอย่างนี้: w3schools.com/howto/howto_css_aspect_ratio.asp ..... ที่ได้ผลฉัน
Cristian Agudelo

1
คำถามนี้เป็นคำถามสำหรับการตั้งค่าความสูงขึ้นอยู่กับความกว้าง หากคุณต้องการตรงข้ามให้ตรวจสอบการตั้งค่าองค์ประกอบความกว้างบนพื้นฐานของความสูงผ่านทาง CSS
John Mellor

คำตอบ:


1353

เพียงสร้าง wrapper ที่<div>มีค่าเปอร์เซ็นต์สำหรับpadding-bottomเช่นนี้

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>

มันจะส่งผลใน <div>มีความสูงเท่ากับ 75% ของความกว้างของภาชนะ (อัตราส่วน 4: 3)

สิ่งนี้ขึ้นอยู่กับข้อเท็จจริงที่ว่าสำหรับการขยาย:

เปอร์เซ็นต์จะคำนวณโดยเทียบกับความกว้างของบล็อกที่มีกล่องที่สร้างขึ้น [... ] (แหล่งที่มา: w3.org , เหมืองที่เน้น)

ค่า Padding-bottom สำหรับอัตราส่วนภาพอื่น ๆ และความกว้าง 100%:

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

การวางเนื้อหาใน div:

เพื่อที่จะรักษาอัตราส่วนกว้างยาวของ div และป้องกันเนื้อหาไม่ให้ยืดออกคุณจำเป็นต้องเพิ่มลูกที่อยู่ในตำแหน่งที่แน่นอนและยืดลงไปที่ขอบของ wrapper ด้วย:

div.stretchy-wrapper {
  position: relative;
}

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

นี่คือการสาธิตและอื่น ๆ เพิ่มเติมในเชิงลึกสาธิต


29
@schellmax เป็นเพราะ padding% คำนวณโดยสัมพันธ์กับความกว้างขององค์ประกอบปัจจุบันโดยที่ความสูง% ถูกคำนวณเทียบกับความสูงขององค์ประกอบหลัก นอกจากนี้ตำแหน่งสัมบูรณ์จะถูกคำนวณเทียบกับคอนเทนเนอร์ภายนอกขององค์ประกอบซึ่งรวมถึงพื้นที่การขยาย สำหรับข้อมูลเพิ่มเติม Google "CSS Box Model"
Anson Kao

11
สิ่งนี้ดูเหมือนจะไม่ทำงานในลักษณะซ้อนกัน มันใช้งานได้ในระดับแรก แต่เมื่อพยายามทำสิ่งเดียวกันภายในอัตราส่วนการคงสัดส่วน div เปอร์เซ็นต์การเติมด้านล่างน่าจะนำไปใช้กับความกว้างของพาเรนต์ นี่คือตัวอย่างที่. stretchy-wrap.onethird padding-bottom 25% เป็น 25% ของความกว้างหลัก มีคนอธิบายเรื่องนี้ได้ไหม
Misterparker

4
สุดยอดไปเลย. มันกำลังฆ่าฉันว่าเทคนิคนี้จะไม่ทำงานเมื่อคุณต้องการแก้ไขความสูงที่ 100% @Misterparker เทคนิคขึ้นอยู่กับความกว้างและการคำนวณการแพ็ดที่ดำเนินการกับการอ้างอิงเดียวกัน; คุณไม่สามารถใช้ความกว้างน้อยกว่า 100% ตามที่คุณมีในตัวอย่าง
steveluscher

2
@Misterparker ใช่การเติมเปอร์เซ็นต์จะคำนวณตามสัดส่วนของความกว้างขององค์ประกอบหลัก ดูตัวอย่างเชิงลึกเพิ่มเติมที่ฉันโพสต์ในการแก้ไขคำตอบของฉัน การสาธิตที่อัปเดตของฉันแสดงให้เห็นถึง 'แฟชั่นซ้อน' ตามที่คุณพูด
Web_Designer

3
ความจริงที่ว่าเขาได้แสดงให้เห็นว่างานนี้เพียงพอที่จะโน้มน้าวใจฉันว่านี่เป็นคำตอบที่ดีที่สุดที่ฉันเคยเห็นใน SO ส่งเสียงถึงชายของฉัน @Web_Designer

411

vw หน่วย:

คุณสามารถใช้vwหน่วยทั้งความกว้างและความสูงขององค์ประกอบ สิ่งนี้อนุญาตให้รักษาอัตราส่วนองค์ประกอบขององค์ประกอบตามความกว้างของวิวพอร์ต

vw: 1/100 ของความกว้างของวิวพอร์ต [ MDN ]

อีกทางหนึ่งคุณสามารถใช้vhสำหรับความสูงวิวพอร์ตหรือแม้กระทั่งvmin/ vmaxเพื่อใช้มิติวิวพอร์ตที่น้อยกว่า / สูงกว่า (การอภิปรายที่นี่ )

ตัวอย่าง: อัตราส่วน 1: 1

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

สำหรับอัตราส่วนอื่น ๆ คุณสามารถใช้ตารางต่อไปนี้เพื่อคำนวณค่าความสูงตามความกว้างขององค์ประกอบ:

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

ตัวอย่าง: 4x4 grid ของ square divs

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>

นี่คือซอกับการสาธิตนี้และนี่คือวิธีการแก้ปัญหาที่จะทำให้ตารางการตอบสนองของสี่เหลี่ยมที่มีเนื้อหา verticaly และ horizontaly ศูนย์กลาง


การสนับสนุนเบราว์เซอร์สำหรับหน่วย vh / vw คือ IE9 + ดูcanIuse สำหรับข้อมูลเพิ่มเติม


14
นี่ควรเป็นคำตอบที่ยอมรับได้ อาจไม่ใช่ตอนนี้ แต่ในอนาคต หน่วย VW มีการสนับสนุนในเบราว์เซอร์มากที่สุดตอนนี้
ส.ค.

3
@vivekmaharajh ทั้งสองเทคนิคนั้นดีแต่ละคนมีข้อดีและข้อเสียของตัวเอง การใช้รายการใดรายการหนึ่งขึ้นอยู่กับสถานการณ์เป็นอย่างมาก
web-tiki

11
@ web-tiki คุณพูดถูก ฉันพบปัญหาเดียว - ถือว่าความกว้างขององค์ประกอบนั้นเป็นสัดส่วนกับความกว้างของวิวพอร์ตซึ่งจะไม่เกิดขึ้นหาก 1) คุณมีสิ่งต่าง ๆ เช่นท่อระบายความกว้างคงที่หรือ 2) คุณตั้งค่าความกว้างสูงสุด สำหรับองค์ประกอบบางอย่างของคุณ
Vivek Maharajh

1
อาจเป็นเพียง Chrome v47beta แต่เมื่อฉันตั้งค่า div เป็นwidth:50%และheight:50vwความสูงนั้นสูงกว่าความกว้างเล็กน้อยเล็กน้อยดังนั้นจึงไม่ใช่สัดส่วน 1: 1 ความคิดใด ๆ
thdoan

2
@ 10basetom มันเป็นพฤติกรรมปกติ หน่วย vw มีความกว้างของแถบเลื่อนในขณะที่% ความกว้างไม่ได้ ความแตกต่างระหว่างความสูงและความกว้างจะขึ้นอยู่กับขนาดของแถบเลื่อนซึ่งแตกต่างกันไปตามเบราว์เซอร์
web-tiki

26

ฉันพบวิธีการทำสิ่งนี้โดยใช้ CSS แต่คุณต้องระวังเพราะอาจเปลี่ยนแปลงได้ขึ้นอยู่กับการไหลของเว็บไซต์ของคุณเอง ฉันได้ทำไปแล้วเพื่อฝังวิดีโอด้วยอัตราส่วนคงที่ภายในส่วนความกว้างของเว็บไซต์ของฉัน

สมมติว่าคุณมีวิดีโอแบบฝังนี้:

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

คุณสามารถวางทั้งหมดนี้ไว้ใน div ด้วยคลาส "วิดีโอ" คลาสวิดีโอนี้อาจเป็นองค์ประกอบที่เป็นของเหลวในเว็บไซต์ของคุณเองโดยที่มันไม่มีข้อจำกัดความสูงโดยตรง แต่เมื่อคุณปรับขนาดเบราว์เซอร์จะเปลี่ยนความกว้างตามการไหลของเว็บไซต์ นี่เป็นองค์ประกอบที่คุณอาจลองรับวิดีโอที่ฝังไว้ในขณะที่ยังคงรักษาอัตราส่วนภาพของวิดีโอไว้

เพื่อที่จะทำสิ่งนี้ฉันใส่ภาพก่อนวัตถุฝังตัวใน div class "วิดีโอ"

!!! ส่วนที่สำคัญคือภาพมีอัตราส่วนภาพที่ถูกต้องที่คุณต้องการบำรุงรักษา นอกจากนี้ตรวจสอบให้แน่ใจว่าขนาดของภาพเป็นอย่างน้อยใหญ่ที่สุดเท่าที่เล็กที่สุดที่คุณคาดหวังวิดีโอ (หรืออะไรก็ตามที่คุณรักษา AR ของ) เพื่อให้ได้ตามเค้าโครงของคุณ สิ่งนี้จะหลีกเลี่ยงปัญหาที่อาจเกิดขึ้นในความละเอียดของภาพเมื่อมีการปรับขนาดเป็นเปอร์เซ็นต์ ตัวอย่างเช่นหากคุณต้องการรักษาอัตราส่วนภาพไว้ที่ 3: 2 อย่าใช้ภาพ 3px คูณ 2px มันอาจทำงานภายใต้สถานการณ์บางอย่าง แต่ฉันไม่ได้ทดสอบและอาจเป็นความคิดที่ดีที่จะหลีกเลี่ยง

คุณน่าจะมีความกว้างขั้นต่ำเช่นนี้ที่กำหนดไว้สำหรับองค์ประกอบของเหลวในเว็บไซต์ของคุณ หากไม่เป็นเช่นนั้นเป็นความคิดที่ดีที่จะทำเช่นนั้นเพื่อหลีกเลี่ยงการตัดองค์ประกอบหรือมีการทับซ้อนกันเมื่อหน้าต่างเบราว์เซอร์มีขนาดเล็กเกินไป มันจะดีกว่าที่จะมีแถบเลื่อนในบางจุด ความกว้างของหน้าเว็บที่เล็กที่สุดควรอยู่ที่ประมาณ ~ 600px (รวมถึงคอลัมน์ที่มีความกว้างคงที่) เนื่องจากความละเอียดหน้าจอจะไม่เล็กลงเว้นแต่คุณจะจัดการกับเว็บไซต์ที่เป็นมิตรกับโทรศัพท์ !!!

ฉันใช้ png โปร่งใสอย่างสมบูรณ์ แต่ฉันไม่คิดว่ามันจะจบลงถ้าคุณทำถูกต้อง แบบนี้:

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

ตอนนี้คุณควรจะสามารถเพิ่ม CSS ได้ดังต่อไปนี้:

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

ตรวจสอบให้แน่ใจว่าคุณได้ลบประกาศความสูงหรือความกว้างที่ชัดเจนภายในวัตถุและแท็กฝังที่มักจะมาพร้อมกับรหัสฝัง / คัดลอก

วิธีการทำงานขึ้นอยู่กับคุณสมบัติตำแหน่งขององค์ประกอบคลาสวิดีโอและรายการที่คุณต้องการคงไว้ซึ่งอัตราส่วนภาพที่แน่นอน มันใช้ประโยชน์จากวิธีที่ภาพจะรักษาอัตราส่วนที่เหมาะสมเมื่อปรับขนาดในองค์ประกอบ มันบอกสิ่งอื่นใดที่อยู่ในองค์ประกอบคลาสวิดีโอเพื่อใช้ประโยชน์จากอสังหาริมทรัพย์ที่มีให้โดยรูปภาพแบบไดนามิกโดยบังคับให้ความกว้าง / ความสูงเป็น 100% ขององค์ประกอบวิดีโอคลาสที่ปรับด้วยรูปภาพ

ค่อนข้างเท่ห์ใช่มั้ย

คุณอาจต้องเล่นกับมันสักหน่อยเพื่อให้มันทำงานกับการออกแบบของคุณเอง แต่มันใช้งานได้ดีจริง ๆ สำหรับฉัน แนวคิดทั่วไปอยู่ที่นั่น


17

เอลเลียตเป็นแรงบันดาลใจให้ฉันแก้ปัญหานี้ - ขอบคุณ:

aspectratio.png เป็นไฟล์ PNG โปร่งใสที่สมบูรณ์ขนาดของอัตราส่วนภาพที่คุณต้องการในกรณีของฉัน 30x10 พิกเซล

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

โปรดทราบ: background-sizeเป็นคุณสมบัติ css3 ซึ่งอาจไม่สามารถใช้งานได้กับเบราว์เซอร์เป้าหมายของคุณ คุณสามารถตรวจสอบการทำงานร่วมกัน (fe บนcaniuse.com )


14

เพื่อเพิ่มการตอบ Web_Designer ของที่<div>จะต้องมีความสูง (ทำขึ้นของการขยายด้านล่าง) 75% ของความกว้างของมันมีองค์ประกอบ นี่เป็นบทสรุปที่ดี: http://mattsnider.com/css-using-percent-for-margin-and-padding/ http://mattsnider.com/css-using-percent-for-margin-and-padding/ฉันไม่แน่ใจว่าทำไมจึงควรเป็นเช่นนั้น แต่นั่นเป็นวิธี

หากคุณต้องการให้ div ของคุณเป็นความกว้างอื่นที่ไม่ใช่ 100% คุณจะต้อง div div อื่นที่จะตั้งค่าความกว้าง:

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

ฉันใช้สิ่งที่คล้ายกับภาพหลอกของ Elliot เมื่อเร็ว ๆ นี้เพื่อให้ฉันใช้แบบสอบถามสื่อ CSS เพื่อให้บริการไฟล์โลโก้ที่แตกต่างกันขึ้นอยู่กับความละเอียดของอุปกรณ์ แต่ยังคงสัดส่วนตามที่<img>ควรจะเป็นธรรมชาติ ด้วยอัตราส่วนภาพที่ถูกต้อง) แต่โซลูชันของ Web_Designer จะช่วยฉันในการร้องขอ http


ทางออกที่ดี ในกรณีของฉันฉันรู้ขนาดภาพ "เป็นธรรมชาติ" เมื่อวางลงใน DOM และฉันต้องมีตัวยึดรูปภาพที่มีความสูงที่เหมาะสมเพื่อป้องกันการเลื่อนเพิ่มเติมเมื่อเบราว์เซอร์โหลดภาพ ใน. ภายนอกฉันมีความกว้างของภาพเป็นพิกเซลและใน. ar ฉันมีช่องว่างด้านล่างคำนวณจากอัตราส่วนภาพจริง แทนที่จะเป็นภายในฉันมีภาพตัวเอง (<img>) อย่างไรก็ตามฉันต้องตั้งค่าความกว้างเป็น 100% แทนที่จะตั้งค่าบนสุดด้านล่างซ้ายและขวา เมื่อฉันตั้งค่า maxWidth เป็น ar-outer รูปภาพจะปรับขนาดได้ดีเมื่อผู้ปกครองมีขนาดเล็ก แต่ไม่ปรับขนาดให้ใหญ่กว่าขนาดที่เป็นธรรมชาติ
Mi-La

13

ตามที่ระบุไว้ในที่นี่ใน w3schools.comและค่อนข้างจะย้ำในคำตอบที่ได้รับการยอมรับค่า padding นี้เป็นเปอร์เซ็นต์ (เน้นที่เหมือง):

ระบุการขยายเป็นเปอร์เซ็นต์ของความกว้างขององค์ประกอบที่มี

Ergo ตัวอย่างที่ถูกต้องของ DIV ที่ตอบสนองต่อการรักษาอัตราส่วนภาพ 16: 9 เป็นดังนี้:

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>

การสาธิตเกี่ยวกับ JSFiddle


13

ในฐานะที่เป็น @ web-tiki แสดงวิธีการใช้vh/ vwแล้วฉันยังต้องการวิธีการศูนย์ในหน้าจอนี่คือรหัสตัวอย่างสำหรับภาพบุคคล9:16

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

translateYจะทำให้ศูนย์กลางนี้อยู่ในหน้าจอ calc(100vw * 16 / 9)คาดว่าความสูงสำหรับ 9/16 (100vw * 16 / 9 - 100vh)มีความสูงมากเกินดังนั้นการดึงขึ้นoverflow height/2จะทำให้อยู่กึ่งกลางหน้าจอ

สำหรับแนวนอนและให้16: 9คุณแสดงการใช้งาน

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

อัตราส่วน 9/16 นั้นง่ายต่อการเปลี่ยนแปลงไม่จำเป็นต้องกำหนดไว้ล่วงหน้า100:56.25หรือ100:75หากคุณต้องการให้แน่ใจว่ามีความสูงก่อนคุณควรสลับความกว้างและความสูงเช่นheight:100vh;width: calc(100vh * 9 / 16)สำหรับภาพบุคคล 9:16

หากคุณต้องการปรับขนาดหน้าจอที่แตกต่างกันคุณอาจสนใจ

  • ปก / บรรจุ ขนาดพื้นหลัง
    • สไตล์ด้านบนคล้ายกับการบรรจุขึ้นอยู่กับอัตราส่วนความกว้าง: ความสูง
  • วัตถุพอดี
    • หน้าปก / บรรจุสำหรับ img / แท็กวิดีโอ
  • @media (orientation: portrait)/@media (orientation: landscape)
    • แบบสอบถามสื่อสำหรับportrait/ landscapeเพื่อเปลี่ยนอัตราส่วน

11

นี่คือการปรับปรุงคำตอบที่ได้รับการยอมรับ:

  • ใช้องค์ประกอบปลอมแทน divpper
  • อัตราส่วนกว้างยาวขึ้นอยู่กับความกว้างของกล่องแทนพาเรนต์
  • กล่องจะยืดในแนวตั้งเมื่อเนื้อหาสูงขึ้น

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


วิธีการปิดการใช้งานการยืดแนวตั้งของกล่อง? นักพูดที่ยืดออกอย่างเข้มงวดไม่ได้รักษาอัตราส่วนของมัน
florian

หากเนื้อหาสูงกว่าความสูงที่คาดไว้กล่องจะยืดในแนวตั้ง แนวคิดนี้ใช้กับเนื้อหาที่สามารถยืดให้เหมาะกับขนาดของผู้ปกครองเช่นวิดีโอและรูปภาพ
Salman

10

ฉัน stumbled เมื่อวิธีการแก้ปัญหาสมาร์ทใช้และ<svg>display:grid

องค์ประกอบกริดช่วยให้คุณสามารถครอบครองพื้นที่เดียวกันกับองค์ประกอบสอง (หรือมากกว่า) โดยไม่จำเป็นต้องระบุว่าชุดใดมีความสูง ซึ่งหมายความว่าออกจากกล่องที่สูงของหนึ่งชุดอัตราส่วน

ซึ่งหมายความว่าคุณสามารถใช้งานได้เช่นเมื่อคุณรู้ว่าเนื้อหาจะไม่สูงพอที่จะเติม "อัตราส่วน" ทั้งหมดและคุณเพียงแค่มองหาวิธีการวางตำแหน่งเนื้อหาในพื้นที่นี้ (เช่นเพื่อให้อยู่กึ่งกลางทั้งสองทิศทาง) display:flex; align-items:center; justify-content:center)
มันสวยมากเช่นเดียวกับการใช้ความโปร่งใส<img>ด้วยdisplay:blockและอัตราที่กำหนดไว้ยกเว้น<svg>มีน้ำหนักเบามากและง่ายต่อการปรับเปลี่ยน (การเปลี่ยนแปลงอัตราส่วน responsively คุณควรต้อง)

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

สิ่งที่คุณต้องทำคือเปลี่ยน<svg>อัตราส่วน s:

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

เห็นมันทำงาน:


หากคุณต้องการโซลูชันที่องค์ประกอบเนื้อหาไม่ได้รับอนุญาตให้กำหนดอัตราส่วนเมื่อสูงกว่า (ที่ซ่อนอยู่มากเกินหรือซ่อนอัตโนมัติ) คุณจะต้องตั้งค่าposition:relativeบนกริดและposition:absolute; height:100%; overflow-y: auto;บนเนื้อหา ตัวอย่าง:


9

การอ้างอิงโซลูชันของคุณฉันได้ทำการหลอกลวง:

เมื่อคุณใช้ HTML ของคุณจะเป็นเพียง

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

วิธีใช้ด้วยวิธีนี้สร้าง: CSS:

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

และ js (jQuery)

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

และเมื่อมีสิ่งนี้คุณเพียงแค่ตั้งค่าdata-keep-ratioความสูง / ความกว้างและนั่นก็คือ


3
คุณควรใช้data-keep-ratioไม่ได้keep-ratioและได้รับความคุ้มค่าของมันโดยใช้$(this).data('keep-ratio');
โรเบิร์ต

รหัสของคุณใช้งานได้ในขณะนี้และอาจใช้งานได้ตลอดไป แต่ไม่ใช่มาตรฐานและเบราว์เซอร์อาจหยุดการสนับสนุนได้ตลอดเวลาในอนาคต
Robert

1
การใช้ JS ที่นี่จะทำให้เกิดข่าวร้าย!
Amir Hossein Ahmadi

8

คุณสามารถใช้ svg ทำให้ตำแหน่งของคอนเทนเนอร์ / wrapper สัมพันธ์กันวาง svg ก่อนเป็นตำแหน่งแบบคงที่จากนั้นใส่เนื้อหาที่จัดวางไว้อย่างแน่นอน (ด้านบน: 0; ซ้าย: 0; ขวา: 0; bottom: 0;)

ตัวอย่างที่มีสัดส่วน 16: 9:

image.svg: (สามารถ inlined ใน 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>

โปรดทราบว่า inline svg ดูเหมือนจะไม่ทำงาน แต่คุณสามารถ urlencode svg และฝังไว้ในคุณลักษณะ img src ดังนี้:

<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 เป็นทางออกที่ดีที่สุดในกรณีของฉัน; ใช้แอตทริบิวต์ 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%;
}

ตัวอย่างเช่น :

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

แหล่ง


15
แค่ FYI ... คุณสามารถทำสิ่งนี้ได้อย่างแน่นอน (ใช้ตัวเลือกแอททริบิวต์) ในจำนวนบรรทัดที่เท่ากันโดยใช้ CSS ธรรมดา [data-aspect-ratio]เลือกแอตทริบิวต์สามารถใช้ได้กับคุณใน CSS
rnevius

6

ในขณะที่คำตอบส่วนใหญ่จะเจ๋งมาก แต่ส่วนใหญ่ต้องการให้มีขนาดภาพที่ถูกต้องแล้ว ... โซลูชันอื่น ๆ ใช้สำหรับความกว้างและไม่สนใจความสูงที่มี แต่บางครั้งคุณต้องการให้พอดีกับเนื้อหาในความสูงที่แน่นอน .

ฉันได้ลองจับคู่เข้าด้วยกันเพื่อนำโซลูชันที่ปรับขนาดได้และพกพาได้อย่างสมบูรณ์แบบ ... เคล็ดลับคือการใช้การปรับขนาดของภาพโดยอัตโนมัติ แต่ใช้องค์ประกอบ svg แบบอินไลน์แทนการใช้ภาพที่แสดงล่วงหน้าหรือรูปแบบ คำขอ HTTP ที่สอง ...

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>

โปรดสังเกตว่าฉันใช้ค่าขนาดใหญ่ในแอตทริบิวต์ความกว้างและความสูงของ SVG เนื่องจากจำเป็นต้องมีขนาดใหญ่กว่าขนาดสูงสุดที่คาดไว้เนื่องจากสามารถลดขนาดลงได้เท่านั้น ตัวอย่างทำให้อัตราส่วนของ div 10: 5


4

แค่ความคิดหรือแฮ็ค

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>


นี่ไม่ใช่วิธีแก้ปัญหา CSS เท่านั้น ... ทีนี้ถ้าคุณจะใช้อิมเมจที่เข้ารหัส base64 ในองค์ประกอบแบบหลอกมันน่าจะเป็นทางออกที่ยอดเยี่ยม
rnevius

1
ไม่มีโซลูชัน CSS-only จริงๆ HTML เป็นองค์ประกอบพื้นฐานของเว็บ ฉันเชื่อว่าจุดประสงค์ของคำถามคืองดใช้ JS เพื่อประหยัดทรัพยากร / การประมวลผล
orlland

ฉันไม่แน่ใจว่าองค์ประกอบหลอกจะใช้งานได้หรือไม่ ฉันใช้คุณสมบัติขององค์ประกอบ img เพื่อรักษาอัตราส่วนสำหรับโซลูชันนี้ในการทำงาน
orlland

ดี แต่มันจะคำนวณความสูงเฉพาะเมื่อความกว้างเปลี่ยนไป มันควรทำทั้งสองอย่างดังนั้นเมื่อฉันลดความสูงความกว้างก็จะคำนวณอีกครั้ง มิฉะนั้นมันก็ไร้ประโยชน์ ..
Ωmega

4

สมมติว่าคุณมี 2 divs div outher เป็นคอนเทนเนอร์และด้านในอาจเป็นองค์ประกอบใด ๆ ที่คุณต้องรักษาอัตราส่วนไว้ (img หรือ iframe youtube หรืออะไรก็ตาม)

html มีลักษณะดังนี้:

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

สมมติว่าคุณต้องรักษาอัตราส่วนของ "องค์ประกอบ"

อัตราส่วน => 4 ถึง 1 หรือ 2 ต่อ 1 ...

css หน้าตาแบบนี้

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

การเติมเต็มเมื่อระบุเป็น% จะคำนวณจากความกว้างไม่ใช่ความสูง .. ดังนั้นโดยทั่วไปคุณไม่สำคัญว่าความกว้างของคุณความสูงนั้นจะถูกคำนวณตามนั้น ซึ่งจะทำให้อัตราส่วน


4

หากคุณต้องการให้พอดีกับสี่เหลี่ยมในวิวพอร์ตในมุมมองแนวตั้งหรือแนวนอน (ใหญ่ที่สุดเท่าที่จะเป็นไปได้ แต่ไม่มีอะไรติดด้านนอก) ให้สลับระหว่างการใช้vw/ vhบนการวางแนวportrait/ landscape:

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

4

ฉันต้องการแบ่งปันวิธีแก้ปัญหาของฉันซึ่งฉันมี - imgแท็กเติมอัตราส่วนภาพที่แน่นอน ฉันไม่สามารถใช้backgroundเพราะขาดการสนับสนุนของ CMS <img style="background:url(...)" />และฉันไม่ชอบที่จะใช้แท็กสไตล์ชอบโดย: นอกจากนี้ความกว้างคือ 100% ดังนั้นจึงไม่จำเป็นต้องตั้งค่าขนาดคงที่ในโซลูชันบางตัว มันจะขยายการตอบสนอง!

.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

ฉันพบปัญหานี้หลายครั้งดังนั้นฉันจึงทำโซลูชัน JS สำหรับมัน โดยทั่วไปจะปรับความสูงของ domElement ตามความกว้างขององค์ประกอบตามอัตราส่วนที่คุณระบุ คุณสามารถใช้มันได้ดังต่อไปนี้:

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

โปรดทราบว่าเพราะมันคือการตั้งค่าความสูงขององค์ประกอบองค์ประกอบที่ควรจะเป็นอย่างใดอย่างหนึ่งหรือdisplay:blockdisplay:inline-block

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


1
แม้ว่าฉันจะไม่ได้เห็นหรือลองใช้รหัสของคุณ (ฉันมีของตัวเองอยู่แล้ว) แต่ฉันได้เพิ่มคำตอบให้กับคุณเพราะคุณนำเสนอโซลูชัน JS ที่น่าเชื่อถือเท่านั้น
Theo d'Or

คำถามที่ถามมาโดยเฉพาะสำหรับวิธีแก้ปัญหาที่ไม่ต้องการ Javascript
Flimm

2

คุณสามารถทำได้โดยใช้ SVG

มันขึ้นอยู่กับกรณี แต่ในบางอย่างมันมีประโยชน์จริงๆ ตัวอย่าง - คุณสามารถตั้งค่าได้background-imageโดยไม่ต้องตั้งค่าความสูงคงที่หรือใช้เพื่อฝัง youtube <iframe>ด้วยอัตราส่วน16:9และposition:absoluteอื่น ๆ

สำหรับการ3:2ตั้งค่าอัตราส่วนviewBox="0 0 3 2"เป็นต้น

ตัวอย่าง:

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

พูดได้ว่าคุณชอบที่จะรักษาความกว้าง: 100px และความสูง: 50px (เช่น 2: 1) เพียงทำคณิตศาสตร์นี้:

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

1

คุณสามารถใช้เค้าโครงฟลักซ์ (FWD)

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

มันจะปรับขนาดและบำรุงรักษาเค้าโครงมันซับซ้อนเล็กน้อย แต่ช่วยให้หน้าปรับขนาดโดยไม่ต้องผลักดันเนื้อหาเช่น (RWD)

ดูเหมือนว่าจะตอบสนองได้ แต่มันก็เป็นการปรับขนาด https://www.youtube.com/watch?v=xRcBMLI4jbg

คุณสามารถค้นหาสูตรการปรับขนาด CSS ได้ที่นี่:

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


คำถามนี้จะตอบคำถามได้อย่างไร
Flimm

1

วิธีง่ายๆในการรักษาอัตราส่วนภาพโดยใช้องค์ประกอบ Canvas

ลองปรับขนาด div ด้านล่างเพื่อดูการทำงาน

สำหรับฉันวิธีนี้ใช้ได้ดีที่สุดดังนั้นฉันจึงแบ่งปันกับผู้อื่นเพื่อให้พวกเขาได้รับประโยชน์จากมันเช่นกัน

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

ใช้ได้กับความสูงแบบไดนามิก!

.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 ช่วยสำหรับฉันตอนนี้ฉันสามารถใช้มันเพื่อตั้งค่าความสูง div ภาพของผู้ปกครอง)
อเล็กซ์

0

ฉันใช้โซลูชันใหม่

.squares{
  width: 30vw
  height: 30vw

ถึงอัตราส่วนภาพหลัก

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

อย่างไรก็ตามนี่สัมพันธ์กับวิวพอร์ตทั้งหมด ดังนั้นหากคุณต้องการ div ที่เป็น 30% ของความกว้างวิวพอร์ตคุณสามารถใช้ 30vw แทนและเมื่อคุณทราบความกว้างคุณสามารถนำมาใช้ใหม่ได้โดยใช้หน่วย calc และ vw


7
นี่ไม่ใช่คำตอบที่ได้รับคะแนนสูงสุดอันดับที่สองที่ระบุไว้แล้วหรือไม่
rnevius


-4

หากโครงสร้างคอนเทนเนอร์ทั้งหมดเป็นเปอร์เซ็นต์ตามนี้จะเป็นพฤติกรรมเริ่มต้นคุณสามารถให้ตัวอย่างที่เฉพาะเจาะจงมากขึ้น?

ด้านล่างเป็นตัวอย่างของสิ่งที่ฉันหมายถึงถ้าลำดับชั้นของผู้ปกครองทั้งหมดของคุณเป็นไปตาม% การปรับหน้าต่างเบราว์เซอร์ใด ๆ จะทำงานได้โดยไม่ต้องมี js / css เพิ่มเติมนี่เป็นไปไม่ได้กับการจัดวางของคุณหรือไม่

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

1
ดูการแก้ไขคำถามเดิมของฉัน ฉันไม่เห็นว่าเทคนิคนี้จะรักษาอัตราส่วนภาพไว้ที่ใดความสูงจะไม่เปลี่ยนแปลง
jackb
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.