พร็อพเพอร์ตี้สัดส่วนภาพ CSS

พร็อพเพอร์ตี้ CSS ที่ช่วยรักษาระยะห่างในเลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์

สัดส่วนภาพ

Browser Support

  • Chrome: 88.
  • Edge: 88.
  • Firefox: 89.
  • Safari: 15.

Source

โดยทั่วไปแล้ว สัดส่วนภาพจะแสดงเป็นจำนวนเต็ม 2 จำนวนและเครื่องหมายโคลอนในมิติข้อมูลของ ความกว้าง:ความสูง หรือ x:y สัดส่วนภาพที่พบบ่อยที่สุดสำหรับการถ่ายภาพคือ 4:3 และ 3:2 ส่วนวิดีโอ และกล้องสำหรับผู้บริโภคที่ใหม่กว่ามักจะมีสัดส่วนภาพ 16:9

รูปภาพ 2 รูปที่มีสัดส่วนภาพเดียวกัน ภาพหนึ่งมีขนาด 634 x 951 พิกเซล ส่วนอีกภาพมีขนาด 200 x 300 พิกเซล ทั้ง 2 รูปแบบมีสัดส่วนภาพ 2:3
รูปภาพ 2 รูปที่มีสัดส่วนภาพเดียวกัน ภาพหนึ่งมีขนาด 634 x 951 พิกเซล ส่วนอีกภาพมีขนาด 200 x 300 พิกเซล ทั้ง 2 รูปแบบมีสัดส่วนภาพ 2:3

เมื่อการออกแบบที่ปรับเปลี่ยนตามพื้นที่โฆษณาเข้ามามีบทบาท การรักษาสัดส่วนภาพจึงมีความสำคัญมากขึ้นสำหรับ นักพัฒนาเว็บ โดยเฉพาะอย่างยิ่งเมื่อขนาดรูปภาพแตกต่างกันและขนาดองค์ประกอบเปลี่ยนไปตามพื้นที่ ที่มี

ตัวอย่างบางส่วนที่การรักษาอัตราส่วนภาพมีความสำคัญมีดังนี้

  • การสร้าง iframe ที่ปรับเปลี่ยนตามอุปกรณ์ ซึ่งมีความกว้าง 100% ขององค์ประกอบระดับบนสุด และความสูงควรคงอัตราส่วนวิวพอร์ตที่เฉพาะเจาะจงไว้
  • สร้างคอนเทนเนอร์ตัวยึดตำแหน่งโดยธรรมชาติสำหรับรูปภาพ วิดีโอ และการฝัง เพื่อป้องกันการจัดวางใหม่เมื่อรายการโหลดและใช้พื้นที่
  • สร้างพื้นที่ที่สอดคล้องกันและปรับเปลี่ยนตามพื้นที่โฆษณาสำหรับภาพข้อมูลแบบอินเทอร์แอกทีฟหรือภาพเคลื่อนไหว SVG
  • การสร้างพื้นที่ที่สอดคล้องและตอบสนองสำหรับคอมโพเนนต์แบบหลายองค์ประกอบ เช่น การ์ดหรือวันที่ในปฏิทิน
  • สร้างพื้นที่ที่สอดคล้องกันและปรับเปลี่ยนตามพื้นที่โฆษณาสำหรับรูปภาพหลายรูปที่มีขนาดแตกต่างกัน (ใช้ร่วมกับ object-fit ได้)

Object-fit

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

การแสดงภาพสาธิต Object-fit
แสดงค่า object-fit ต่างๆ ดูการสาธิตใน Codepen

ค่า initial และ fill จะปรับรูปภาพอีกครั้งให้เต็มพื้นที่ ในตัวอย่างของเรา การดำเนินการนี้จะทำให้ รูปภาพบีบและเบลอ เนื่องจากระบบจะปรับพิกเซลใหม่ ไม่เหมาะสม object-fit: cover ใช้ ขนาดที่เล็กที่สุดของรูปภาพเพื่อเติมพื้นที่และครอบตัดรูปภาพให้พอดีกับพื้นที่ตามขนาดนี้ โดยจะ "ซูมเข้า" ที่ขอบเขตล่างสุด object-fit: contain ช่วยให้มั่นใจว่ารูปภาพทั้งหมด จะมองเห็นได้เสมอ ซึ่งตรงข้ามกับ cover ซึ่งจะใช้ขนาดของขอบเขตที่ใหญ่ที่สุด (ในตัวอย่างด้านบนคือความกว้าง) และปรับขนาดรูปภาพเพื่อรักษาสัดส่วนการแสดงผลเดิม ขณะที่พอดีกับพื้นที่ object-fit: none เคสแสดงรูปภาพที่ครอบตัดตรงกลาง (ตำแหน่งออบเจ็กต์เริ่มต้น) ในขนาดจริง

object-fit: cover มักจะใช้ได้ในสถานการณ์ส่วนใหญ่เพื่อให้มั่นใจว่าอินเทอร์เฟซจะดูดีและสม่ำเสมอเมื่อต้องจัดการกับรูปภาพที่มีขนาดแตกต่างกัน แต่คุณจะสูญเสียข้อมูลไปในลักษณะนี้ (ระบบจะครอบตัดรูปภาพที่ขอบที่ยาวที่สุด)

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

เคล็ดลับเก่า: การรักษาสัดส่วนภาพด้วย padding-top

การใช้ padding-top เพื่อตั้งค่าสัดส่วน 1:1 ในรูปภาพตัวอย่างโพสต์ภายในภาพสไลด์
การใช้ padding-top เพื่อตั้งค่าสัดส่วนภาพ 1:1 ในรูปภาพตัวอย่างโพสต์ภายในภาพสไลด์

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

ปัจจุบันโซลูชันข้ามเบราว์เซอร์ที่ได้รับการยอมรับอย่างดีสำหรับการรักษาสัดส่วนภาพตามความกว้างของรูปภาพ เรียกว่า "Padding-Top Hack" โซลูชันนี้ต้องใช้คอนเทนเนอร์หลักและคอนเทนเนอร์ย่อยที่วางตำแหน่งแบบสัมบูรณ์ จากนั้นจึงคำนวณสัดส่วนภาพเป็นเปอร์เซ็นต์เพื่อตั้งค่าเป็น padding-top เช่น

  • สัดส่วนภาพ 1:1 = 1 / 1 = 1 = padding-top: 100%
  • สัดส่วนภาพ 4:3 = 3 / 4 = 0.75 = padding-top: 75%
  • สัดส่วนภาพ 3:2 = 2 / 3 = 0.66666 = padding-top: 66.67%
  • สัดส่วนภาพ 16:9 = 9 / 16 = 0.5625 = padding-top: 56.25%

ตอนนี้เราระบุค่าสัดส่วนภาพได้แล้ว เราจึงนำค่าดังกล่าวไปใช้กับคอนเทนเนอร์หลักได้ ลองดูตัวอย่างต่อไปนี้

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

จากนั้นเราจะเขียน CSS ดังนี้

.container {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 Aspect Ratio */
}

.media {
  position: absolute;
  top: 0;
}

การรักษาสัดส่วนภาพด้วย aspect-ratio

การใช้สัดส่วนภาพเพื่อตั้งค่าสัดส่วนภาพ 1:1 ในรูปภาพตัวอย่างโพสต์ภายในภาพสไลด์
การใช้ aspect-ratio เพื่อตั้งค่าสัดส่วนภาพ 1:1 ในรูปภาพตัวอย่างโพสต์ภายในภาพสไลด์

อย่างไรก็ตาม การคำนวณค่า padding-top เหล่านี้ไม่ใช่เรื่องง่าย และต้องมีค่าใช้จ่ายเพิ่มเติมและการวางตำแหน่ง aspect-ratio พร็อพเพอร์ตี้ CSS แบบใหม่ช่วยให้ภาษาที่ใช้ในการรักษาอัตราส่วน ภาพชัดเจนยิ่งขึ้น

มาร์กอัปเดียวกันนี้ช่วยให้เราแทนที่ padding-top: 56.25% ด้วย aspect-ratio: 16 / 9 ได้ โดยตั้งค่า aspect-ratio เป็นอัตราส่วนที่ระบุของ width / height

การใช้ padding-top
.container {
  width: 100%;
  padding-top: 56.25%;
}
การใช้สัดส่วนภาพ
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

การใช้ aspect-ratio แทน padding-top นั้นชัดเจนกว่ามาก และไม่ได้แก้ไขพร็อพเพอร์ตี้ระยะขอบ เพื่อทำสิ่งต่างๆ นอกขอบเขตปกติ

พร็อพเพอร์ตี้ใหม่นี้ยังเพิ่มความสามารถในการ ตั้งค่าสัดส่วนภาพเป็น auto ซึ่งหมายความว่า "องค์ประกอบที่แทนที่ซึ่งมีสัดส่วนภาพโดยธรรมชาติจะใช้สัดส่วนภาพนั้น มิฉะนั้น กล่องจะไม่มีสัดส่วนภาพที่ต้องการ" หากระบุทั้ง auto และ <ratio> พร้อมกัน สัดส่วนภาพที่ต้องการคือสัดส่วนที่ระบุของ width หารด้วย height เว้นแต่จะเป็นองค์ประกอบที่แทนที่ที่มีสัดส่วนภาพโดยธรรมชาติ ในกรณีนี้จะใช้สัดส่วนภาพดังกล่าวแทน

ตัวอย่าง: ความสอดคล้องกันในตารางกริด

ซึ่งทำงานร่วมกับกลไกเลย์เอาต์ CSS เช่น CSS Grid และ Flexbox ได้เป็นอย่างดี พิจารณารายการ ที่มีรายการย่อยซึ่งคุณต้องการรักษาสัดส่วนภาพ 1:1 เช่น ตารางไอคอนผู้สนับสนุน

<ul class="sponsor-grid">
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
</ul>
.sponsor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}

.sponsor img {
  aspect-ratio: 1 / 1;
  width: 100%;
  object-fit: contain;
}
รูปภาพในตารางกริดที่มีองค์ประกอบระดับบนสุดในมิติข้อมูลสัดส่วนภาพต่างๆ ดูเดโมใน Codepen

ตัวอย่าง: การป้องกันไม่ให้เลย์เอาต์เปลี่ยนแปลง

อีกฟีเจอร์ที่ยอดเยี่ยมของ aspect-ratio คือการสร้างพื้นที่ตัวยึดตำแหน่งเพื่อป้องกันCumulative Layout Shift และมอบ Web Vitals ที่ดียิ่งขึ้น ในตัวอย่างแรกนี้ การโหลดชิ้นงานจาก API เช่น Unsplash จะทำให้เกิด การเปลี่ยนเลย์เอาต์เมื่อโหลดสื่อเสร็จ

วิดีโอการเปลี่ยนแปลงเลย์เอาต์แบบสะสมที่เกิดขึ้นเมื่อไม่ได้ตั้งค่าสัดส่วนภาพในชิ้นงานที่โหลด วิดีโอนี้บันทึกด้วยเครือข่าย 3G ที่จำลอง

ในทางกลับกัน การใช้ aspect-ratio จะสร้างตัวยึดตำแหน่งเพื่อป้องกันการเปลี่ยนแปลงเลย์เอาต์นี้

img {
  width: 100%;
  aspect-ratio: 8 / 6;
}
วิดีโอที่มีอัตราส่วนที่กำหนดจะตั้งค่าในชิ้นงานที่โหลด วิดีโอนี้บันทึกด้วยเครือข่าย 3G ที่จำลอง ดูเดโมใน Codepen

เคล็ดลับเพิ่มเติม: แอตทริบิวต์รูปภาพสำหรับสัดส่วนภาพ

อีกวิธีในการตั้งค่าสัดส่วนภาพของรูปภาพคือผ่านแอตทริบิวต์รูปภาพ หากทราบขนาดของรูปภาพล่วงหน้า แนวทางปฏิบัติแนะนำคือการตั้งค่าขนาดเหล่านี้เป็น width และ height

สำหรับตัวอย่างด้านบน เมื่อทราบว่าขนาดคือ 800 x 600 พิกเซล มาร์กอัปรูปภาพจะมีลักษณะดังนี้ <img src="image.jpg" alt="..." width="800" height="600"> หากรูปภาพที่ส่งมีสัดส่วนภาพเดียวกัน แต่ไม่จำเป็นต้องมีค่าพิกเซลที่ตรงกัน เราก็ยังสามารถใช้ค่าแอตทริบิวต์รูปภาพ เพื่อตั้งค่าสัดส่วนร่วมกับรูปแบบของ width: 100% เพื่อให้รูปภาพใช้พื้นที่ที่เหมาะสม โดยรวมแล้วจะมีลักษณะดังนี้

<!-- Markup -->
<img src="image.jpg" alt="..." width="8" height="6">
/* CSS */
img {
  width: 100%;
  height: auto;
}

ท้ายที่สุดแล้ว ผลลัพธ์จะเหมือนกับการตั้งค่า aspect-ratio ในรูปภาพผ่าน CSS และหลีกเลี่ยงการเปลี่ยนแปลงเลย์เอาต์แบบสะสม (ดูการสาธิตใน Codepen)

บทสรุป

aspect-ratioพร็อพเพอร์ตี้ CSS ใหม่นี้เปิดตัวในเบราว์เซอร์สมัยใหม่หลายเบราว์เซอร์ การรักษาสัดส่วนภาพที่เหมาะสมในคอนเทนเนอร์สื่อและเลย์เอาต์จึงง่ายขึ้นเล็กน้อย

รูปภาพโดย Amy Shamblen และ Lionel Gustave ผ่าน Unsplash