צגים עם צפיפות פיקסלים גבוהה הופכים במהירות לנורמה. יוצרים של תוכן צריכים להסתגל לעובדה הזו. זהו מדריך קצר לגבי הצגה של תמונות באיכות גבוהה באינטרנט כיום, בלי polyfills , JavaScript, פריצות CSS ותכונות דפדפן שעדיין לא הוטמעו. בקיצור: בלי שינויים קיצוניים בתהליך העבודה.
כיום יש הרבה הצעות לתמונות רספונסיביות, ורבות מהן כרוכות בשינויים משמעותיים בשביל מפתח האתר. קשה להטמיע את המאפיין srcset
<img>
, במיוחד בגלל המורכבות של הבחירה הנוספת של srcset
שמבוססת על חלון התצוגה:
banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x
למרות שמאפיין ה-CSS image-set
משתמש ב-devicePixelRatio
רק כדי להחליט איזו תמונה לטעון, הוא עדיין מאלץ את המפתחים לכתוב הרבה תגי markup נוספים לכל תמונה.
הצעות אחרות, כמו הרכיב <picture>
, עוד יותר מפורטות.
בנוסף, הם לא נכללים בסטנדרטים, ולכן הזמינות שלהם בכל מקום רחוקה עוד יותר מזו של מאפיין srcset. החלופה היחידה: JavaScript ופתרונות בצד השרת הם החלופה היחידה, אבל לגישות האלה יש חסרונות משלהן, כפי שמוסבר במאמרים אחרים.
המאמר הזה מתאר מספר שימושים בתמונות שניתן למצוא באינטרנט בדרך כלל, ויציע פתרונות פשוטים שעובדים במסכים עם צפיפות פיקסלים גבוהה, כמו גם במסכים רגילים. לצורך הדיון הזה, כל מכשיר שמדווח על window.devicePixelRatio
גדול מ-1 יכול להיחשב כ-DPI גבוה, כי המשמעות היא שפיקסלים של CSS לא זהים לפיקסלים של המכשיר, והתמונות מוגדלות.
סיכום הקווים המנחים:
- אם אפשר, השתמשו ב-CSS/SVG במקום בתמונות רסטר.
- כברירת מחדל, כדאי להשתמש בתמונות שעברו אופטימיזציה לתצוגות עם צפיפות פיקסלים גבוהה.
- מומלץ להשתמש בקובצי PNG לציורים פשוטים ולגרפיקה שמורכבת מפיקסלים (למשל, סמלי לוגו).
- צריך להשתמש בקובצי JPEG דחוסים לתמונות במגוון צבעים (למשל, תמונות).
- תמיד צריך להגדיר גדלים מפורשים (באמצעות CSS או HTML) בכל רכיבי התמונות.
ציורים פשוטים ופיקסל ארט
לעיתים קרובות ניתן להימנע לחלוטין משימוש בתמונות קטנות באמצעות תכונות CSS או SVG.
למשל, אין צורך להשתמש בתמונות כדי ליצור פינות מעוגלות, כי יש תמיכה רחבה במאפיין border-radius
של CSS. באופן דומה, יש תמיכה רחבה בגופנים מותאמים אישית, ולכן לא מומלץ להשתמש בטקסט 'בפורמט תמונה'.
עם זאת, במקרים מסוימים, כמו סמלי לוגו, תמונה יכולה להיות הדרך היחידה קדימה. לדוגמה, הלוגו הזה של Chrome הוא בגודל טבעי של 256x256. במסך רטינה, אפשר לראות את הקו העובר באלכסון ועקומות, שנראה מגושם וגרוע, במיוחד בהשוואה לטקסט שעבר רינדור מהיר:
מידות טבעיות: 256x256px
, גודל הנכס: 31 kB
, פורמט: PNG
משוכנעים? טוב. עכשיו נשתמש בתמונה בצפיפות גבוהה. יכול להיות שתתפתתו לחסוך מקום על ידי שמירת הלוגו כקובץ JPEG, אבל יכול להיות שזו לא רעיון טוב, כי שמירת סמלי לוגו וגרפיקה אחרת בפורמט עם אובדן נתונים נוטה לגרום לבעיות. במקרה הזה הגזמתי את הבעיה באמצעות דחיסת תמונה ברמה גבוהה מאוד, אבל אפשר לראות את הפסים בצבעים כהים, את הנקודות ברקעים לבנים ואת הקווים המבולבלים:
מימדים טבעיים: 512x512px
, גודל הנכס: 13 kB
, פורמט: JPEG
במקרה של תמונות קטנות יחסית, השימוש הוא פי 2 קובצי PNG. חשוב לזכור שההבדל בגודל בין קובץ PNG בגודל 1x לבין קובץ PNG בגודל 2x הוא בדרך כלל גדול מאוד (52KB במקרה הזה). עם זאת, במקרה של לוגו, הוא הפנים של האתר והדבר הראשון שהמבקרים יראו. אם תתפשרו יותר מדי על האיכות כדי להגדיל את הגודל, זה יהיה גם הדבר האחרון שהמבקרים שלכם יראו.
זהו הלוגו של Chrome במלוא הדרו, בגודל של מחצית מהמידות הטבעיות שלו במסכים עם רזולוציה כפולה:
מימדים טבעיים: 512x512px
, גודל הנכס: 83 kB
, פורמט: PNG
הקוד הבא יוצר את הרינדור שלמעלה:
<img src="chrome2x.png" style="width: 256px; height: 256px;"/>
שים לב שציינתי רוחב וגובה בתמונה. צריך לעשות זאת כי הגודל הטבעי של התמונה הוא 512px. היא טובה גם לביצועים, כי מנוע הרינדור מבין היטב את גודל הרכיב ואין צורך להשקיע מאמצים רבים כדי לחשב אותו.
אחת האפשרויות לאופטימיזציה אפשרית היא להקטין את קובץ ה-PNG של 24 סיביות לקובץ PNG עם לוח צבעים של 8 ביט. התכונה הזו פועלת בתמונות עם מספר קטן של צבעים, כולל הלוגו של Chrome. כדי לבצע את האופטימיזציה, אפשר להשתמש בכלי כמו http://pngquant.org/. אפשר לראות כאן קצת פסים, אבל הקובץ הזה הוא רק 13KB, חיסכון עצום של פי 6 בהשוואה לקובץ ה-PNG המקורי בגודל 512x512.
מימדים טבעיים: 512x512px
, גודל הנכס: 13 kB
, פורמט: PNG,
8-bit palette
תמונות במגוון צבעים
כתבתי מאמר ב-HTML5Rocks שבו סקירה של כמה שיטות שונות לתמונות עם תגובה דינמית, וערךתי מחקר בנושא דחיסת JPEG ברזולוציות 1x ו-2x והשוואה בין הגדלים והאיכות החזותית של התוצאות. הנה משבצת אחת כזו מהמאמר שלמעלה:
תייגתי את התמונות לפי רמת הדחיסה שלהן (שמצביעה לפי איכות JPEG), הגודל שלהן (בבייטים) והדעה הסובייקטיבית שלי על האמינות החזותית ההשוואה שלהן (בדירוג לפי מספרים). הקטע המעניין הוא שהתמונה הדחוסה במיוחד פי 2 (תווית 3) קטנה יותר ונראית טוב יותר מאשר התמונה הלא דחוסה 1x (תווית 4). כלומר, בין תמונות 4 ל-3 הצלחנו לשפר את איכות התמונה על ידי הכפלה של כל ממד והגדלת משמעותית את הדחיסה, ובו-זמנית צמצמנו את הגודל ב-2KB.
דחיסה, מאפיינים ואיכות חזותית
רציתי לקבל תובנות נוספות לגבי הפשרות בין רמת הדחיסה, מידות התמונה, האיכות החזותית וגודל התמונה. על סמך המחקר שלמעלה, הרצתי מחקר עם ההשערה הבאה:
השערה
עם דחיסת נתונים מספקת, תמונה בגודל 2x תיראה זהה לאותה תמונה בגודל 1x עם דחיסת נתונים אחרת (נמוכה יותר). עם זאת, במקרה כזה, התמונה הדחוסה במיוחד פי 2 תהיה קטנה יותר מאשר התמונה שפי 1x.
התהליך
- נתונה תמונה ביחס גובה-רוחב של 2x, יוצרים את התמונה ביחס גובה-רוחב של 1x.
- לדחוס את שתי התמונות ברמות שונות.
- צור דף בדיקה שמציג את שתי קבוצות התמונות זו לצד זו.
- מחפשים את המקום בשתי הקבוצות שבו התמונות זהות.
- שימו לב לגודלי התמונות ולרמות הדחיסה המקבילות.
- נסו את זה גם במסך 1x וגם במסך 2x.
יצרתי אפליקציה להשוואה של תמונות זו לצד זו, בדומה לתצוגת ההשוואה של Lightroom. המטרה היא להציג תמונות בגודל 1x ו-2x זה לצד זה, אבל גם לאפשר לכם להגדיל את התצוגה של כל קטע בתמונה כדי לראות פרטים נוספים. אפשר גם לבחור בין הפורמטים JPEG ו-WebP ולשנות את איכות הדחיסה כדי לראות השוואות בין גודל הקובץ לאיכות התמונות. הרעיון הוא לשנות את ההגדרות בכמה תמונות, לבדוק איזו איכות דחיסה, שינוי גודל ופורמט מול איכות התמונה מתאימה לכם, ולהשתמש בהגדרה הזו בכל התמונות.
הכלי עצמו זמין לניסיון. כדי להגדיל את התמונה, בוחרים אזור משנה להגדלה.
ניתוח
אני אומר מראש שאיכות התמונה היא דבר סובייקטיבי. בנוסף, סביר להניח שתרחיש השימוש הספציפי שלכם יקבע את סדר העדיפויות שלכם בספקטרום של איכות התצוגה לעומת גודל הקובץ. בנוסף, סוגים שונים של תכונות תמונה מגיבים באופן שונה לאיכות הדחיסה והדחיסה, כך שפתרון אחד שמתאים לכולם לא בהכרח יעבוד כאן. המטרה של הכלי היא לעזור לכם להבין איך לבצע דחיסה, כמו גם קנה מידה ופורמטים של תמונה.
אחרי ששיחקתי עם הכלי להגדלת התמונות, הבנתי כמה דברים במהירות. קודם כול, אני מעדיף תמונות quality=30 dpr=2x
על תמונות quality=90
dpr=1x
בגלל רמת הפירוט הגבוהה יותר. התמונות האלה דומות גם בגודל הקובץ (במישור, התמונה הדחוסה 2x היא 76kB ואילו הגודל הלא דחוס של 1x הוא 80kB).
חריגים לכלל הזה הם תמונות עם מעברים צבעים (quality<30
) שעברו דחיסה חזקה. בתמונות כאלה יש נטייה לבעיות של פס צבע, שגם הן נראות רע באותה מידה, ללא קשר לקנה המידה של התמונה. דוגמאות לציפורים ולמכוניות שאפשר למצוא בכלי.
תמונות WebP נראות הרבה יותר נקיות מ-JPEG, במיוחד ברמות דחיסה נמוכות. נראה שהבעיה של פס הצבע הרבה פחות חמורה. לסיום, תמונות WebP הרבה יותר קומפקטיות.
אזהרות וסנפיר
שיפור המראה של תמונות בצגים בצפיפות גבוהה הוא רק חצי מהבעיות שקשורות לתמונות, שנגרמות כתוצאה מהבדלים משמעותיים במסכים. במקרים מסוימים, יכול להיות שתרצו להציג תמונות שונות לחלוטין, בהתאם לגודל אזור התצוגה. לדוגמה, ייתכן שצילום הפנים של אובמה יתאים למסך בגודל של טלפון, אבל המעמד שלפניו והדגל מאחוריו אולי יתאים יותר למסך של מחשב נייד.
התכוונתי להימנע מהנושא 'ביצועים גרפיים' כדי להתמקד בתמונות עם DPI גבוה בלבד. אפשר לפתור את הבעיה הזו באמצעות כמה גישות שונות: שימוש בשאילתות מדיה ותמונות רקע באמצעות JavaScript, באמצעות כמה תכונות חדשות כמו image-set
, או בשרת. הנושא הזה מוסבר במאמר תמונות ברזולוציית DPI גבוהה לצפיפות פיקסלים משתנה.
לפני שנסיים, רציתי לציין כמה בעיות פתוחות:
- ההשפעה של דחיסת נתונים גבוהה על הביצועים. מהן העונשים על פענוח של תמונות דחוסות מאוד?
- מהם העונשים בביצועים של הצורך להקטין את התמונה כאשר פי 2 נטען במסך 1x?
לסיכום, מומלץ להשתמש ב-CSS וב-SVG במקום בתמונות רסטר. אם אתם חייבים להשתמש בתמונות רסטר, השתמשו בפורמט PNG לתמונות עם לוחות צבעים מוגבלים וצבעים מוצקים רבים, ובפורמט JPEG לתמונות עם הרבה צבעים וצבעים מדורגים. היתרון הנהדר בגישה הזו הוא שהתגי עיצוב שלכם כמעט לא השתנו. כל מה שנדרש ממפתח האתר הוא ליצור פי 2 נכסים ולגודל נכון את התמונות ב-DOM.
למידע נוסף, כדאי לקרוא את המאמר של Scott Jehl בנושא דומה. חשוב שהתמונות ייראו חדות ושהשימוש בחבילת הגלישה יהיה נמוך