Responsive Sprite

משך זמן קריאה: 4 דקות

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

בנושא התאמת תמונות לרזולוציות השונות יש הרבה מאמרים ודרכי טיפול. החל משימוש בתגית img-ושימוש ב srcset להגשת תמונות בגדלים שונים לפי רוחב מסך, ועד שימוש בתמונות רקע עם שליטה על הגודל עם המאפיין background-size-ושימוש ב media query להצגת גדלים שונים לרזולוציות שונות.

כל השיטות האלו מאוד מעניינות ועוזרות אבל מה עושים אם האתר מכיל תמונת רקע אחת והיא sprite?

ב footer של אחד האתרים שעבדתי עליהם היה בר ניווט עם 4 הפניות ובגרסה של המובייל הייתי צריכה לשמור על הפרופורציות של ההפניות גם כשהמסך ברוחב 320px וגם כשהוא 550px.

footer-mobile

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

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

הכנתי דוגמה כדי להמחיש את העניין (ממליצה לפתוח את הדוגמה בדף חדש ולשחק עם גודל המסך)

See the Pen wBoapX by Rachel Bratt Tannenbaum (@rachelbt) on CodePen.

בדוגמה הראשונה (First Four – simple sprite) אני משתמשת בספרייט אשר מכיל 4 תמונות שכל אחת ברוחב של 65px. הרוחב הכולל של הספרייט הוא 260px.
בעיקרון, אילו לא היה צורך בהתאמה רספונסיבית, אלמנט ה-a – שמשתמש בספרייט בתור ה-background-image שלו – היה מוגדר ברוחב 65px. אבל, כדי לשמור על הפרופורציה של ה-a נגדיר את הרוחב שלו ל 22% וניתן margin-left: 3%; כדי לרווח בין ההפניות.
בנוסף, ל-background-image ניתן את ההגדרות הבאות:

background-size: 400% auto;
background-position: 0 33.333%;

כאשר הרוחב  background-size מוגדר באחוזים הכוונה היא לאחוז של התמונה (=הספרייט שלנו) שתהייה מוצגת בתוך האלמנט שמחזיק אותה (ה-a). זאת אומרת שאם הגדרנו רוחב של 400%, מה שיוצג בתוך ה-a יהיה אייקון בודד מתוך הספרייט (היות שהספרייט כולל 4 אייקונים ברוחב שווה). בהגדרה של גובה תמונת הרקע לא ניגע ונשאיר auto, כדי שהפרופורציה תשמר.
מיקום תמונת הרקע על ידי background-position יהיה גם כן באחוזים כאשר החישוב הוא כזה:

100% / (4-1) = 100% / (3) = 33.33333%.

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

מעבר להגדרות שציינתי לגבי background-image חשוב להגדיר ל a:

  •  display: block
  • כדי לשמור על פרופורציה של ריבוע יש לתת  padding-bottom זהה לרוחב שלו
  • החישובים מסתבכים אם הטקסט של ה a מוצג, ולכן בדוגמה יש text-indent: -9999px

עד עכשיו הכל היה מעולה 🙂

אבל מה קורה אם הספרייט שלנו מכיל עוד אלמנטים מעבר לאייקונים שאנחנו משתמשים בהם באזור הזה?
בדוגמה השניה (Second Four – complex sprite) אני משתמשת בספרייט מורכב יותר. כמו כן אלמנט ה-a שלי עטוף ב-li – שתי עובדות שקצת מסבכות את העניין. אבל לא נורא, השיטה עדיין עובדת.

את הגדרות הרוחב והריווח אנחנו מגדירים ל-li. כמו כן גם את הגדרת תמונת הרקע:

width: 22%;
padding-bottom: 22%; /*to ensure the height will be equal to the width*/
margin-right: 3%;
background-image: url("http://www.s.ort.org.il/wp-content/themes/mobile_singalovsky/images/sprite.png");
background-repeat: no-repeat;
background-size: 493.85% auto; /*calculated by http://rqrwd.com/*/
background-position: 0 55%;

בדוגמה השניה הרוחב של תמנות הרקע הוא 493.85%. מה זה המספר הזה ואיך הגעתי אליו? אז ככה:

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

px to %

את הגדרת המיקום באחוזים מצאתי ע"י שימוש של ניסוי וטעייה. ידעתי  שאין לי תזוזה על ציר ה Y ולכן הוא תמיד יהיה 55%, ואילו על ציר ה X כל פעם הזזתי באחוזים ב-firebug עד שהגעתי לתוצאה משביעת רצון ברזולוציות שונות (על הציר של 320 – 600 פיקסלים בלבד).

ל-a שנמצא בתוך ה-li צריך להגדיר:

  • כמובן – display: block
  • width: 100% כדי שיתפרס מקצה לקצה בתוך ה-li שלו
  • היות ולא ניתן להגדיר גובה של 100%, ניתן padding-bottom: 100%-מה שאומר שאם למשל הרוחב של ה-li הוא 65px (ברגע נתון ברזולוציה מסויימת), אז הרוחב של ה a הוא גם 65px ויש לו padding-bottom של 65px מה שהופך אותו לריבוע.

ל-li יש להגדיר line-height: 0, כי בלי זה יהיה ל li גובה מסויים שיפריע לחישובים באחוזים.

דבר אחרון – השיטה עובדת מעולה, אבל לא תמיד נכונה לשימוש במנעד רחב מדי של רזולוציות שונות. למשל בדוגמה שלנו, מעבר ל 600 פיקסלים האייקונים גדלים פרופורציונאלית אבל מתחילים להתפקסל. נכון ששימוש בספרייט של SVG היה פותר את העניין, אבל יש עוד שיקולים של עיצוב ונגישות. הפתרון הזה טוב לקפיצות קטנות כמו למשל כיסוי רוב הגדלים של מובייל, החל מאייפון שמוגדר ב-320 פיסקלים, ועד ה-note שהוא כמעט 600 פיקסלים רוחב.

וכך משתמשים בספרייט באתרים רספונסיביים.

נסו ותהנו!