גיליונות סגנונות ניתנים לבנייה

סגנונות חלקים לשימוש חוזר.

ג'ייסון מילר
ג'ייסון מילר

גיליונות סגנונות ניתנים לבנייה הם דרך ליצור ולהפיץ סגנונות לשימוש חוזר כשמשתמשים ב-Shadow DOM.

תמיכה בדפדפן

  • 73
  • 79
  • 101
  • 16.4

מקור

תמיד היה אפשר ליצור גיליונות סגנונות באמצעות JavaScript. עם זאת, בעבר היה התהליך ליצור אלמנט <style> באמצעות document.createElement('style'), ואז לגשת למאפיין הגיליון שלו כדי לקבל הפניה למכונה הבסיסית CSSStyleSheet. השיטה הזו יכולה ליצור קוד CSS כפול ואת ה-blob הזמני שלו, ופעולת הצירוף מובילה להבזק של תוכן לא מעוצב, בין אם יש ריבוי או לא. הממשק CSSStyleSheet הוא השורש של אוסף של ממשקים לייצוג CSS שנקראים CSSOM, ומציע דרך פרוגרמטית לשינוי גיליונות סגנונות ולבטל את הבעיות המשויכות לשיטה הישנה.

תרשים שמראה הכנה של שירות CSS ויישום שלו.

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

השיוך שנוצר על ידי Constructable Stylesheets מתאים מאוד למספר אפליקציות שונות. אפשר להשתמש בו כדי לספק עיצוב מרוכז שמשתמשים בו רכיבים רבים: העיצוב יכול להיות מכונה CSSStyleSheet שמועברת לרכיבים, והעדכונים לעיצוב מופצים באופן אוטומטי לרכיבים. אפשר להשתמש בו כדי להפיץ ערכים של נכס CSS מותאם אישית לעץ משנה ספציפיים ב-DOM, בלי להסתמך על הרמה. אפשר אפילו להשתמש בו כממשק ישיר למנתח ה-CSS של הדפדפן, כדי שיהיה קל לטעון מראש גיליונות סגנונות בלי להחדיר אותם ל-DOM.

בניית גיליון סגנונות

במקום להוסיף API חדש שיעזור לכם לעשות את זה, המפרט של Constructable StyleSheets מאפשר ליצור באופן מיידי גיליונות סגנונות על ידי הפעלת הבנאי CSSStyleSheet(). לאובייקט CSSStyleSheet שיתקבל יש שתי שיטות חדשות שמאפשרות להוסיף ולעדכן כללים של גיליון סגנונות באופן בטוח יותר, בלי להפעיל Flash of Unstyled Content (FOUC). השיטה replace() ו-replaceSync() מחליפות את גיליון הסגנונות במחרוזת של CSS, ו-replace() מחזירה Promise. בשני המקרים, אין תמיכה בהפניות של גיליון סגנונות חיצוני – המערכת מתעלמת מכללי @import, ותוצג אזהרה.

const sheet = new CSSStyleSheet();

// replace all styles synchronously:
sheet.replaceSync('a { color: red; }');

// replace all styles:
sheet.replace('a { color: blue; }')
  .then(() => {
    console.log('Styles replaced');
  })
  .catch(err => {
    console.error('Failed to replace styles:', err);
  });

// Any @import rules are ignored.
// Both of these still apply the a{} style:
sheet.replaceSync('@import url("styles.css"); a { color: red; }');
sheet.replace('@import url("styles.css"); a { color: red; }');
// Console warning: "@import rules are not allowed here..."

שימוש בדפי סגנונות מובנים

המאפיין החדש השני שמוצג ב-Constructable StyleSheets הוא מאפיין adoptedStyleSheets שזמין ב-Shadow Roots וב-Documents. כך אנחנו יכולים להחיל באופן מפורש את הסגנונות שהוגדרו על ידי CSSStyleSheet על עץ משנה נתון של DOM. לשם כך, אנחנו מגדירים את המאפיין למערך של גיליון סגנונות אחד או יותר שיש להחיל על הרכיב הזה.

// Create our shared stylesheet:
const sheet = new CSSStyleSheet();
sheet.replaceSync('a { color: red; }');

// Apply the stylesheet to a document:
document.adoptedStyleSheets.push(sheet);

// Apply the stylesheet to a Shadow Root:
const node = document.createElement('div');
const shadow = node.attachShadow({ mode: 'open' });
shadow.adoptedStyleSheets.push(sheet);

Putting it all together

With Constructable StyleSheets, web developers now have an explicit solution for creating CSS StyleSheets and applying them to DOM trees. We have a new Promise-based API for loading StyleSheets from a string of CSS source that uses the browser's built-in parser and loading semantics. Finally, we have a mechanism for applying stylesheet updates to all usages of a StyleSheet, simplifying things like theme changes and color preferences.

View Demo

Looking ahead

The initial version of Constructable Stylesheets shipped with the API described here, but there's work underway to make things easier to use. There's a proposal to extend the adoptedStyleSheets FrozenArray with dedicated methods for inserting and removing stylesheets, which would obviate the need for array cloning and avoid potential duplicate stylesheet references.

More information