สไตล์ชีตที่สร้างได้

สไตล์ที่นำมาใช้ซ้ำได้อย่างราบรื่น

เจสัน มิลเลอร์
เจสัน มิลเลอร์

สไตล์ชีตที่สร้างได้คือวิธีสร้างและเผยแพร่สไตล์ที่นำมาใช้ใหม่ได้เมื่อใช้ Shadow DOM

การสนับสนุนเบราว์เซอร์

  • 73
  • 79
  • 101
  • 16.4

แหล่งที่มา

คุณสามารถสร้างสไตล์ชีตโดยใช้ JavaScript ได้เสมอ แต่ที่ผ่านมาขั้นตอนนี้คือการสร้างองค์ประกอบ <style> โดยใช้ document.createElement('style') แล้วเข้าถึงพร็อพเพอร์ตี้ชีตเพื่อรับการอ้างอิงไปยังอินสแตนซ์ CSSStyleSheet ที่เกี่ยวข้อง วิธีนี้สามารถสร้างโค้ด CSS ที่ซ้ำกันและการขยายตัวของผู้ดูแลได้ และการแนบจะนำไปสู่เนื้อหาที่ไม่มีสไตล์แบบแฟลชไม่ว่าจะมีการขยายตัวหรือไม่ อินเทอร์เฟซ CSSStyleSheet คือรูทของคอลเล็กชันอินเทอร์เฟซการแทน CSS ที่เรียกว่า CSSOM ซึ่งเป็นวิธีแบบเป็นโปรแกรมในการจัดการสไตล์ชีตและขจัดปัญหาที่เกี่ยวข้องกับเมธอดแบบเดิม

แผนภาพแสดงการเตรียมการและการใช้ CSS

สไตล์ชีตที่สร้างได้ช่วยให้กำหนดและเตรียมสไตล์ CSS ที่แชร์ แล้วใช้รูปแบบเหล่านั้นกับ Shadow Roots หรือเอกสารหลายรายการได้อย่างง่ายดายและไม่ซ้ำซ้อน การอัปเดต CSSStyleSheet ที่แชร์จะมีผลกับรูททั้งหมดที่นำไปใช้ และการนำสไตล์ชีตมาใช้จะทำได้อย่างรวดเร็วและซิงโครนัสเมื่อโหลดชีตแล้ว

การเชื่อมโยงที่ตั้งค่าโดยสไตล์ชีตที่สร้างได้จะให้ผลดีสำหรับแอปพลิเคชันต่างๆ ซึ่งอาจใช้เพื่อสร้างธีมส่วนกลางที่คอมโพเนนต์ต่างๆ ใช้อยู่ เช่น ธีมอาจเป็นอินสแตนซ์ CSSStyleSheet ที่ส่งไปยังคอมโพเนนต์ได้ โดยการอัปเดตธีมจะเผยแพร่ไปยังคอมโพเนนต์โดยอัตโนมัติ สามารถใช้เพื่อกระจายค่าพร็อพเพอร์ตี้ที่กำหนดเองของ CSS ไปยังทรีย่อย DOM ที่เฉพาะเจาะจงโดยไม่ต้องอาศัยการเรียงซ้อน ยังสามารถใช้เป็นอินเทอร์เฟซโดยตรงไปยังโปรแกรมแยกวิเคราะห์ CSS ของเบราว์เซอร์ได้ด้วย ทำให้การโหลดสไตล์ชีตล่วงหน้าเป็นเรื่องง่ายโดยไม่ต้องแทรกลงใน DOM

การสร้างสไตล์ชีต

แทนที่จะนำ API ใหม่มาใช้เพื่อให้บรรลุเป้าหมายนี้ ข้อกำหนดของ Constructable Stylesheets ช่วยให้สามารถสร้างสไตล์ชีตที่จำเป็นได้โดยเรียกใช้ตัวสร้าง CSSStyleSheet() ออบเจ็กต์ CSSStyleSheet ที่ได้จะมีวิธีการใหม่ 2 วิธีที่ช่วยให้เพิ่มและอัปเดตกฎของสไตล์ชีตได้อย่างปลอดภัยยิ่งขึ้นโดยไม่ต้องเรียกใช้ Flash ของเนื้อหาที่ไม่มีสไตล์ (FOUC) ทั้งเมธอด replace() และ replaceSync() จะแทนที่สไตล์ชีตด้วยสตริง CSS และ replace() จะแสดง Promise ในทั้ง 2 กรณี ระบบจะไม่รองรับการอ้างอิงสไตล์ชีตภายนอก โดยระบบจะไม่สนใจกฎ @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..."

การใช้สไตล์ชีตที่สร้างขึ้น

ฟีเจอร์ใหม่รายการที่ 2 ของ Constructable Stylesheets คือพร็อพเพอร์ตี้ adoptedStyleSheets ซึ่งใช้ได้ใน Shadow Roots และ Documents วิธีนี้ช่วยให้เรานำรูปแบบที่ CSSStyleSheet กำหนดไว้ไปใช้กับทรีย่อย DOM ที่ระบุได้อย่างชัดเจน วิธีการคือเราตั้งค่าพร็อพเพอร์ตี้เป็นอาร์เรย์ของสไตล์ชีตอย่างน้อย 1 รายการเพื่อใช้กับองค์ประกอบนั้น

// 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