תחביר תיאורי

הרכיב <picture> לא מבצע רינדור באופן עצמאי, אלא משמש כמנוע החלטות עבור רכיב <img> פנימי שאומר לו מה להציג. הפונקציה <picture> פועלת לפי תקדים שכבר הוגדר על ידי הרכיבים <audio> ו-<video>: רכיב wrapper שמכיל רכיבי <source> בודדים.

<picture>
   <source …>
   <source …>
    <img …>
</picture …>

<img> הפנימי הזה מספק לך גם דפוס חלופי מהימן לדפדפנים ישנים יותר ללא תמיכה בתמונות רספונסיביות: אם הדפדפן של המשתמש לא מזהה את הרכיב <picture>, המערכת תתעלם ממנו. לאחר מכן המערכת מוחקת גם את הרכיבים <source>, כי הדפדפן לא יזהה אותן בכלל, או שלא יהיה לו הקשר משמעותי בשבילם בלי הורה <video> או <audio>. עם זאת, כל דפדפן יזהה את רכיב <img> הפנימי, והמקור שצוין ב-src שלו יעובד כמצופה.

'תוכן אומנותי' תמונות עם <picture>

שינוי בתוכן או ביחס הגובה-רוחב של תמונה על סמך גודל התמונה בדף, בדרך כלל נקרא 'תוכן שנוצר בפורמט אומנותי' לתמונות רספונסיביות. srcset ו-sizes תוכננו לפעול באופן בלתי נראה, ומחליפים מקורות בצורה חלקה בהתאם לפקודות הדפדפן של המשתמש. עם זאת, לפעמים תרצו לשנות מקורות בנקודות עצירה שונות כדי להדגיש את התוכן בצורה טובה יותר, באותו אופן שבו אתם מתאימים את פריסות הדף. לדוגמה: תמונת כותרת ברוחב מלא עם מיקוד קטן במרכז עשויה להתאים לאזור תצוגה גדול:

תמונה ברוחב כותרת של פרח סגלגל מוקף עלים ובגבעים, שדבורה מסיירת בו.

עם זאת, כשמגדילים את התצוגה כדי להתאים לאזורי תצוגה קטנים, המיקוד המרכזי של התמונה עלול להיאבד:

תמונה של רוחב כותרת של פרח כחול בהיר סגלגל, בגודל מוקטן. דבורת הדבש בקושי רואים אותו.

הנושא של מקורות התמונות האלה זהה, אבל כדי להתמקד טוב יותר בנושא הזה מבחינה חזותית, מומלץ יחסים של מקור התמונה שישתנו בין נקודות עצירה (breakpoint). לדוגמה, זום קצר יותר במרכז התמונה, וכן חלק מהפרטים בשוליים נחתכו:

תמונה עם חיתוך מוגדל של פרח סגלגל.

סוג של "חיתוך" שניתן להשיג באמצעות שירות CSS, אבל המשתמש יצטרך לבקש את כל הנתונים שמהם מורכבת התמונה הזו, למרות שהם אולי אף פעם לא יראו אותו.

לכל רכיב source יש מאפיינים שמגדירים את התנאים לבחירה של הנכס source: media, שמקבל ו-type, שמקבל סוג מדיה (לשעבר "סוג MIME"). <source> הראשון במקור כדי להתאים להקשר הגלישה הנוכחי של המשתמש נבחר, והתוכן של המאפיין srcset באותו source ישמשו לקביעת המועמדים המתאימים לאותו הקשר. בדוגמה הזו, הערך הראשון של source עם המאפיין media שתואם לגודל אזור התצוגה של המשתמש, הערך שייבחר יהיה:

<picture>
  <source media="(min-width: 1200px)" srcset="wide-crop.jpg">
  <img src="close-crop.jpg" alt="…">
</picture>

יש לציין תמיד את img הפנימי האחרון לפי הסדר – אם אף אחד מהאלמנטים של source לא תואם לרכיב media או type שלהם קריטריונים מסוימים, התמונה תשמש כ"ברירת מחדל" מקור. אם משתמשים ב-min-width שאילתות מדיה, מומלץ להשתמש בכמות הגדולה ביותר קודם, כפי שאפשר לראות בקוד הקודם. כשמשתמשים בשאילתות מדיה עם max-width, צריך לציין קודם את המקור הקטן ביותר.

<picture>
   <source media="(max-width: 400px)" srcset="mid-bp.jpg">
   <source media="(max-width: 800px)" srcset="high-bp.jpg">
   <img src="highest-bp.jpg" alt="…">
</picture>

כשמקור נבחר על סמך הקריטריונים שציינתם, המאפיין srcset ב-source מועבר אל <img>, כאילו שהיא הוגדרה ב-<img> עצמה – כלומר, אפשר להשתמש ב-sizes כדי לבצע אופטימיזציה של תמונה שמיועדת לגרפיקה גם במקורות שונים.

<picture>
   <source media="(min-width: 800px)" srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w">
   <source srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w">
   <img src="fallback.jpg" alt="…" sizes="calc(100vw - 2em)">
</picture>

כמובן שתמונה עם פרופורציות שיכולות להשתנות בהתאם לרכיב <source> שנבחר יוצרת בעיה בביצועים: ב-<img> יש תמיכה רק במאפיינים width ו-height בודדים, אבל השמטת המאפיינים האלה עלולה לפגוע בחוויית המשתמש. כדי להביא בחשבון את התופעה הזו, מדובר בלאחרונהתמיכה טובה – תוספת ל-HTML המפרט מאפשר להשתמש במאפיינים height ו-width ברכיבי <source>. הפעולות האלה נועדו לצמצם את השינויים בפריסה כמו שהם עושים ב-<img>, עם השטח המתאים ששמור בפריסה לכל רכיב של <source> שנבחר.

<picture>
   <source
      media="(min-width: 800px)"
      srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w"
      width="1600"
      height="800">
   <img src="fallback.jpg"
      srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w"
      sizes="calc(100vw - 2em)"
      width="1200"
      height="750"
      alt="…">
</picture>

חשוב לציין שאפשר להסתמך על כיוון הגרפיקה של המסך לקבלת החלטות שמבוססות על גודל אזור התצוגה, ולא ניתן לשנות את הכיוון של הטקסט, ברוב המקרים האלה אפשר לטפל בצורה יעילה יותר באמצעות srcset מתוך sizes. לדוגמה, בחירה טובה יותר של מקור התמונה שמותאמת לערכת הצבעים שנקבעה על ידי העדפת המשתמש:

<picture>
   <source media="(prefers-color-scheme: dark)" srcset="hero-dark.jpg">
   <img srcset="hero-light.jpg">
</picture>

המאפיין type

המאפיין type מאפשר לך להשתמש במנוע קבלת ההחלטות, הבקשה אחת בלבד של הרכיב <picture> כדי להציג רק פורמטים של תמונות לדפדפנים שתומכים בהם.

כפי שלמדתם בקטע פורמטים של תמונות ודחיסה, קידוד שהדפדפן לא יכול לנתח אפילו לא יהיה מזוהה בתור של נתוני תמונה.

לפני ההשקה של האלמנט <picture>, היה צורך בפתרונות הקצה הקדמיים השימושיים ביותר להצגת פורמטים חדשים של תמונות. לדפדפן לבקש ולנסות לנתח קובץ תמונה לפני ההחלטה אם להשליך אותו או לטעון חלופה. א' דוגמה נפוצה הייתה סקריפט שמנוסח בשורות הבאות:

   <img src="image.webp"
    data-fallback="image.jpg"
    onerror="this.src=this.getAttribute('data-fallback'); this.onerror=null;"
    alt="...">

עם קו ביטול הנעילה הזה, עדיין תתבצע בקשה עבור image.webp בכל דפדפן – כלומר העברה לא מנוצלת של דפדפנים ללא תמיכה ב-WebP. דפדפנים שלא היו יכולים לנתח את הקידוד של WebP יזינו אירוע onerror ויחליפו את הערך data-fallback ב-src. זה היה פתרון בזבזני, אבל שוב, גישות כמו זו הייתה האפשרות היחידה יהיו זמינות בקצה הקדמי. זכרו שהדפדפן מתחיל לשלוח בקשות לתמונות לפני שסקריפט מותאם אישית כלשהו להפעיל את הכלי - או אפילו לנתח אותו - כך שלא יכולנו למנוע את התהליך הזה.

הרכיב <picture> מתוכנן באופן מפורש למנוע את הבקשות המיותרות האלה. עדיין אין דרך להשתמש בדפדפן כדי לזהות פורמט שהוא לא תומך בו בלי לבקש אותו, המאפיין type מזהיר את הדפדפן לגבי המקור מראש, כדי שהיא תוכל להחליט אם לשלוח בקשה.

במאפיין type, מציינים את סוג המדיה (סוג MIME לשעבר) של מקור התמונה שצוין במאפיין srcset של כל <source>. כך הדפדפן מקבל את כל המידע צריך לקבוע באופן מיידי אם אפשר לפענח את התמונה הפוטנציאלית שסופקה על ידי source, בלי לבצע שום פעולה חיצונית בקשות — אם סוג המדיה לא מזוהה, המערכת מתעלמת מהשדה <source> ומכל המועמדים שלו, והדפדפן ממשיך הלאה.

<picture>
 <source type="image/webp" srcset="pic.webp">
 <img src="pic.jpg" alt="...">
</picture>

כאן, כל דפדפן שתומך בקידוד WebP יזהה את סוג המדיה image/webp שצוין במאפיין type של הרכיב <source>, צריך לבחור את המימד <source>, ובגלל שסיפקנו רק מועמד אחד ב-srcset <img> כדי לבקש, להעביר ולעבד את pic.webp. כל דפדפן שאין לו תמיכה ב-WebP יתעלם מהsource, וגם בהיעדר הוראות מנוגדות, <img> יציג את התוכן של src כפי שנעשה מאז 1992. כמובן שאין צורך לציין כאן רכיב <source> שני עם type="image/jpeg" — אפשר להניח שיש תמיכה אוניברסלית ב-JPEG.

ללא קשר להקשר הגלישה של המשתמש, כל זה מתבצע באמצעות העברת קובץ יחידה, ללא שימוש ברוחב פס מיותר מקורות של תמונות שלא ניתן לעבד. זאת גם מחשבה קדימה: בהמשך נוסיף פורמטים חדשים ויעילים יותר של קבצים. עם סוגי מדיה משל עצמם, ונוכל לנצל אותם בזכות picture — ללא JavaScript וללא צד השרת ואת כל המהירות של <img>.

העתיד של תמונות רספונסיביות

כל דפוסי תגי העיצוב שהוזכרו כאן היו עלייה משמעותית במונחים של תקן: שינוי הפונקציונליות של משהו שכבר מובן ומרכזי את האינטרנט, כמו <img> אתגר לא פשוט, ואוסף הבעיות שהעלו השינויים היו מקיפות יותר, או במילים אחרות, הצעות לפתרון. אם גיליתם שיש הרבה מקום לשיפור, לתבניות תגי עיצוב, נכון מאוד. מלכתחילה, מטרתם של סטנדרטים אלה הייתה לספק בסיס לעתיד שעליה אפשר להתבסס.

כל הפתרונות האלה תלויים בהכרח בתגי עיצוב, כדי להיכלל במטען הייעודי (payload) הראשוני מהשרת, ולהגיע בזמן לדפדפן לבקש מקורות של תמונות – מגבלה שהובילה למאפיין sizes המורכב לכאורה.

עם זאת, מאז שהתכונות האלה נוספו לפלטפורמת האינטרנט, הושקה שיטה מקורית לדחיית בקשות תמונה. <img> רכיבים עם המאפיין loading="lazy" לא יישלחו עד שפריסת הדף ידועה, כדי לדחות את הבקשה בקשות לתמונות מחוץ לאזור התצוגה הראשוני של המשתמש עד למועד מאוחר יותר בתהליך עיבוד הדף, דבר שעלול למנוע בקשות מיותרות. מאחר שהדפדפן מבין באופן מלא את פריסת הדף בזמן שמתבצעות הבקשות האלה, הוצע המאפיין sizes="auto" כתוספת למפרט ה-HTML כדי להימנע מהטרחה של מאפייני sizes שנכתבו באופן ידני במקרים כאלה.

יש גם תוספות לרכיב <picture> באופק, כדי להתאים לכמה שינויים מרגשים במיוחד ועד לאופן שבו אנחנו מעצבים פריסות דפים. המידע על אזור התצוגה הוא בסיס טוב להחלטות פריסה כלליות, אבל מונעת מאיתנו לנקוט גישה לפיתוח ברמת הרכיבים המלאים, כלומר רכיב שאפשר לשים בכל חלק בפריסת דף, עם סגנונות שמגיבים לשטח שתופס הרכיב עצמו. חשש זה גרם ליצירת שאילתות קונטיינר: שיטה של עיצוב רכיבים על סמך הגודל של מאגר ההורה שלהם, ולא על סמך אזור התצוגה בלבד.

התחביר של שאילתות הקונטיינר רק התייצב, והתמיכה בדפדפן מוגבלת מאוד, בזמן הכתיבה - ההוספה של טכנולוגיות הדפדפן שמאפשרות לו לספק לרכיב <picture> לעשות את אותו הדבר: מאפיין container פוטנציאלי שמאפשר בחירה של <source> קריטריונים לפי המרחב ב-<img> של הרכיב <picture>, ולא על סמך הגודל של אזור התצוגה.

אם זה נשמע קצת מעורפל, יש סיבה טובה לכך: הדיונים על תקני האינטרנט האלה נמשכים, אבל רחוקים מלהיקבע — עדיין לא יכול להשתמש בהם.

למרות שתגי עיצוב של תמונות רספונסיביות מבטיחים שרק קל יותר לעבוד איתן עם הזמן, כמו בכל טכנולוגיה אינטרנטית, יש לכך של שירותים, טכנולוגיות ומסגרות שיעזרו להקל על העומס של כתיבה ידנית של תגי העיצוב האלה. במודול הבא, נלמד איך לשלב את כל מה שלמדנו על פורמטים של תמונות, דחיסה ותמונות רספונסיביות בתהליך העבודה המודרני של הפיתוח.