Tutorial

Img และ Picture Tag ใช้อันไหนดี ?

By Arnon Puitrakul - 25 มีนาคม 2021 - 1 min read min(s)

Img และ Picture Tag ใช้อันไหนดี ?

ความเว็บในปัจจุบันเปลี่ยนไปกว่าสมัยก่อนมาก ตั้งแต่มีโทรศัพท์และอุปกรณ์เคลื่อนที่มากมาย ขนาดหน้าจอก็มีความเยอะมากขึ้นด้วยเช่นกัน ถ้าเราเปิดบน Laptop มันก็ขนาดนึง เราเปิดบน โทรศัพท์มันก็ขนาดนึง เราเปิดบนเครื่องตั้งโต๊ะจอใหญ่ ๆ ก็ขนาดนึง มันมีความต่างของขนาดเยอะมาก ทำให้คนที่ออกแบบเว็บก็ต้องเปลี่ยนมาใช้ Mobile First เป็น Concept ในการออกแบบ ฝั่ง Programmer เองก็ต้องเปลี่ยนด้วยเช่นกัน

ปกติแล้วเราใช้ img เป็น Tag ใน HTML เพื่อบอก Web Browser ว่า นี่คือรูปภาพ ยุคสมัยเปลี่ยนไป อย่างที่บอกว่าเรามีอุปกรณ์หลายขนาดมาก ๆ เช่นโทรศัพท์ก็จะมีหน้าจอที่แคบกว่าเครื่องคอมพิวเตอร์จอใหญ่ ๆ แน่ ๆ ถ้าจะให้โทรศัพท์มาโหลดภาพขนาดใหญ่ ๆ โดยเฉพาะผ่าน Cellular Network ก็คงจะไม่ดี ไหนจะเรื่อง Art Direction ที่บางที เราอาจจะปรับอัตราส่วนของภาพให้เหมาะสมกับอุปกรณ์ต่าง ๆ อีก วันนี้เราจะมาดูกันว่า เราจะแก้ปัญหาพวกนี้ได้อย่างไรบ้างผ่าน HTML ธรรมดานี่แหละ

ปัญหาเดิมของ <img>

รู้หมื่อไร ว่า Img Tag มีอายุเยอะมาก ๆ แล้ว มันถูกนำมาใช้ตั้งแต่ปี 1992 จนถึงตอนนี่ปี 2021 เราก็ยังใช้งานมันอยู่ เกือบ 30 ปีแล้วนะ

<img src="img_1.jpg" />

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

พอรูปใหญ่ ๆ เข้า เราจะเจอกับอาการที่รูปค่อย ๆ โหลดจากบนลงล่างเรื่อย ๆ นั่นเกิดจากรูปมันใหญ่เกินไปหน่อย เมื่อเทียบกับความเร็วอินเตอร์เน็ต หรือบางเว็บอาจจะมีรูปโหลดขึ้นมาเป็นอัน ๆ เลย แต่ว่ามันเป็นขาวดำ แล้วสีค่อยๆ โหลดจากบนลงล่างอีกเหมือนกัน พวกนี้เขาเซฟเป็นไฟล์สกุล JPG นี่แหละ แต่เลือกแบบ Progressive แทน

นอกจากนั้นอีกปัญหาที่เราบอกคือ เมื่อหน้าจอเปลี่ยน การ Design มันก็ต้องเปลี่ยนด้วยเช่นกัน โดยเฉพาะเรื่องของอัตราส่วน ตอนที่อยู่บน Desktop เราอาจจะต้องการให้มันแสดงเป็นอัตราส่วน 16:9 แต่พอมาเป็นบน Mobile ด้วยความที่มันแคบ ทำให้พอแสดงผลออกมา มันก็จะสูงได้แค่นิดเดียวเท่านั้น นั่นคือปัญหา

วิธีแก้ปัญหาคือ เราจะต้อง Crop รูปเอาให้กลายเป็นแนวตั้ง แต่ถ้าเราใช้ Script ในการ Crop  มันก็ยากที่เราจะกำหนดว่า เราอยากจะให้มัน Crop ตรงไหน ถ้าเราสั่งให้มันหั่นมาตรงกลางเลย บางที Content ที่เราต้องการอาจจะไม่อยู่ตรงกลางก็ได้ นี่แหละคืออีกปัญหา

จากทั้ง 2 ปัญหาที่เราเล่าไป เป็นปัญหาที่นักพัฒนาเว็บสมัยใหม่น่าจะได้เจอไม่เว้นแต่ละวัน ถามว่า คนที่คิด Img มันผิดมั้ยก็ไม่นะ เพราะตอนที่เขาคิด Tag นี้ขึ้นมาแหม่ เกือบ 30 ปีก่อน ใครจะไปคิดละว่า โลกเราจะมีเทคโนโลยีที่โตได้เร็วขนาดนี้ มีโทรศัพท์มือถือที่สามารถต่ออินเตอร์เน็ตความเร็วสูงในเวลาอันสั้นได้ขนาดนี้ ทำให้ต้องมีการเปลี่ยนแปลง เพิ่มเติมมาตรฐานเพื่อให้สอดคล้องกับอุปกรณ์ และเว็บให้ทันสมัยตลอดเวลา

Srcset กับการแก้ปัญหาเรื่องขนาดไฟล์

<img srcset="cat-600.jpg 600w,
             cat-1000.jpg 1000w, 
             cat-1600.jpg 1600w" 
     src="cat.jpg" 
     alt="Image of Cat"
 />

เรื่องของขนาด และ ความละเอียดของไฟล์ เราสามารถแก้ปัญหาได้ด้วยการใช้ Srcset ที่อยู่ใน Img Tag ได้เลย โดยที่เราสามารถกำหนดขนาดความกว้างเทียบกับความกว้างของหน้าจอได้เลย โดยที่ Web Browser มันจะเลือกตัวที่ใกล้เคียงที่สุดให้ User เองเลย

ใน Srcset เราก็จะเติมเป็น Source ของรูปต่าง ๆ ที่เราต้องการ จากนั้นตามด้วย ขนาดของความกว้างของรูป เช่น cat-600.jpg เราเซฟมากว้างอยู่ที่ 600px ส่วนที่เหลือ Web Browser จะจัดการเลือกให้กับ User เองเลยว่า จะเอาอันไหนมาแสดง โดยจะดูจากขนาดหน้าจอ หรือในบาง Browser ถ้าเราเลือก Data Saver Mode ไว้ มันก็จะโหลดอันที่เล็กที่สุดมาเพื่อประหยัด Data นั่นเอง

แต่ ๆ ลองสังเกตุดี ๆ ว่า เราก็ยังคงเลือกที่จะใส่ src ธรรมดามาอยู่ไม่ได้หายไปไหน อันนี้ต้องเผื่อ เพราะเราไม่รู้ว่าคนที่เปิดเข้ามาในหน้าเว็บที่เราสร้าง จะรองรับ srcset รึเปล่า ถ้าไม่รองรับ เขาจะได้ Fallback กลับไปที่ src ธรรมดา และโหลดรูปขึ้นอยู่

อันนี้ก็จะเข้ามาช่วยแก้ปัญหาเรื่องของความเร็วในการโหลดได้เยอะมาก ๆ บางหน้าที่มีรูปเยอะ ๆ การใช้รูปใหญ่ ๆ มาก ๆ อาจจะทำให้โหลดช้าไปหลายวินาที อาจจะถึง 5 วินาทีเลยก็เป็นได้ ดังนั้นการใช้พวก Srcset สร้าง Option ให้กับ Web Browser เลยเป็นตัวเลือกที่ดีตัวนึงเลย

Art Direction กับ <picture>

อีกปัญหาที่เราบอกไปคือ เมื่อเราย่อขนาดของหน้าจอลงไปเรื่อย ๆ กับบอกว่าเราจะฟิคให้ขนาดของรูปมีขนาดเท่ากับความกว้างของหน้าจอเสมอ สมมุติว่า เราเจอรูปแนวนอน ถ้าเราทำแบบนี้ แปลว่า ในหน้าจอที่มีความกว้างน้อย ๆ ความสูงของรูปจะหดเหลือเล็กมาก ๆ เลยนะ ทำให้เราไม่เห็นรายละเอียดเท่าที่ควร

มันจะดีกว่ามั้ย ถ้าเราบอกว่า ในหน้าจอเล็ก ๆ เราอยากจะให้มันแสดงผลเป็นอีกรูปที่เรา Crop ไว้เป็นแนวตั้งแล้วได้ ตรงนี้แหละที่ srcset จะไม่ตอบโจทย์แล้ว <picture> ที่เป็น Tag ที่พึ่งประกาศตอน HTML5 จะเฉิดฉายแล้ว

<picture>
        <source media="(max-width: 600px)" 
                srcset="cat-portrait.jpg" 
                sizes="50vw"/>
    
        <img srcset="cat-600 600w,
                     cat-1000.jpg 1000w,
                     cat-1600.jpg 1600w" 
             sizes="(max-width: 600px) 100vw, 
                    (max-width: 1000px) 100vw, 
                    (max-width: 1600px) 100vw"/>
</picture>

จาก HTML ด้านบน เราเอา Img Tag ตัวเก่านี่แหละไปยัดใส่ใน Tag Picture เข้าไป และเติม Tag source เข้าไป โดยที่เราบอกว่า เราจะให้มันใช้ Source นี้ได้ก็ต่อเมื่อขนาดของจุดที่แสดงผลรูปมีความกว้าง 600px ลงไป นอกจากนั้น หรือก็คือให้ Fallback ไปใช้ของใน Img Tag เหมือนเดิม

สังเวยตัวเองไปอี๊กกก ด้านซ้ายคือ เมื่อเราแสดงผลในหน้าจอที่กว้างอย่างใน Desktop ด้านขวาจะเป็นหน้าจอแคบ ๆ เช่นโทรศัพท์ เราจะเห็นว่า ส่วนซ้ายและขวาของรูปหายไปแทน เพราะเรา Crop เอง แทนที่เราจะแสดงผลรูปเดิมที่อาจจะเล็กไปเลย

เท่านี้เราก็สามารถคุมเรื่องของ Art Direction ในหน้าเว็บของเราได้ง่าย ๆ แล้ว โดยที่ไม่ต้องมานั่งคิดว่า ถ้ามันเป็นแนวนอน แล้วเราย่อหน้าจอเล็ก ๆ แล้วจะยังไง หรือกลับกัน ถ้าเรามีหน้าจอใหญ่ ๆ แล้วยังไงต่ออะไรแบบนั้น ให้อิสระกับ Designer ในการออกแบบหน้าเว็บเรามากขึ้นโขเลย

Next-Gen Image Format

ถ้าเราติดตามเรื่องของ Web Performance ในช่วงหลายปีที่ผ่าน ๆ มา เรื่องนึงที่คุยกันเยอะพอตัวเลยคือ เรื่องของสกุลไฟล์รูปภาพใหม่ ๆ เช่น WebP หรือ AVIF ก็เป็นที่พูดถึง ถ้าได้ลองแล้วจะรู้เลยว่า มันช่วยลดขนาดของรูปภาพได้เยอะมาก ๆ เผลอ ๆ ถ้าหน้าไหนรูปเยอะ ๆ ลดได้ถึงระดับวินาทีเลยทีเดียว

<img src="cat_1.webp"/>

แต่ปัญหาคือ พอมันเป็นสกุลไฟล์แบบไหน Web Browser ก็ Support น้อยเช่นกัน ทำให้มีปัญหาเวลาเราเรียกใช้งานปกติ จากตัวอย่างข้างบน เราจะเห็นได้ว่า WebP Format เองก็เป็นรูปภาพ ที่เราสามารถเรียกผ่าน Img Tag ได้ตามปกติแหละ แต่ปัญหาก็อย่างที่บอกว่า มันไม่ Support ใน Web Browser เก่า ๆ ทำให้เมื่อไปแสดงผล มันก็จะไม่มีอะไรออกมา เพราะมันอ่านไม่ออกนั่นเอง ดังนั้น การที่เราจะใช้ Format รูปภาพใหม่ ๆ เราก็อาจจะต้องมี Fallback Format ให้มันหน่อย

<picture>
    <source srcset="cat.webp" type="image/webp">
    <img src="cat.png">
</picture>

HTML ด้านบน เราจะเห็นว่า เราเลือกเอา webp Format มาใช้แล้ว โดยที่เรากำหนดลงไปใน Source Tag และบอกเป็น Attribute Type ลงไปว่า มันคือ WebP ถ้า Web Browser ที่มัน Support WebP Format มันก็จะดึงไปแสดงผลได้เลย ส่วนถ้าไม่รองรับ หรือแม้กระทั่งไม่รองรับ Picture Tag เลย มันก็จะโดดไปดึงจาก Img Tag อีกทีนึงได้เหมือนกัน ทำให้เราสามารถที่จะใช้ Format ใหม่ ๆ ได้แล้ว โดยที่ Web Browser ที่ไม่รองรับก็ยังทำงาน และ แสดงผลให้เราได้เหมือนกัน

สรุป: เราต้องใช้อะไร อันไหนกันแน่

ถึงแม้ว่า Picture Tag จะเป็น Tag ที่ถูกกำหนดขึ้นมาบนมาตรฐาน HTML5 แล้วก็เถอะ แต่ถ้าเทียบกับ Img เอง มันก็ต่างกันอยู่แล้ว เพราะ Img มันเกิดมานานกว่านั้น และฝังรากลึกลงไปใน HTML ไปซะแล้ว ทำให้ ถ้าเราบอกว่า เราต้องการที่จะแสดงผลรูปเดียวกันเลย แค่ความกว้างตามขนาดของการแสดงผล เราแนะนำให้ใช้ Img เหมือนเดิมนี่แหละ แต่ถ้าเราบอกว่า เราอยากที่จะ Crop รูปตามขนาดการแสดงผล หรือ การใช้พวก Next-Gen Format ต่าง ๆ อันนี้แหละ เราว่าการเปลี่ยนมาใช้ Picture Tag จะคุ้มกว่าเยอะ

BONUS: เราจะสร้างรูปหลาย ๆ ขนาดยังไงให้เร็ว ๆ

หลังจากที่เราอ่านกันไปในเรื่องของการที่เราจะต้องเซฟรูปออกมาเป็นหลาย ๆ ขนาด ยิ่งเราซอยเยอะ เวลาเราใส่รูปเข้าไป เราก็ต้องใส่หลายรูปมากขึ้น ถ้าเราต้องมานั่งเซฟเองทีละรูปก็ดูจะโหดร้ายเกินไปหน่อย มันก็จะมี โปรแกรม หลาย ๆ ตัวที่ออกมาเพื่อทำอะไรแบบนี้ให้เราเองเลย มันจะ Generate รูปในแต่ละขนาดออกมาให้เราเลย ปกติแล้ว การทำพวกนี้เราจะใช้ sharp ที่ไม่ใช่เครื่องใช้ไฟฟ้าน่ะ เป็นตัวที่เร็ว และใช้งานได้ดีเลย เราก็เขียน Script เอาไว้ ถ้ามันมีการอัพโหลดรูปเข้ามา เราก็เขียน Script ให้มัน Generate รูปภาพในแต่ละ Breakpoint ที่เรากำหนดให้ กับ Generate พวก Next-Gen Format อย่าง WebP ออกมาให้เลยด้วย ถือว่าสะดวกมาก ๆ

แต่ถ้าใครไม่สะดวกที่จะทำงานพวกนี้เอง เราก็สามารถไปใช้งานพวก Image CDN ได้เลย โดยที่พวกนี้ เขาจะจัดการในเรื่องของการย่อขยาย หรือการแปลง Format ให้เราเลย เราแค่ใส่ Image ปกติเข้าไป เราก็จะสามารถเรียกรูปภาพที่ความละเอียด และ Format ต่าง ๆ ออกมาได้เลย คิดซะว่า เป็น Optimisation as a Service Cloud ละกัน มันสะดวกมาก ๆ เลย หลัก ๆ ที่ดัง ๆ เลยก็จะเป็นของ Akamai และ Cloudinary