אנימציות של גבולות CSS

בדיקה של כמה דרכים להנפיש גבולות ב-CSS

יש כמה שיטות להגדרת גבול לרכיב: border,‏ outline ו-box-shadow. כפי שמפורט במאמר 3 השיטות של CSS להוספת גבולות רכיבים מאת סטפני אקלס, לכל גישה יש יתרונות וחסרונות משלה – במיוחד כשמדובר באנימציה של הגבולות. הסיבה העיקרית לכך שלא משתמשים ב-border תקין של CSS היא למטרות אנימציה.

אנימציות של גבולות באמצעות outline-offset מאת Kevin J. Powell

מאמר שמשך את תשומת הלב שלי לאחרונה הוא אנימציה מדהימה של גבולות CSS, שבה המחבר Coco בדק אפשרויות נוספות. הוספת תוכן שנוצר באמצעות ::before ו-::after יוצרת גבול מלאכותי שמקבל אנימציה.

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

אנימציות של גבולות באמצעות תוכן שנוצר על ידי Coco

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

שמירה על מודל התיבה

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

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

העקרונות הבסיסיים

נתחיל ביצירת גבול מקווקו והוספת הרקעים המרובים.

/* Size of the border */
--border-size: 0.5rem;

/* Create a dotted border */
border: var(--border-size) dotted lime;

/* Create two background layers:
   1. A white semi-transparent
   2. A layer with the colored boxes
 */
background-image:
  linear-gradient(to right, rgb(255 255 255 / 0.5), rgb(255 255 255 / 0.5)),

  conic-gradient(
    from 45deg,
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  )
;

שינוי הגודל של הרקעים באמצעות background-origin

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

כדי לפתור את הבעיה, צריך למתוח את הרקע כך שיתפוס גם את הגודל של המסגרת. אפשר לעשות זאת באופן ידני על ידי מתיחה והצבה מחדש של הרקע, אבל עדיף להשתמש בנכס background-origin כדי לשנות את הגודל של הרקע בהתאם ל-border-box.

תמיכה בדפדפנים

  • Chrome:‏ 1.
  • קצה: 12.
  • Firefox: 4.
  • Safari: 3.

מקור

מה אסור לעשות
/* Manually add or offset the size of the border where needed */
background-position: calc(var(--border-size) * -1) calc(var(--border-size) * -1);
background-size: calc(var(--border-size) * 2 + 100%) calc(var(--border-size) * 2 + 100%);
מה מותר לעשות
background-origin: border-box;

הוספה אחת משפרת את המראה של הכול:

צמצום שכבת הרקע הלבן באמצעות background-clip

מאחר שהרקעים תופסים את כל השטח עכשיו, צריך לכווץ שוב את השכבה השקופה למחצה. במקום להתעסק שוב ב-background-size, יש דרך קלה יותר לעשות זאת: משתמשים ב-background-clip ומגדירים אותו ל-padding-box. כך הרקע לא ישורטט יותר מתחת לגבול.

תמיכה בדפדפנים

  • Chrome:‏ 1.
  • Edge:‏ 12.
  • Firefox: 4.
  • Safari: 5.

מקור

background-clip:
  padding-box, /* Clip white semi-transparent to the padding-box */
  border-box /* Clip colored boxes to the border-box (default) */
;

לבסוף, צריך להפוך את הגבול transparent לתוצאה המלאה.

border: 0.3rem dotted transparent;

Animation

כדי לשחזר אנימציה של הגבול, אפשר לשנות את זווית ההתחלה של conic-gradient.

--angle: 0deg;
conic-gradient(
  from var(--angle),
  #d53e33 0deg 90deg,
  #fbb300 90deg 180deg,
  #377af5 180deg 270deg,
  #399953 270deg 360deg
);

בעזרת ‎@property, זה קל מאוד בדפדפנים שתומכים בכך:

תמיכה בדפדפנים

  • Chrome:‏ 85.
  • Edge:‏ 85.
  • Firefox:‏ 128.
  • Safari: 16.4.

מקור

@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes rotate {
  to {
    --angle: 360deg;
  }
}

כשמשלבים את כל החלקים, הקוד נראה כך:

תוכן בונוס: border-image

גישה שסקרנו בעבר לציור גבול עם שיפוע היא שימוש ב-CSS border-image.

תמיכה בדפדפנים

  • Chrome: 16.
  • Edge:‏ 12.
  • Firefox:‏ 15.
  • Safari: 6.

מקור

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

/* Create a border */
border: 0.5rem solid transparent;

/* Paint an image in the border */
border-image:
  conic-gradient(
    from var(--angle),
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  ) 1
;

עם זאת, תבחינו בכמה דברים שלא יפעלו יותר בגישה הזו:

  • border-image לא עוקב אחרי border-radius, והוא תמיד יישאר מלבני.
  • כשמגדירים את border-image-slice למלא, ה-border-image לא מצויר מתחת לקבוצה background אלא מעליה. זה עלול להיות מטריד אם רוצים שהרקע יהיה שקוף למחצה.

לסיום

יש מגוון אפשרויות להוסיף אנימציה לשוליים ב-CSS. בהתאם לתרחיש לדוגמה, יכול להיות שתעדיפו להשתמש באפשרות אחת או באחרת.