เผยแพร่: 22 สิงหาคม 2012 อัปเดตล่าสุด: 14 เมษายน 2025
เมื่อมีอุปกรณ์จํานวนมากในตลาด ความหนาแน่นของพิกเซลหน้าจอจึงมีหลากหลายมาก นักพัฒนาแอปพลิเคชันต้องรองรับความหนาแน่นของพิกเซลที่หลากหลาย ซึ่งอาจเป็นเรื่องยาก ในเว็บบนอุปกรณ์เคลื่อนที่ ปัญหาต่างๆ จะทวีความรุนแรงขึ้นด้วยปัจจัยต่อไปนี้
- อุปกรณ์ที่หลากหลายซึ่งมีรูปแบบของอุปกรณ์ต่างๆ กัน
- แบนด์วิดท์เครือข่ายและอายุการใช้งานแบตเตอรี่ถูกจำกัด
ในด้านรูปภาพ เป้าหมายของนักพัฒนาเว็บคือการแสดงรูปภาพที่มีคุณภาพดีที่สุดอย่างมีประสิทธิภาพมากที่สุด บทความนี้จะกล่าวถึงเทคนิคที่เป็นประโยชน์ในการดำเนินการนี้ในปัจจุบันและในอนาคต
หลีกเลี่ยงการใช้รูปภาพหากเป็นไปได้
ก่อนที่จะคิดว่าต้องใส่รูปภาพ โปรดทราบว่าเว็บมีเทคโนโลยีที่มีประสิทธิภาพมากมายซึ่งส่วนใหญ่ไม่เกี่ยวข้องกับความละเอียดและ DPI
กล่าวโดยละเอียดคือ ข้อความ, SVG และ CSS ส่วนใหญ่จะ "ใช้งานได้เลย" เนื่องจากฟีเจอร์การปรับขนาดพิกเซลอัตโนมัติของเว็บที่มี devicePixelRatio
อย่างไรก็ตาม คุณไม่สามารถหลีกเลี่ยงรูปภาพแรสเตอร์ได้เสมอไป เช่น คุณอาจได้รับชิ้นงานที่จำลองใน SVG หรือ CSS ล้วนๆ ได้ค่อนข้างยาก คุณอาจกำลังจัดการกับรูปภาพ แม้ว่าคุณจะแปลงรูปภาพเป็น SVG โดยอัตโนมัติได้ แต่การแปลงรูปภาพเป็นเวกเตอร์นั้นไม่ค่อยมีประโยชน์ เนื่องจากเวอร์ชันที่ขยายขนาดมักจะดูไม่ดี
ประวัติความหนาแน่นของพิกเซล
ในช่วงแรก จอแสดงผลคอมพิวเตอร์มีความหนาแน่นของพิกเซล 72 หรือ 96 จุดต่อนิ้ว (DPI)
จอแสดงผลมีความหนาแน่นของพิกเซลเพิ่มขึ้นเรื่อยๆ ซึ่งส่วนใหญ่เป็นผลมาจากความก้าวหน้าของอุปกรณ์เคลื่อนที่ เนื่องจากโดยทั่วไปผู้ใช้จะถือโทรศัพท์ไว้ใกล้ใบหน้ามากขึ้น ทำให้เห็นพิกเซลได้ชัดเจนขึ้น ภายในปี 2008 โทรศัพท์ 150 dpi กลายเป็นมาตรฐานใหม่ ความหนาแน่นของจอแสดงผลเพิ่มขึ้นอย่างต่อเนื่อง และโทรศัพท์ในปัจจุบันมีจอแสดงผล 300 dpi
ในทางปฏิบัติ รูปภาพที่มีความหนาแน่นต่ำควรมีลักษณะเหมือนกันบนหน้าจอใหม่กับบนหน้าจอเก่า แต่เมื่อเปรียบเทียบกับภาพที่มีความหนาแน่นสูงซึ่งคมชัดและผู้ใช้คุ้นเคย รูปภาพที่มีความหนาแน่นต่ำจะดูสะดุดตาและแตกเป็นพิกเซล ต่อไปนี้เป็นการจําลองคร่าวๆ ว่ารูปภาพขนาด 1x จะมีลักษณะอย่างไรบนจอแสดงผลขนาด 2x ในทางตรงกันข้าม รูปภาพขนาด 2 เท่าดูค่อนข้างดี
พิกเซล 1x | พิกเซล 2 เท่า |
![]() |
![]() |
พิกเซลบนเว็บ
เมื่อออกแบบเว็บ จอแสดงผล 99% มีความละเอียด 96dpi และมีการจัดเตรียมไว้สำหรับรูปแบบต่างๆ เพียงไม่กี่รายการ เมื่อเรามีขนาดและความละเอียดของหน้าจอที่หลากหลาย เราจึงต้องมีวิธีมาตรฐานในการทำให้รูปภาพดูดีบนหน้าจอทุกขนาด
ข้อกำหนด HTML แก้ปัญหานี้ด้วยการกําหนดพิกเซลอ้างอิงที่ผู้ผลิตใช้เพื่อกําหนดขนาดของพิกเซล CSS
การใช้พิกเซลอ้างอิงช่วยให้ผู้ผลิตระบุขนาดของพิกเซลจริงของอุปกรณ์ได้เมื่อเทียบกับพิกเซลมาตรฐานหรือพิกเซลที่เหมาะ อัตราส่วนนี้เรียกว่าอัตราส่วนพิกเซลของอุปกรณ์
คำนวณอัตราส่วนพิกเซลของอุปกรณ์
สมมติว่าโทรศัพท์มือถือมีหน้าจอขนาดพิกเซลจริง 180 พิกเซลต่อนิ้ว (ppi) การคำนวณอัตราส่วนพิกเซลของอุปกรณ์มี 3 ขั้นตอนดังนี้
เปรียบเทียบระยะทางจริงที่ถืออุปกรณ์กับระยะทางของพิกเซลอ้างอิง
จากข้อมูลจำเพาะ เราทราบว่าขนาด 28 นิ้วควรมีความละเอียด 96 พิกเซลต่อนิ้ว เมื่อใช้โทรศัพท์มือถือ เราทราบดีว่าใบหน้าของผู้ใช้อยู่ใกล้กับอุปกรณ์มากกว่าเมื่อเทียบกับแล็ปท็อปและคอมพิวเตอร์เดสก์ท็อป สำหรับสมการต่อไปนี้ เราประมาณว่าระยะทางนั้นคือ 18 นิ้ว
คูณอัตราส่วนระยะทางกับความหนาแน่นมาตรฐาน (96ppi) เพื่อหาความหนาแน่นพิกเซลที่เหมาะสมสำหรับระยะทางที่กำหนด
idealPixelDensity = (28/18) * 96 = 150 พิกเซลต่อนิ้ว (โดยประมาณ)
นำอัตราส่วนความหนาแน่นของพิกเซลจริงไปหารกับความหนาแน่นของพิกเซลที่ต้องการเพื่อหาอัตราส่วนพิกเซลของอุปกรณ์
devicePixelRatio = 180/150 = 1.2

ดังนั้นเมื่อเบราว์เซอร์ต้องการทราบวิธีปรับขนาดรูปภาพให้พอดีกับหน้าจอตามความละเอียดที่เหมาะสมหรือมาตรฐาน เบราว์เซอร์จะอ้างอิงอัตราส่วนพิกเซลของอุปกรณ์ที่ 1.2 ซึ่งหมายความว่าอุปกรณ์นี้มีพิกเซลจริง 1.2 พิกเซลสำหรับพิกเซลที่สมบูรณ์แบบแต่ละพิกเซล สูตรในการแปลงระหว่างพิกเซลที่เหมาะเจาะ (ตามที่ระบุไว้ในข้อกำหนดของเว็บ) กับพิกเซลจริง (จุดบนหน้าจออุปกรณ์) มีดังนี้
physicalPixels = window.devicePixelRatio * idealPixels
ที่ผ่านมา ผู้ให้บริการอุปกรณ์มักจะปัดเศษ devicePixelRatios
(DPR) iPhone และ iPad ของ Apple จะรายงาน DPR เป็น 1 ส่วนอุปกรณ์ Retina เทียบเท่าจะรายงานเป็น 2 ข้อกำหนด CSS แนะนำให้ทำดังนี้
หน่วยพิกเซลหมายถึงจำนวนเต็มของพิกเซลอุปกรณ์ที่ใกล้เคียงกับพิกเซลอ้างอิงมากที่สุด
เหตุผลหนึ่งที่ทำให้อัตราส่วนแบบปัดเศษดีกว่าคืออาจทำให้ข้อบกพร่องระดับพิกเซลย่อยน้อยลง
อย่างไรก็ตาม สภาพการณ์จริงของอุปกรณ์มีความหลากหลายมากกว่ามาก และโทรศัพท์ Android มักจะมี DPR เท่ากับ 1.5 แท็บเล็ต Nexus 7 มี DPR ประมาณ 1.33 ซึ่งคำนวณได้โดยใช้วิธีเดียวกับตัวอย่างก่อนหน้านี้ ในอนาคตคุณจะเห็นอุปกรณ์ที่มี DPR แบบแปรผันมากขึ้น คุณจึงไม่ควรสรุปว่าลูกค้ามี DPR เป็นจำนวนเต็ม
เทคนิครูปภาพ HiDPI
เทคนิคในการแก้ปัญหาการแสดงรูปภาพคุณภาพดีที่สุดให้เร็วที่สุดมีอยู่หลายวิธี ซึ่งแบ่งออกเป็น 2 หมวดหมู่ใหญ่ๆ ดังนี้
- การเพิ่มประสิทธิภาพรูปภาพเดี่ยว
- การเพิ่มประสิทธิภาพการเลือกระหว่างรูปภาพหลายรูป
แนวทางแบบรูปภาพเดียว: ใช้รูปภาพเดียว แต่ใช้อย่างชาญฉลาด แนวทางเหล่านี้มีข้อเสียคือคุณต้องเสียประสิทธิภาพอย่างหลีกเลี่ยงไม่ได้ เนื่องจากต้องดาวน์โหลดรูปภาพ HiDPI แม้ในอุปกรณ์รุ่นเก่าที่มี DPI ต่ำ แนวทางบางส่วนสำหรับกรณีรูปภาพเดียวมีดังนี้
- รูปภาพ HiDPI ที่บีบอัดมาก
- รูปแบบรูปภาพที่ยอดเยี่ยม
- รูปแบบรูปภาพแบบโปรเกรสซีฟ
การใช้รูปภาพหลายรูป: ใช้รูปภาพหลายรูป แต่ใช้วิธีอัจฉริยะในการเลือกรูปภาพที่จะโหลด แนวทางเหล่านี้มีค่าใช้จ่ายเพิ่มเติมโดยปริยายสำหรับนักพัฒนาแอปในการสร้างชิ้นงานเดียวกันหลายเวอร์ชัน แล้วจึงหากลยุทธ์การตัดสินใจ ตัวเลือกมีดังต่อไปนี้:
- JavaScript
- การแสดงผลฝั่งเซิร์ฟเวอร์
- การค้นหาสื่อ CSS
- ฟีเจอร์ในตัวของเบราว์เซอร์ (
image-set()
,<img srcset>
)
รูปภาพ HiDPI ที่บีบอัดมาก
รูปภาพกินแบนด์วิดท์ถึง 60% ในการดาวน์โหลดเว็บไซต์โดยเฉลี่ย การแสดงรูปภาพ HiDPI แก่ลูกค้าทุกรายจะช่วยเพิ่มจำนวนนี้ได้ ช่องจะเติบโตได้อีกมากน้อยเพียงใด
เราได้ทำการทดสอบบางอย่างซึ่งสร้างภาพขนาด 1x และ 2x ที่มีคุณภาพ JPEG ที่ 90, 50 และ 20
จากตัวอย่างขนาดเล็กที่ไม่เป็นไปตามหลักวิทยาศาสตร์นี้ ดูเหมือนว่าการบีบอัดรูปภาพขนาดใหญ่จะให้ผลลัพธ์ที่ดีในแง่คุณภาพต่อขนาด เราคิดว่าภาพขนาด 2 เท่าที่มีการบีบอัดมากนั้นดูดีกว่ารูปภาพขนาด 1 เท่าที่ไม่ได้บีบอัด
อย่างไรก็ตาม การแสดงภาพขนาด 2 เท่าที่มีคุณภาพต่ำและบีบอัดสูงในอุปกรณ์ขนาด 2 เท่านั้นแย่กว่าการแสดงภาพคุณภาพสูง และแนวทางดังกล่าวจะส่งผลให้มีการหักคะแนนคุณภาพรูปภาพ เมื่อเปรียบเทียบรูปภาพ quality: 90
กับรูปภาพ quality: 20
รูปภาพมีความคมชัดลดลงและมีความขุ่นมากขึ้น ระบบอาจไม่ยอมรับอาร์ติแฟกต์ที่มี quality:20
ในกรณีที่รูปภาพคุณภาพสูงมีความสำคัญ (เช่น แอปพลิเคชันโปรแกรมดูรูปภาพ) หรือสำหรับนักพัฒนาแอปที่ไม่ต้องการประนีประนอม
การเปรียบเทียบนี้ทำโดยใช้ JPEG ที่บีบอัดทั้งหมด โปรดทราบว่ามีข้อเสียหลายประการระหว่างรูปแบบรูปภาพที่ใช้งานกันอย่างแพร่หลาย (JPEG, PNG, GIF) ซึ่งนำเราไปสู่…
WebP: รูปแบบรูปภาพที่ยอดเยี่ยม
WebP เป็นรูปแบบรูปภาพที่ดึงดูดใจซึ่งบีบอัดได้ดีมาก ทั้งยังรักษาคุณภาพรูปภาพให้สูง
วิธีหนึ่งในการตรวจสอบการรองรับ WebP คือการใช้ JavaScript โหลดรูปภาพขนาด 1 พิกเซลด้วย data-uri
รอให้เหตุการณ์ "โหลด" หรือ "ข้อผิดพลาด" แสดงขึ้น แล้วตรวจสอบว่าขนาดถูกต้อง Modernizr มาพร้อมกับสคริปต์การตรวจหาฟีเจอร์ดังกล่าว ซึ่งพร้อมใช้งานใน Modernizr.webp
แต่วิธีที่ดีกว่านั้นคือการใช้ฟังก์ชัน image() ใน CSS โดยตรง ดังนั้น หากคุณมีรูปภาพ WebP และ JPEG สำรอง คุณจะเขียนข้อมูลต่อไปนี้ได้
#pic {
background: image("foo.webp", "foo.jpg");
}
วิธีการนี้มีปัญหาอยู่ 2-3 อย่าง ประการแรก image()
ยังไม่ได้รับการนำมาใช้งานอย่างแพร่หลาย ประการที่ 2 แม้ว่าการบีบอัด WebP จะมีประสิทธิภาพเหนือกว่า JPEG แต่ก็ยังถือว่ามีการปรับปรุงที่ดีขึ้นกว่าเดิมอยู่บ้าง โดยไฟล์มีขนาดเล็กลงประมาณ 30% จากแกลเลอรี WebP นี้ ดังนั้น WebP เพียงอย่างเดียวจึงยังไม่เพียงพอที่จะแก้ไขปัญหา DPI สูง
รูปแบบรูปภาพแบบโปรเกรสซีฟ
รูปแบบรูปภาพแบบเป็นขั้นๆ เช่น JPEG 2000, Progressive JPEG, Progressive PNG และ GIF มีข้อดี (ซึ่งยังถกเถียงกันอยู่) ตรงที่ผู้ใช้จะเห็นรูปภาพปรากฏขึ้นก่อนที่จะโหลดเสร็จ ไฟล์ดังกล่าวอาจมีค่าใช้จ่ายเพิ่มเติมบางอย่างเกี่ยวกับขนาด แม้ว่าจะมีหลักฐานที่ขัดแย้งกันเกี่ยวกับเรื่องนี้ Jeff Atwood อ้างว่าโหมดนี้ "ทำให้ขนาดรูปภาพ PNG เพิ่มขึ้นประมาณ 20% และทำให้ขนาดรูปภาพ JPEG และ GIF เพิ่มขึ้นประมาณ 10%" อย่างไรก็ตาม Stoyan Stefanov ได้กล่าวอ้างว่าโหมดแบบเป็นขั้นเป็นตอนมีประสิทธิภาพมากกว่า (ในกรณีส่วนใหญ่) สำหรับไฟล์ขนาดใหญ่
เมื่อมองแวบแรก รูปภาพแบบ Progressive ดูเหมือนจะมีประโยชน์มากในบริบทของการแสดงรูปภาพคุณภาพดีที่สุดโดยเร็วที่สุด แนวคิดคือเบราว์เซอร์จะหยุดดาวน์โหลดและถอดรหัสรูปภาพได้เมื่อทราบว่าข้อมูลเพิ่มเติมจะไม่ช่วยเพิ่มคุณภาพของรูปภาพ (เช่น การปรับปรุงความถูกต้องทั้งหมดอยู่ต่ำกว่าระดับพิกเซล)
แม้ว่าการเชื่อมต่อจะสิ้นสุดได้อย่างรวดเร็ว แต่การเริ่มต้นการเชื่อมต่อใหม่มักมีค่าใช้จ่ายสูง สําหรับเว็บไซต์ที่มีรูปภาพจํานวนมาก แนวทางที่มีประสิทธิภาพมากที่สุดคือการรักษาการเชื่อมต่อ HTTP รายการเดียวให้ใช้งานได้อยู่เสมอ และนํากลับมาใช้ใหม่ให้นานที่สุด หากการเชื่อมต่อสิ้นสุดลงก่อนเวลาอันควรเนื่องจากมีการดาวน์โหลดรูปภาพ 1 รูปแล้ว เบราว์เซอร์จะต้องสร้างการเชื่อมต่อใหม่ ซึ่งอาจช้ามากในสภาพแวดล้อมที่มีเวลาในการตอบสนองต่ำ
วิธีแก้ปัญหาอย่างหนึ่งคือการใช้คำขอ HTTP Range ซึ่งช่วยให้เบราว์เซอร์ระบุช่วงไบต์ที่จะดึงข้อมูลได้ เบราว์เซอร์อัจฉริยะอาจส่งคำขอ HEAD เพื่อรับส่วนหัว ประมวลผล ตัดสินใจว่าต้องใช้ภาพขนาดเท่าใด แล้วจึงดึงข้อมูล แต่น่าเสียดายที่เว็บเซิร์ฟเวอร์รองรับช่วง HTTP ไม่ดีนัก ทำให้แนวทางนี้ใช้ไม่ได้จริง
สุดท้าย ข้อจำกัดที่เห็นได้ชัดของแนวทางนี้คือคุณจะเลือกรูปภาพที่จะโหลดไม่ได้ มีเพียงรูปภาพเดียวกันที่มีคุณภาพแตกต่างกันเท่านั้น ด้วยเหตุนี้ กรณีการใช้งาน "การกำหนดแนวทางศิลป์" จึงใช้ไม่ได้
ใช้ JavaScript เพื่อเลือกรูปภาพที่จะโหลด
แนวทางแรกและชัดเจนที่สุดในการตัดสินว่าจะโหลดรูปภาพใดคือการใช้ JavaScript ในไคลเอ็นต์ วิธีนี้จะช่วยให้คุณทราบข้อมูลทั้งหมดเกี่ยวกับ User Agent และดำเนินการอย่างถูกต้อง คุณสามารถระบุอัตราส่วนพิกเซลของอุปกรณ์ด้วย window.devicePixelRatio
, รับความกว้างและความสูงของหน้าจอ และอาจทำการสแกนซอฟต์แวร์เพื่อหาช่องโหว่การเชื่อมต่อเครือข่ายด้วย navigator.connection หรือส่งคำขอปลอมได้ เช่นเดียวกับที่ไลบรารี foresight.js ทำ เมื่อรวบรวมข้อมูลทั้งหมดแล้ว คุณจะเลือกรูปภาพที่จะโหลดได้
มีไลบรารี JavaScript ประมาณ 1 ล้านรายการที่ใช้เทคนิคนี้ แต่ไม่มีชิ้นงานใดโดดเด่นเป็นพิเศษ
ข้อเสียอย่างหนึ่งที่สำคัญคือคุณจะต้องเลื่อนเวลาการโหลดรูปภาพจนกว่าโปรแกรมแยกวิเคราะห์การมองไปข้างหน้าจะเสร็จสิ้น ซึ่งหมายความว่ารูปภาพจะไม่เริ่มดาวน์โหลดจนกว่าจะเกิดเหตุการณ์ pageload
ดูข้อมูลเพิ่มเติมได้ในบทความของ Jason Grigsby
เลือกรูปภาพที่จะโหลดในเซิร์ฟเวอร์
คุณสามารถเลื่อนการตัดสินใจไปไว้ฝั่งเซิร์ฟเวอร์ได้โดยเขียนตัวแฮนเดิลคำขอที่กำหนดเองสำหรับรูปภาพแต่ละรูปที่แสดง แฮนเดิลดังกล่าวจะตรวจสอบการรองรับ Retina ตาม User Agent (ข้อมูลเพียงอย่างเดียวที่แชร์กับเซิร์ฟเวอร์) จากนั้น คุณโหลดชิ้นงานที่เหมาะสม (ตั้งชื่อตามรูปแบบที่รู้จัก) โดยขึ้นอยู่กับว่าตรรกะฝั่งเซิร์ฟเวอร์ต้องการแสดงชิ้นงาน HiDPI หรือไม่
ขออภัย User-Agent ไม่ได้ให้ข้อมูลที่เพียงพอในการตัดสินว่าอุปกรณ์ควรได้รับรูปภาพคุณภาพสูงหรือต่ำ และควรหลีกเลี่ยงโซลูชันที่ใช้ User-Agent
ในการตัดสินใจเกี่ยวกับสไตล์
ใช้การค้นหาสื่อ CSS
คิวรีสื่อ CSS เป็นแบบประกาศ ซึ่งช่วยให้คุณระบุความตั้งใจและปล่อยให้เบราว์เซอร์ทําในสิ่งที่ถูกต้องในนามของคุณ นอกจากการใช้งานคิวรีสื่อที่พบบ่อยที่สุดซึ่งก็คือการจับคู่ขนาดอุปกรณ์แล้ว คุณยังจับคู่ devicePixelRatio
ได้ด้วย คําค้นหาสื่อที่เกี่ยวข้องคือ device-pixel-ratio และมีตัวแปรขั้นต่ำและสูงสุดที่เกี่ยวข้องตามที่คาดไว้
หากต้องการโหลดรูปภาพที่มี DPI สูงและอัตราส่วนพิกเซลของอุปกรณ์เกินเกณฑ์ คุณอาจต้องทำดังนี้
#my-image { background: (low.png); }
@media only screen and (min-device-pixel-ratio: 1.5) {
#my-image { background: (high.png); }
}
การตั้งค่าจะซับซ้อนขึ้นเมื่อรวมคำนำหน้าของผู้ให้บริการทั้งหมดเข้าด้วยกัน โดยเฉพาะเนื่องจากตำแหน่งที่แตกต่างกันอย่างมากของคำนำหน้า "min" และ "max"
@media only screen and (min--moz-device-pixel-ratio: 1.5),
(-o-min-device-pixel-ratio: 3/2),
(-webkit-min-device-pixel-ratio: 1.5),
(min-device-pixel-ratio: 1.5) {
#my-image {
background:url(high.png);
}
}
วิธีนี้จะช่วยให้คุณได้รับประโยชน์จากการแยกวิเคราะห์การมองไปข้างหน้าอีกครั้ง ซึ่งหายไปเมื่อใช้โซลูชัน JavaScript นอกจากนี้ คุณยังเลือกเบรกพอยต์ที่ตอบสนองได้ (เช่น คุณอาจมีรูปภาพ DPI ต่ำ ปานกลาง และสูง) ซึ่งใช้ไม่ได้กับวิธีการฝั่งเซิร์ฟเวอร์
แต่ก็ยังใช้งานยากอยู่บ้างและทำให้ CSS ดูแปลกๆ หรือต้องมีการประมวลผลก่อน นอกจากนี้ แนวทางนี้ยังจํากัดไว้สําหรับพร็อพเพอร์ตี้ CSS เท่านั้น คุณจึงไม่สามารถตั้งค่า <img src>
และรูปภาพทั้งหมดต้องเป็นองค์ประกอบที่มีพื้นหลัง สุดท้ายนี้ การใช้อัตราส่วนพิกเซลของอุปกรณ์เพียงอย่างเดียวอาจทำให้โทรศัพท์มือถือที่มี DPI สูงดาวน์โหลดชิ้นงานรูปภาพขนาด 2 เท่าขณะใช้การเชื่อมต่อ EDGE ซึ่งไม่ใช่ประสบการณ์การใช้งานที่ดีที่สุด
เนื่องจาก image-set()
เป็นฟังก์ชัน CSS จึงไม่สามารถแก้ปัญหาสำหรับแท็ก <img>
ได้ ป้อน @srcset ซึ่งจะแก้ไขปัญหานี้ได้
ส่วนถัดไปจะอธิบายเรื่อง image-set
และ srcset
อย่างละเอียด
ฟีเจอร์ของเบราว์เซอร์ที่รองรับ DPI สูง
ท้ายที่สุดแล้ว วิธีการเข้าถึงการสนับสนุน DPI สูงจะขึ้นอยู่กับข้อกำหนดเฉพาะของคุณ แนวทางข้างต้นทั้งหมดมีข้อเสีย
เนื่องจาก image-set
และ srcset
ได้รับการรองรับอย่างกว้างขวางแล้ว จึงถือเป็นโซลูชันที่ดีที่สุด มีแนวทางปฏิบัติแนะนำเพิ่มเติมที่จะช่วยให้เราเข้าใกล้ผู้ใช้เบราว์เซอร์รุ่นเก่าได้มากขึ้น
2 อย่างนี้แตกต่างกันอย่างไร image-set()
คือฟังก์ชัน CSS ซึ่งเหมาะที่จะใช้เป็นค่าของพร็อพเพอร์ตี้ CSS พื้นหลัง
srcset
เป็นแอตทริบิวต์เฉพาะสำหรับองค์ประกอบ <img>
ที่มีไวยากรณ์คล้ายกัน
แท็กทั้ง 2 รายการนี้ให้คุณระบุประกาศรูปภาพได้ แต่แอตทริบิวต์ srcset
ยังให้คุณกําหนดค่ารูปภาพที่โหลดตามขนาดวิวพอร์ตได้ด้วย
แนวทางปฏิบัติแนะนำสำหรับชุดรูปภาพ
ไวยากรณ์ image-set()
จะรับการประกาศรูปภาพที่คั่นด้วยคอมมาอย่างน้อย 1 รายการ ซึ่งประกอบด้วยสตริง URL หรือฟังก์ชัน url()
ตามด้วยความละเอียดที่เหมาะสม เช่น
image-set(
url("image1.jpg") 1x,
url("image2.jpg") 2x
);
/* You can also include image-set without `url()` */
image-set(
"image1.jpg" 1x,
"image2.jpg" 2x
);
ซึ่งบอกเบราว์เซอร์ว่ามีรูปภาพให้เลือก 2 รูป รูปภาพหนึ่งได้รับการเพิ่มประสิทธิภาพสำหรับจอแสดงผลขนาด 1x และอีกรูปหนึ่งสำหรับจอแสดงผลขนาด 2x จากนั้นเบราว์เซอร์จะเลือกรายการที่จะโหลดโดยพิจารณาจากปัจจัยต่างๆ ซึ่งอาจรวมถึงความเร็วของเครือข่ายด้วย หากเบราว์เซอร์ฉลาดพอ
นอกจากการโหลดรูปภาพที่ถูกต้องแล้ว เบราว์เซอร์จะปรับขนาดรูปภาพให้เหมาะสมด้วย กล่าวคือ เบราว์เซอร์จะถือว่ารูปภาพขนาด 2 เท่ามีขนาดใหญ่กว่ารูปภาพขนาด 1 เท่า 2 เท่า จึงปรับขนาดรูปภาพขนาด 2 เท่าให้เล็กลง 2 เท่าเพื่อให้รูปภาพปรากฏในหน้าเว็บในขนาดเดียวกัน
คุณสามารถระบุความหนาแน่นของพิกเซลของอุปกรณ์เป็น DPI แทนการระบุ 1x, 1.5x หรือ Nx
หากกังวลเกี่ยวกับเบราว์เซอร์รุ่นเก่าที่ไม่รองรับพร็อพเพอร์ตี้ image-set
คุณเพิ่มทางเลือกสำรองเพื่อให้รูปภาพแสดงได้ เช่น
/* Fallback support. */
background-image: url(icon1x.jpg);
background-image: image-set(
url(icon1x.jpg) 1x,
url(icon2x.jpg) 2x
);
image-set(
url(icon1x.jpg) 1x,
url(icon2x.jpg) 2x
);
โค้ดตัวอย่างนี้จะโหลดชิ้นงานที่เหมาะสมในเบราว์เซอร์ที่รองรับ รูปแบบรูปภาพ และจะใช้ชิ้นงานขนาด 1x เป็นชิ้นงานสำรอง
ณ จุดนี้ คุณอาจสงสัยว่าทำไมไม่ใช้ polyfill (นั่นคือสร้าง shim ของ JavaScript สําหรับ) image-set()
แล้วจบเลย แต่กลับพบว่าการใช้ polyfill ที่มีประสิทธิภาพสำหรับฟังก์ชัน CSS นั้นค่อนข้างยาก (ดูคำอธิบายโดยละเอียดได้ที่การสนทนาเกี่ยวกับรูปแบบ www นี้)
srcset ของรูปภาพ
นอกเหนือจากการประกาศที่ image-set
มีให้แล้ว องค์ประกอบ srcset
ยังใช้ค่าความกว้างและความสูงซึ่งสอดคล้องกับขนาดของวิวพอร์ตด้วย เพื่อพยายามแสดงเวอร์ชันที่เกี่ยวข้องมากที่สุด
<img alt="my awesome image"
src="banner.jpeg"
srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">
ตัวอย่างนี้จะแสดง banner-phone.jpeg
ให้กับอุปกรณ์ที่มีความกว้างของวิวพอร์ตต่ำกว่า 640 พิกเซล, banner-phone-HD.jpeg
ให้กับอุปกรณ์ที่มีความละเอียดสูงและหน้าจอขนาดเล็ก, banner-HD.jpeg
ให้กับอุปกรณ์ที่มีความละเอียดสูงและหน้าจอกว้างกว่า 640 พิกเซล และ banner.jpeg
ให้กับอุปกรณ์อื่นๆ ทั้งหมด
ใช้ image-set สำหรับองค์ประกอบรูปภาพ
คุณอาจต้องการแทนที่องค์ประกอบ img ด้วย <div>
s
ที่มีพื้นหลังและใช้แนวทางชุดรูปภาพ วิธีนี้ใช้ได้ แต่มีข้อจำกัด ข้อเสียคือแท็ก <img>
มีคุณค่าทางความหมายในระยะยาว ในทางปฏิบัติ การดำเนินการนี้สำคัญต่อการช่วยเหลือพิเศษและ Crawler ของเว็บ
คุณอาจใช้พร็อพเพอร์ตี้ CSS ของเนื้อหา ซึ่งจะปรับขนาดรูปภาพโดยอัตโนมัติตาม devicePixelRation
เช่น
<div id="my-content-image"
style="content: -webkit-image-set(
url(icon1x.jpg) 1x,
url(icon2x.jpg) 2x);">
</div>
แหล่งที่มาของ Polyfill
ฟีเจอร์ที่มีประโยชน์อย่างหนึ่งของ srcset
คือมีคำอธิบายสำรองที่สื่อความหมาย
ในกรณีที่ไม่ได้ใช้แอตทริบิวต์ srcset เบราว์เซอร์ทั้งหมดจะรู้วิธีประมวลผลแอตทริบิวต์ src นอกจากนี้ เนื่องจากเป็นเพียงแอตทริบิวต์ HTML คุณจึงสร้าง polyfill ด้วย JavaScript ได้
โพลีฟิลล์นี้มาพร้อมกับการทดสอบยูนิตเพื่อให้มั่นใจว่าใกล้เคียงกับข้อกําหนดมากที่สุด นอกจากนี้ ยังมีการตรวจสอบที่ป้องกันไม่ให้โพลีไฟล์เรียกใช้โค้ดใดๆ หากมีการใช้ srcset โดยตรง
บทสรุป
โซลูชันที่ดีที่สุดสำหรับรูปภาพที่มี DPI สูงคือเลือกใช้ SVG และ CSS อย่างไรก็ตาม วิธีนี้อาจไม่เหมาะเสมอไป โดยเฉพาะสำหรับเว็บไซต์ที่มีรูปภาพจำนวนมาก
แนวทางใน JavaScript, CSS และโซลูชันฝั่งเซิร์ฟเวอร์ต่างก็มีจุดแข็งและจุดอ่อน แนวทางที่น่าจะได้ผลที่สุดคือการใช้ image-set
และ srcset
โดยสรุปแล้ว คำแนะนำของเรามีดังนี้
- สำหรับรูปภาพพื้นหลัง ให้ใช้ image-set ที่มีการแสดงผลสำรองที่เหมาะสมสำหรับเบราว์เซอร์ที่ไม่รองรับ
- สำหรับรูปภาพเนื้อหา ให้ใช้ srcset polyfill หรือใช้การใช้ image-set เป็นทางเลือก (ดูด้านบน)
- สำหรับกรณีที่คุณยอมลดคุณภาพรูปภาพ ให้ลองใช้รูปภาพที่บีบอัด 2 เท่าอย่างหนัก