אפשר להשתמש במאפיין interpolate-size
או בפונקציה calc-size()
כדי להפעיל מעברים ואנימציות חלקות מאורכים למילות מפתח עם שינוי גודל מובנה, ולהפך.
תאריך פרסום: 17 בספטמבר 2024
מבוא
תכונה של CSS שמופיעה לעיתים קרובות בבקשות היא היכולת ליצור אנימציה ל-height: auto
. וריאציה קלה על הבקשה הזו היא מעבר של המאפיין width
במקום height
, או מעבר לכל אחד מהגדלים המובנים האחרים שמיוצגים על ידי מילות מפתח כמו min-content
, max-content
ו-fit-content
.
לדוגמה, בדמו הבא, כדאי שהתוויות יתרחבו בצורה חלקה לרוחב הטבעי שלהן כשעוברים עם העכבר מעל הסמלים.
קוד ה-CSS שבו נעשה שימוש הוא:
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease; /* 👈 Transition the width */
&:hover,
&:focus-visible {
width: max-content; /* 👈 Doesn't work with transitions */
}
}
למרות ש-transition
מוגדר להעביר את הנכס width
ו-width: auto
מוגדר ב-:hover
, לא מתרחש מעבר חלק. במקום זאת, השינוי הוא פתאומי.
אנימציה של מעבר ממילות מפתח עם גודל מותאם אישית אל מילות מפתח עם גודל מובנה וחזרה מהן באמצעות interpolate-size
הנכס interpolate-size
ב-CSS מאפשר לכם לקבוע אם תהיה אפשרות להשתמש באנימציות ובמעברים של מילות מפתח פנימיות של CSS לבחירת גודל.
ערך ברירת המחדל שלו הוא numeric-only
, שלא מפעיל אינטרפולציה. כשמגדירים את המאפיין כ-allow-keywords
, מביעים הסכמה לשימוש באינטרפולציות מאורך למילות מפתח של CSS עם הגדרת גודל מובנית, במקרים שבהם הדפדפן יכול ליצור אנימציה למילות המפתח האלה.
numeric-only
: לא ניתן לבצע אינטרפולציה של<intrinsic-size-keyword>
.allow-keywords
: אפשר לבצע אינטרפולציה של שני ערכים אם אחד מהם הוא<intrinsic-size-keyword>
והשני הוא<length-percentage>
. […]
מכיוון שנכס interpolate-size
הוא נכס שעובר בירושה, אפשר להצהיר עליו ב-:root
כדי לאפשר מעבר למילות מפתח של תצוגה בגודל טבעי ומהן, לכל המסמך. זו הגישה המומלצת.
/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
בדמו הבא, הכלל הזה מתווסף לקוד. כתוצאה מכך, האנימציות אל width: auto
וממנו פועלות כמו שצריך (בדפדפנים עם תמיכה):
הגבלת פוטנציאל החשיפה של בקשת ההסכמה על ידי צמצום הבורר
אם רוצים להגביל את ההסכמה ל-allow-keywords
רק להסתעפות עץ משנית של המסמך, משנים את הבורר מ-:root
רק לרכיב שרוצים לטרגט. לדוגמה, אם הרכיב <header>
בדף לא תואם לסוגים האלה של מעברים, אפשר להגביל את ההסכמה רק לרכיב <main>
ולצאצאיו באופן הבא:
main { /* 👈 Scope the opt-in to only <main> and its descendants */
interpolate-size: allow-keywords;
}
למה לא מאפשרים אנימציה ממילת מפתח לבחירת גודל וממנה כברירת מחדל?
משוב נפוץ לגבי מנגנון ההסכמה הזה הוא שדפדפנים צריכים לאפשר פשוט מעברים ואנימציות ממילות מפתח עם הגדרת אורך מובנית לאורך לפי ברירת המחדל.
האפשרות להפעיל את ההתנהגות הזו נבדקה במהלך הפיתוח של התכונה. קבוצת העבודה גילתה שהפעלה של התכונה הזו כברירת מחדל לא תואמת לאחור, כי גיליונות סגנונות רבים מניחים שלא ניתן להוסיף אנימציה למילות מפתח עם הגדרת גודל מובנית (כמו auto
או min-content
). הפרטים מופיעים בתגובה הזו בבעיה הרלוונטית בקבוצת העבודה בנושא CSS.
לכן, הנכס הוא נכס שבו צריך להביע הסכמה. בזכות מאפיין הירושה, הסכמה למסמך שלם היא רק הצהרת interpolate-size: allow-sizes
ב-:root
, כפי שמפורט למעלה.
אנימציה של מעבר ממילות מפתח עם גודל מותאם אישית אל מילות מפתח עם גודל מובנה וחזרה מהן באמצעות calc-size()
דרך נוספת להפעיל אינטרפולציה אל מילת מפתח עם שינוי גודל מובנה וממנה היא להשתמש בפונקציה calc-size()
. הוא מאפשר לבצע פעולות מתמטיות על גדלים מהותיים בצורה בטוחה ומוגדרת היטב.
הפונקציה מקבלת שני ארגומנטים, לפי הסדר:
- בסיס calc-size, שיכול להיות
<intrinsic-size-keyword>
אבל גםcalc-size()
בתצוגת עץ. - חישוב calc-size, שמאפשר לבצע חישובים על בסיס calc-size. כדי להפנות לבסיס calc-size, משתמשים במילות המפתח
size
.
הנה כמה דוגמאות:
width: calc-size(auto, size); // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered
הוספת calc-size()
לדמו המקורי, הקוד נראה כך:
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease;
&:hover,
&:focus-visible {
width: calc-size(max-content, size); /* 👈 */
}
}
מבחינה חזותית, התוצאה זהה לזו שמתקבלת כשמשתמשים ב-interpolate-size
. לכן במקרה הספציפי הזה צריך להשתמש ב-interpolate-size
.
היתרון של calc-size()
הוא היכולת לבצע חישובים, דבר שלא ניתן לעשות באמצעות interpolate-size
:
width: calc-size(auto, size - 10px); // = The auto width minus 10 pixels
width: calc-size(min-content, size + 1rem); // = The min-content width plus 1rem
width: calc-size(max-content, size * .5); // = Half the max-content width
לדוגמה, אם רוצים שהגודל של כל הקטעים בדף יהיה מכפיל של 50px
הקרוב ביותר, אפשר להשתמש בקוד הבא:
p {
width: calc-size(fit-content, round(up, size, 50px));
height: calc-size(auto, round(up, size, 50px));
}
נוסחת calc-size()
מאפשרת גם לבצע אינטרפולציה בין שתי נוסחאות calc-size()
כששתי הבסיסות שלהן לחישוב הגודל זהות. גם זה לא ניתן להשיג באמצעות interpolate-size
.
#element {
width: min-content; /* 👈 */
transition: width 0.35s ease;
&:hover {
width: calc-size(min-content, size + 10px); /* 👈 */
}
}
למה לא לאפשר את <intrinsic-size-keyword>
ב-calc()
?
שאלה נפוצה לגבי calc-size()
היא למה קבוצת העבודה של CSS לא שינתה את הפונקציה calc()
כדי לתמוך במילות מפתח עם הגדרת גודל מובנית.
אחת הסיבות לכך היא שאסור לשלב בין מילות מפתח לבחירת גודל מובנית כשמבצעים חישובים. לדוגמה, יכול להיות שתתפתו לכתוב calc(max-content - min-content)
שנראה תקין, אבל בפועל הוא לא תקין. הפונקציה calc-size()
אוכפת את הנכונות כי, בניגוד ל-calc()
, היא מקבלת רק <intrinsic-size-keyword>
אחד בתור הארגומנט הראשון שלה.
סיבה נוספת היא התאמה להקשר. לאלגוריתמים מסוימים של פריסה יש התנהגות מיוחדת למילות מפתח ספציפיות לבחירת גודל מודעה מובנית. calc-size()
מוגדר במפורש לייצוג גודל מהותי, ולא <length>
. כך, האלגוריתמים האלה יכולים להתייחס ל-calc-size(<intrinsic-size-keyword>, …)
כאל <intrinsic-size-keyword>
, תוך שמירה על ההתנהגות המיוחדת של מילת המפתח הזו.
באיזו גישה כדאי להשתמש?
ברוב המקרים, מגדירים את interpolate-size: allow-keywords
ב-:root
. זו הדרך הפשוטה ביותר להפעיל אנימציה אל מילות מפתח עם שינוי גודל פנימי ומהן, כי היא בעצם שורה אחת.
/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
קטע הקוד הזה הוא שיפור מתקדם ומתמשך, כי בדפדפנים שלא תומכים בו, המערכת תשתמש ללא מעברים.
כשצריך שליטה ברמת פירוט גבוהה יותר – למשל, ביצוע חישובים – או כשרוצים להשתמש בהתנהגות שרק calc-size()
יכול לבצע, אפשר להשתמש ב-calc-size()
.
#specific-element {
width: 50px;
&:hover {
width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
}
}
עם זאת, כדי להשתמש ב-calc-size()
בקוד, תצטרכו לכלול חלופות לדפדפנים שלא תומכים ב-calc-size()
. לדוגמה, הוספת הצהרות נוספות לגבי גודל או חזרה לזיהוי תכונות באמצעות @supports
.
width: fit-content;
width: calc-size(fit-content, size + 1em);
/* 👆 Browsers with no calc-size() support will ignore this second declaration,
and therefore fall back to the one on the line before it. */
הדגמות נוספות
הנה כמה הדגמות נוספות שבהן נעשה שימוש ב-interpolate-size: allow-keywords
.
התראות
הדגמה הבאה היא גרסת פורק (fork) של הדגמה הזו של @starting-style
. הקוד הותאם כדי לאפשר הוספה של פריטים בגבהים שונים.
כדי לעשות זאת, צריך להביע הסכמה לשימוש בהשתנות של מילות מפתח לפי גודל בכל הדף, ולהגדיר את הערך של height
בכל אלמנט .item
כ-auto
. אחרת, הקוד יהיה זהה לקוד שהיה לפני היצירה של ההסתעפות.
:root {
interpolate-size: allow-keywords; /* 👈 */
}
.item {
height: auto; /* 👈 */
@starting-style {
height: 0px;
}
}
הנפשת הרכיב <details>
תרחיש לדוגמה שבו כדאי להשתמש בסוג הזה של אינטרפולציה הוא כדי ליצור אנימציה לווידג'ט של גילוי נאות או לאקורדיון בלעדי בזמן שהוא נפתח. ב-HTML, משתמשים לצורך כך ברכיב <details>
.
בעזרת interpolate-size: allow-keywords
אפשר להגיע רחוק:
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
details {
transition: height 0.5s ease;
height: 2.5rem;
&[open] {
height: auto;
overflow: clip; /* Clip off contents while animating */
}
}
}
עם זאת, כפי שאפשר לראות, האנימציה פועלת רק כשחלונית הווידג'ט של גילוי הנאות נפתחת. כדי לטפל בבעיה הזו, אנחנו עובדים ב-Chrome על ::details-content
pseudo שיגיע ל-Chrome בהמשך השנה (ונתאר אותו בפרסום עתידי). שילוב של interpolate-size: allow-keywords
ו-::details-content
מאפשר ליצור אנימציה בשני הכיוונים: