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

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

สัดส่วนภาพ

การรองรับเบราว์เซอร์

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

แหล่งที่มา

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

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

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

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

  • การสร้าง iframe ที่ปรับเปลี่ยนตามอุปกรณ์ ซึ่งมีขนาดเท่ากับ 100% ของความกว้างขององค์ประกอบหลัก และความสูงควรคงเป็นสัดส่วนวิวพอร์ตที่เจาะจง
  • การสร้างคอนเทนเนอร์ตัวยึดตำแหน่งภายในสำหรับรูปภาพ วิดีโอ และการฝังเพื่อป้องกันไม่ให้มีการจัดวางซ้ำเมื่อรายการโหลดขึ้นและกินพื้นที่
  • การสร้างพื้นที่ที่ปรับเปลี่ยนตามอุปกรณ์และเหมือนกันทั้งหมดสําหรับการแสดงภาพข้อมูลแบบอินเทอร์แอกทีฟหรือภาพเคลื่อนไหว SVG
  • การสร้างพื้นที่ที่ปรับเปลี่ยนตามอุปกรณ์และเหมือนกันสำหรับคอมโพเนนต์หลายองค์ประกอบ เช่น การ์ดหรือวันที่ในปฏิทิน
  • การสร้างพื้นที่โฆษณาที่ปรับเปลี่ยนตามพื้นที่โฆษณาที่แสดงและมีขนาดเท่าๆ กันสำหรับรูปภาพหลายรูปที่มีขนาดแตกต่างกัน (ใช้ควบคู่ไปกับ 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 เช่น

  • สัดส่วนภาพ 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 ที่ระบุ

การใช้ระยะห่างจากขอบด้านบน
.container {
  width: 100%;
  padding-top: 56.25%;
}
การใช้ aspect-ratio
.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 คือสามารถสร้างพื้นที่สำหรับวางโฆษณาเพื่อป้องกันการการเปลี่ยนเลย์เอาต์แบบสะสมและช่วยให้ 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