การใช้และการจัดการไอคอน

การเลือกเทคนิคไอคอน

การจัดเก็บและการแสดงผลไอคอนเป็นตัวเลือกที่แยกกัน เช่น สไปรต์ SVG สามารถระบุไอคอนให้กับระบบไอคอน CSS หรืออ้างอิงด้วย <use>

  • ระบบไอคอน CSS: ใช้เมื่อ CSS ควรเลือกเวลาและไอคอนที่จะแสดง ใช้มาสก์สำหรับไอคอนสีเดียวหรือรูปภาพพื้นหลังสำหรับไอคอนสีเต็ม
  • SVG ที่มี <use>: ใช้เพื่อใช้สัญลักษณ์ซ้ำเมื่อตัวเลือกการจัดรูปแบบในตัวเพียงพอแล้ว CSS ไม่สามารถจัดรูปแบบหรือสร้างภาพเคลื่อนไหวให้กับเนื้อหาของ SVG ที่อ้างอิงได้ตามใจชอบ แต่สามารถส่งต่อพร็อพเพอร์ตี้ที่รับค่ามาและคุณสมบัติที่กำหนดเองได้เมื่อออกแบบสัญลักษณ์ให้ใช้พร็อพเพอร์ตี้เหล่านั้น เช่น เส้นทางสามารถใช้ fill="var(--icon-accent, currentColor)" เพื่อให้ CSS กำหนดสีส่วนนั้นของไอคอนได้
  • SVG ในบรรทัด: ใช้เมื่อคุณต้องการการจัดรูปแบบหรือภาพเคลื่อนไหวที่กำหนดเองของเนื้อหา SVG
  • <img> ที่มีตัวกรอง CSS: หลีกเลี่ยงวิธีนี้ในการเปลี่ยนสีไอคอน ตัวกรองไม่สามารถใช้ค่าสี CSS ที่กำหนดเองกับรูปภาพได้อย่างน่าเชื่อถือ ดังนั้นการเปลี่ยนสีจึงยุ่งยากและไม่ยืดหยุ่น

โดยให้พิจารณาจากคำถาม 2 ข้อต่อไปนี้ CSS จำเป็นต้องเลือกหรือสลับไอคอน (ค่าเริ่มต้นของคอมโพเนนต์ การเปลี่ยนแปลงสถานะ การกำหนดธีม) หรือไม่ หากใช่ ให้ใช้ระบบไอคอน CSS คุณต้องการเข้าถึงภายในไอคอนนอกเหนือจากสีหรือไม่ หากใช่และคุณควบคุมแหล่งที่มาของไอคอน ให้ออกแบบสัญลักษณ์ด้วยคุณสมบัติที่กำหนดเองและใช้ <use> หากคุณไม่ได้ควบคุมแหล่งที่มา ให้แทรก SVG ในบรรทัด ชุดไอคอนของบุคคลที่สามไม่ค่อยแสดงคุณสมบัติที่กำหนดเอง ดังนั้น <use> จึงให้สีและอื่นๆ เพียงเล็กน้อย

ไอคอนแบบฝังหรือไอคอนระยะไกล

ทั้งระบบไอคอน CSS และ <use> สามารถใช้ไอคอนจาก URI ข้อมูล, ไฟล์เดี่ยว หรือสไปรต์ได้ การฝัง (URI ข้อมูลหรือ SVG ในบรรทัด) จะหลีกเลี่ยงคำขอและแสดงผลด้วย First Paint แต่จะทำให้ CSS หรือ HTML มีขนาดใหญ่เกินไปและไม่สามารถแคชแยกต่างหากได้ จึงเหมาะสำหรับชุดไอคอนขนาดเล็กที่ปรากฏในทุกหน้า ระบบจะแคชไฟล์แต่ละไฟล์แยกกันและโหลดตามต้องการ โดยมีค่าใช้จ่าย 1 คำขอต่อไฟล์ สไปรต์เป็นคำขอที่แคชได้ 1 รายการสำหรับทั้งชุด แต่จะดาวน์โหลดไอคอนทุกรายการไม่ว่าจะใช้หรือไม่ก็ตาม และ <use> จะอ้างอิงสไปรต์จากต้นทางเดียวกันได้เท่านั้น แนะนำให้ฝังไอคอนหลักจำนวนหนึ่งและสไปรต์หรือไฟล์เดี่ยวๆ สำหรับชุดที่ใหญ่ขึ้น

หากหน้าเว็บแสดงผลไอคอนหลายพันรายการพร้อมกัน ให้เปรียบเทียบหน้าเว็บและชิ้นงานจริง ในการทดสอบความเครียด SVG ในบรรทัดมีข้อได้เปรียบด้านประสิทธิภาพเล็กน้อยในระดับนั้น แต่ผลลัพธ์จะขึ้นอยู่กับเบราว์เซอร์และการใช้งาน การทดสอบความเครียดของไอคอน SVG ของ Cloud Four

แนวทางหลัก: เครื่องมือไอคอนที่ขับเคลื่อนด้วย CSS

ไอคอนคือโทเค็นการออกแบบ โดยไอคอนแต่ละรายการเป็นคุณสมบัติที่กำหนดเองซึ่งมีรูปภาพ และองค์ประกอบใดๆ ก็สามารถแสดงไอคอนได้โดยการตั้งค่า --icon-start หรือ --icon-end เครื่องมือนี้รวมความสามารถของ CSS 3 อย่างเข้าด้วยกัน ได้แก่

  • คุณสมบัติที่กำหนดเองที่ลงทะเบียนไว้ (@property) จะป้องกันไม่ให้ --icon-start และ --icon-end รับค่า ดังนั้นไอคอนที่ตั้งค่าในคอมโพเนนต์จะไม่ส่งต่อลงไปยังองค์ประกอบย่อย
  • การค้นหาสไตล์คอนเทนเนอร์ (@container style(...)) จะตรวจจับเมื่อองค์ประกอบมีไอคอนที่กำหนดและแสดงผลโดยไม่มีการเปลี่ยนแปลงคลาสหรือมาร์กอัป
  • มาสก์ CSS และ currentColor แสดงผลไอคอนในองค์ประกอบจำลองที่ใช้สีข้อความขององค์ประกอบ ระบบจะอ่านขนาด สี ระยะห่าง และออฟเซ็ตแนวตั้งจากพร็อพเพอร์ตี้ --icon-style-* ที่รับค่าได้พร้อมกับทางเลือกที่เหมาะสม ดังนั้นจึงสามารถจัดรูปแบบทั้งซับทรีใหม่จากระดับบนสุดได้ คำนำหน้า --icon-style- จะป้องกันไม่ให้การตั้งค่าเหล่านี้ขัดแย้งกับโทเค็นไอคอน ซึ่งอยู่ใน --icon-* ด้วย

การกำหนดโทเค็นการออกแบบไอคอน

กำหนดไอคอน SVG และการลบล้าง --icon-style-* เป็นคุณสมบัติที่กำหนดเองซึ่งนำมาใช้ซ้ำได้โดยใช้ URI ข้อมูล SVG ในบรรทัดหรือ Relative URL (เช่น url("/icons/trash.svg")) เมื่อโหลดไอคอนจากไฟล์ SVG ภายนอก ให้ใช้ Relative URL หรือ URI ข้อมูลที่ฝัง Relative URL ที่ใช้ผ่านคุณสมบัติที่กำหนดเองสามารถแก้ไขให้สัมพันธ์กับสไตล์ชีตที่ใช้ไอคอน แทนที่จะเป็นสไตล์ชีตที่กำหนดคุณสมบัติที่กำหนดเอง หากสไตล์ชีตเหล่านั้นอยู่ในไดเรกทอรีที่ต่างกัน URL อาจแก้ไขเป็นไฟล์ที่ไม่ถูกต้อง

หากต้องการเก็บ URL ที่สัมพันธ์กับสไตล์ชีตที่กำหนดโทเค็นไอคอน พร็อพเพอร์ตี้ที่ลงทะเบียนไว้จะช่วยได้ โดยค่าที่คำนวณแล้วของ <url> หรือ <image> ที่ลงทะเบียนไว้จะได้รับการแก้ไขตามสไตล์ชีตที่ประกาศไว้ อย่าพึ่งพาการลงทะเบียนโทเค็นเป็น <image> ด้วย URL ใน initial-value Chrome และ Safari จะแปลง URL initial-value เป็นเอกสาร ดังนั้นจึงใช้ได้เฉพาะใน Firefox เท่านั้น นอกจากนี้ Chrome ยังแก้ไขค่าที่ประกาศใน :root เทียบกับเอกสาร เว้นแต่ไวยากรณ์จะขึ้นต้นด้วย <url>

เมื่อหลีกเลี่ยง Relative URL ไม่ได้ เช่น สไตล์ชีตในไดเรกทอรีต่างๆ ให้ลงทะเบียนโทเค็นด้วยไวยากรณ์ที่ขึ้นต้นด้วย <url> และประกาศ URL จริงใน :root ซึ่งจะแก้ไขสไตล์ชีตที่ประกาศในทุกเบราว์เซอร์ ดังนี้

@property --icon-caret {
  /* The syntax must start with <url>. A syntax that starts with <image> resolves against the document in Chrome. */
  syntax: "<url> | <image> | none";
  inherits: true;
  initial-value: none;
}

:root {
  /* Declared here, the URL resolves against this stylesheet */
  --icon-caret: url("icons/caret.svg");
}

ตอนนี้แต่ละไอคอนจะอยู่ใน 2 ตำแหน่ง และมีต้นแบบมากขึ้น ดังนั้นวิธีนี้จึงคุ้มค่าก็ต่อเมื่อโปรเจ็กต์มีสไตล์ชีตในไดเรกทอรีต่างๆ และมีจำนวนไอคอนที่จัดการได้ เมื่อมีไอคอนมากกว่า 12 รายการ ให้ลงทะเบียนโทเค็น --icon-* (ยกเว้น --icon-style-*) จากสคริปต์ที่มี CSS.registerProperty โดยใช้ไวยากรณ์เดียวกัน แทนที่จะเขียน @property แต่ละรายการด้วยตนเอง พร็อพเพอร์ตี้ที่ลงทะเบียนเป็นแบบส่วนกลางและใช้ไม่ได้ใน Shadow Root ดังนั้นจึงอาจไม่เหมาะกับทุกโปรเจ็กต์ หาก URL ที่สัมพันธ์กับรูทหรือ URI ข้อมูลเป็นตัวเลือกหนึ่ง URL หรือ URI เหล่านี้จะใช้งานได้ง่ายกว่าและใช้ได้ทุกที่

:root {
  /* Optional: override the built-in fallbacks (1em, currentColor, 0.3em, -0.02em) */
  --icon-style-size: 1em;
  --icon-style-spacing: 0.4em;
  --icon-trash: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6h16Z'/%3E%3C/svg%3E");
  --icon-favorite: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/%3E%3C/svg%3E");
}

การแสดงผลไอคอนจากโทเค็น

องค์ประกอบจะแสดงไอคอนโดยตั้งค่า --icon-start (นำหน้า) หรือ --icon-end (ต่อท้าย) เป็นโทเค็นใดโทเค็นหนึ่งข้างต้น CSS 2 ส่วนจะเปลี่ยนการกำหนดนั้นให้เป็นไอคอนที่แสดงผล

ก่อนอื่น ให้ลงทะเบียน --icon-start และ --icon-end กับ @property ไวยากรณ์ "*" ยอมรับค่าใดก็ได้ และ inherits: false เป็นส่วนสำคัญ หากไม่มีไวยากรณ์นี้ ไอคอนที่ตั้งค่าไว้ในปุ่มจะรับค่าไปยังองค์ประกอบสืบทอดทุกรายการ และแต่ละรายการจะแสดงผลไอคอนด้วย

@property --icon-start {
  syntax: "*";
  inherits: false;
}

@property --icon-end {
  syntax: "*";
  inherits: false;
}

ประการที่ 2 การค้นหารูปแบบคอนเทนเนอร์จะตรวจจับเมื่อมีการตั้งค่าพร็อพเพอร์ตี้ในองค์ประกอบและแสดงผลไอคอนในองค์ประกอบจำลอง เนื่องจากองค์ประกอบจำลองไม่รับค่า --icon-start (มีการลงทะเบียนเป็นแบบไม่รับค่า) การประกาศแรกจึงส่งต่อค่าอย่างชัดแจ้งด้วย inherit การประกาศที่เหลือจะจัดการการปรับขนาด การมาสก์ การจัดแนว และระยะห่าง เนื่องจากการเติมมีค่าเริ่มต้นเป็น currentColor ไอคอนจึงใช้สีข้อความขององค์ประกอบและเป็นไปตามการเปลี่ยนสีขององค์ประกอบ

/* Style query for elements configuring a start icon */
@container style(--icon-start) {
  ::before {
    --icon-start: inherit; /* Forward the value inside the query block */
    content: "" / var(--icon-style-alt, "");
    display: inline-block;
    width: var(--icon-style-size, 1em);
    height: var(--icon-style-size, 1em);
    background-color: var(--icon-style-color, currentColor);
    mask: var(--icon-start) no-repeat center / contain;
    /* Center on the cap height, nudged slightly up for optical balance */
    vertical-align: calc(0.5cap - var(--icon-style-size, 1em) / 2 + var(--icon-style-voffset, -0.02em));
    flex: none;
    pointer-events: none;
    forced-color-adjust: none;
  }

  /* Automatically add spacing ONLY if the element has other text or sibling content */
  :where(:not(.icon, :empty))::before {
    margin-inline-end: var(--icon-style-spacing, 0.3em);
  }
}

การประกาศแต่ละรายการมีบทบาทของตัวเอง ดังนี้

  • vertical-align: middle จะจัดแนวให้ตรงกับครึ่งหนึ่งของความสูง x ซึ่งจะอยู่ต่ำอย่างเห็นได้ชัดสำหรับชุดไอคอนส่วนใหญ่ การจัดให้อยู่ตรงกลางใน 0.5cap จะทำให้จุดศูนย์กลางของไอคอนคงที่เมื่อ --icon-style-size ขยาย และ --icon-style-voffset เชิงลบขนาดเล็กจะชดเชยสายตาที่ให้น้ำหนักกับพื้นที่เหนือไอคอนมากกว่าพื้นที่ด้านล่าง
  • flex: none: องค์ประกอบเทียมที่ว่างเปล่ามีขนาดขั้นต่ำเป็น 0 ดังนั้นภายในปุ่ม Flex องค์ประกอบนี้จึงเป็นสิ่งแรกที่หดตัวเมื่อป้ายกำกับยาว ซึ่งอาจหดตัวจนไม่เหลืออะไรเลย ขนาดไอคอนเป็นการตัดสินใจด้านการออกแบบ ไม่ใช่สิ่งที่ควรต่อรองกับแรงกดดันด้านเลย์เอาต์
  • pointer-events: none: ป้องกันไม่ให้ไอคอนดักจับการคลิกหรือกลายเป็น event.target
  • forced-color-adjust: none: ในโหมดบังคับใช้สี เบราว์เซอร์จะแทนที่ background-color ซึ่งทำให้ไอคอนที่มาสก์หายไป ระบบจะคงการเติมมาสก์ไว้ และ currentColor จะยังคงเป็นไปตามสีข้อความที่บังคับ
  • content: "" / var(--icon-style-alt, ""): ข้อความสำรองสำหรับเนื้อหาที่สร้างขึ้นช่วยให้การควบคุมแบบไอคอนเท่านั้นใช้ชื่อที่เข้าถึงได้จากไอคอนผ่าน --icon-style-alt (ดูการควบคุมแบบไอคอนเท่านั้นด้านล่าง) แอตทริบิวต์ alt ที่ว่างเปล่าโดยค่าเริ่มต้นจะซ่อนไอคอนตกแต่งจากเทคโนโลยีความช่วยเหลือพิเศษ

สำหรับไอคอนต่อท้าย ให้ใช้รูปแบบเดียวกันกับ --icon-end และ ::after แทน --icon-start และ ::before ใช้ mask: var(--icon-end) และใช้การเว้นวรรคด้วย margin-inline-start แทน margin-inline-end

องค์ประกอบแบบสแตนด์อโลนและองค์ประกอบที่มีเฉพาะไอคอน

สำหรับไอคอนแบบสแตนด์อโลนหรือปุ่มที่มีเฉพาะไอคอน ให้ใช้ .icon กับองค์ประกอบที่ว่างเปล่าโดยตรง (ปุ่มสำหรับตัวควบคุมที่มีเฉพาะไอคอน) และตั้งค่าไอคอนด้วย --icon ในที่นี้ --icon คือพร็อพเพอร์ตี้ระดับสูงกว่า กฎ .icon:empty จะแมปพร็อพเพอร์ตี้นี้กับ --icon-start สำหรับไอคอนนำหน้า

.icon:empty {
  --icon-start: var(--icon);
}

ตัวอย่างการใช้

ค่าเริ่มต้นของคอมโพเนนต์ในสไตล์ชีต

ประโยชน์หลักของไอคอนในฐานะคุณสมบัติที่กำหนดเองคือไอคอนเหล่านี้จะอยู่ใน Cascade ตั้งค่าไอคอนในตัวเลือก แล้วองค์ประกอบที่ตรงกันทั้งหมดจะได้รับไอคอนดังกล่าวโดยไม่มีการเปลี่ยนแปลงมาร์กอัป

.button-delete {
  --icon-start: var(--icon-trash);
}

a[href^="http"]:not([href*="example.com"]) {
  --icon-end: var(--icon-external);
}
<button class="button-delete">Delete item</button>

การเปลี่ยนไอคอนตามสถานะ

เนื่องจากไอคอนเป็นเพียงพร็อพเพอร์ตี้ การเปลี่ยนสถานะจึงเป็นการลบล้าง CSS แบบธรรมดา ไม่มีองค์ประกอบที่ 2 ที่จะแสดงหรือซ่อน และไม่มีคลาสที่จะสลับ

.button-expand {
  --icon-start: var(--icon-caret-right);
}

.button-expand[aria-expanded="true"] {
  --icon-start: var(--icon-caret-down);
}

เช่นเดียวกับการนำเสนอ ให้ตั้งค่า --icon-style-size, --icon-style-color หรือ --icon-style-spacing ในคอนเทนเนอร์ เช่น แถบเครื่องมือ และไอคอนทุกรายการภายในจะอัปเดต

ไอคอนแบบใช้ครั้งเดียวที่มีสไตล์ในบรรทัด

องค์ประกอบที่ไม่มีกฎคอมโพเนนต์ครอบคลุมสามารถตั้งค่าพร็อพเพอร์ตี้เดียวกันในบรรทัดได้ เช่น <button style="--icon-start: var(--icon-trash)"> ให้ถือว่าวิธีนี้เป็นทางออกฉุกเฉินมากกว่าวิธีเริ่มต้น กล่าวคือ เมื่อไอคอนเดียวกันปรากฏในองค์ประกอบประเภทเดียวกันมากกว่า 1 ครั้ง ให้ย้ายไอคอนนั้นไปไว้ในกฎสไตล์ชีต

การควบคุมแบบไอคอนเท่านั้น

ปุ่มที่มีเฉพาะไอคอนจะใช้คลาส .icon และ --icon ที่อธิบายไว้ข้างต้น ตั้งชื่อที่เข้าถึงได้ให้ปุ่มด้วย aria-label หรือให้ไอคอนระบุชื่อผ่าน --icon-style-alt หากไม่มีทั้ง 2 อย่าง ไอคอนที่สร้างโดย CSS จะเป็นเพียงการตกแต่ง สำหรับไอคอนที่ให้ข้อมูลแบบสแตนด์อโลน ให้แสดงองค์ประกอบ .icon ด้วย role="img" และ aria-label ดังนี้

.button-close {
  --icon: var(--icon-close);
  --icon-style-alt: "Close";
}
<!-- Icon-only interactive control, icon and name from the stylesheet -->
<button class="icon button-close"></button>

<!-- Icon-only interactive control, named via aria-label -->
<button class="icon" style="--icon: var(--icon-trash);" aria-label="Delete item"></button>

<!-- Standalone informative icon -->
<span class="icon" style="--icon: var(--icon-favorite);" role="img" aria-label="Favorite"></span>

การทำงานกับ SVG โดยตรง

เมื่อระบบไอคอน CSS ไม่เหมาะสม ให้ใช้ SVG ในบรรทัดและ <use> ร่วมกันแทนที่จะใช้เป็นทางเลือก แทรก SVG ในบรรทัดเมื่อไอคอนปรากฏในหน้าเป็นครั้งแรก และอ้างอิงด้วย <use href="#id"> สำหรับการทำซ้ำทุกครั้ง การอ้างอิงในเครื่องไม่จำเป็นต้องส่งคำขอและไม่มีข้อจำกัดแบบข้ามต้นทาง สำรองสไปรต์ภายนอก (<use href="/icons.svg#id">) สำหรับไอคอนที่แชร์ในหลายๆ หน้า

เมื่อใช้ <use> ระบบจะโคลนเนื้อหาที่อ้างอิงลงใน Shadow Tree ดังนั้น CSS ของหน้าจึงเลือกองค์ประกอบของเนื้อหาไม่ได้ สิ่งที่เข้าถึงได้คือการรับค่า ซึ่งได้แก่ color, currentColor และคุณสมบัติที่กำหนดเอง นอกจากแอตทริบิวต์การนำเสนอ SVG แล้ว CSS สมัยใหม่ยังเปลี่ยนแอตทริบิวต์เรขาคณิตได้หลายรายการด้วย ดังนั้นไอคอนที่คุณควบคุมจึงแสดงฮุกที่คุณต้องการได้อย่างถูกต้อง เช่น stroke-width="var(--icon-stroke, 2)" หรือแม้แต่ d: var(--icon-path, path(…)) ในเส้นทางหนึ่งๆ

Safari ไม่รองรับ CSS d ดังนั้นให้ใช้การปรับแต่งนี้เฉพาะเมื่อยอมรับช่องว่างของการรองรับดังกล่าวได้เท่านั้น หากคุณไม่ได้ควบคุมไอคอน ให้แทรกไอคอนในบรรทัด

<use> ข้อควรระวังที่ควรรู้

  • viewBox ต้องอยู่บน <symbol> หรือ <svg> ที่อ้างอิง <svg> ด้านนอกที่รวม <use> จะไม่เลือกจากข้อมูลอ้างอิง ดังนั้นให้ตั้งค่า width และ height บน Wrapper และเก็บ viewBox ไว้กับสัญลักษณ์
  • สไตล์จะไม่ข้ามขอบเขตไปในทิศทางใดทิศทางหนึ่ง: <style> ภายในสไปรต์ภายนอกจะไม่มีผลกับหน้าเว็บ และสไตล์ชีตของหน้าเว็บจะไม่มีผลภายในต้นไม้ที่อ้างอิง ระบบจะส่งผ่านเฉพาะพร็อพเพอร์ตี้ที่รับค่ามาและคุณสมบัติที่กำหนดเองเท่านั้น
  • การอ้างอิงภายนอกเป็นแบบต้นทางเดียวกันเท่านั้น สไปรต์แบบข้ามต้นทางจะล้มเหลวโดยไม่มีการแจ้งเตือน
  • สไปรต์ที่แทรกในเอกสารจะใช้เนมสเปซ id ของหน้าร่วมกัน ดังนั้นให้ใช้เนมสเปซรหัสสัญลักษณ์เพื่อหลีกเลี่ยงการชนกัน

ทำเครื่องหมาย SVG ที่ใช้ตกแต่งด้วย aria-hidden="true" และตั้งชื่อที่เข้าถึงได้ให้กับตัวควบคุมที่มี SVG นั้น เช่นเดียวกับระบบไอคอน CSS

กลยุทธ์สำรอง

คุณสมบัติที่กำหนดเองที่ลงทะเบียนแล้ว

หากไม่มี @property, --icon-start และ --icon-end จะทำงานเป็นคุณสมบัติที่กำหนดเองซึ่งรับค่ามาตามปกติ ดังนั้นชุดไอคอนที่ตั้งค่าไว้ในองค์ประกอบหนึ่งจะแสดงผลในองค์ประกอบสืบทอดด้วย ป้องกันปัญหานี้ได้โดยรีเซ็ตพร็อพเพอร์ตี้ในองค์ประกอบย่อยภายในคิวรีสไตล์ (@container style(--icon-start) { * { --icon-start: initial; } }) ซึ่งเป็นวิธีเดียวกับวิธีแก้ปัญหาชั่วคราวของ Safari ด้านล่าง

การค้นหาสไตล์คอนเทนเนอร์

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

:where(.icon-start, .icon:empty)::before {
  content: image-set(linear-gradient(transparent 0 100%), var(--icon-start)) / var(--icon-style-alt, "");
  /* icon styles */
}

:where(.icon-start)::before {
  --icon-start: inherit;
}

:where(.icon:empty)::before {
  --icon-start: var(--icon);
}

:where(.icon-start:not(.icon, :empty))::before {
  margin-inline-end: var(--icon-style-spacing, 0.3em);
}

สำหรับไอคอนต่อท้าย ให้ใช้ Class Hook สำรองเดียวกันกับ .icon-end, --icon-end และ ::after แทน .icon-start, --icon-start และ ::before ใช้การเว้นวรรคกับเนื้อหาที่ไม่ว่างเปล่าด้วย margin-inline-start แทน margin-inline-end

รูปแบบ image-set() นี้ทำให้ content ไม่ถูกต้องเมื่อไม่ได้ตั้งค่าคุณสมบัติที่กำหนดเอง ดังนั้นจึงกลับไปใช้ none และองค์ประกอบจำลองจะหายไปโดยไม่ต้องเพิ่มหรือนำคลาสออก แต่ไม่ได้นำสไตล์อื่นๆ ขององค์ประกอบเทียมออกหรือป้องกันความขัดแย้งกับกฎ ::before หรือ ::after อื่นๆ ดังนั้นให้ใช้ฮุกเหล่านี้เฉพาะในกรณีที่องค์ประกอบเทียมเหล่านั้นพร้อมใช้งานสำหรับไอคอน

วิธีแก้ปัญหาเบราว์เซอร์ Safari

Safari มีข้อบกพร่องในการแสดงผล 2 รายการที่ส่งผลต่อไอคอน ได้แก่ WebKit #301609 ซึ่งอาจทำให้ไอคอนไม่ปรากฏจนกว่าผู้ใช้จะโต้ตอบ และ #320220 ซึ่งส่งผลต่อการแสดงผลไอคอนด้วย วิธีแก้ปัญหาด้านล่างจะช่วยแก้ปัญหาทั้ง 2 อย่างนี้

@keyframes webkit-301609 {}

@supports ((-webkit-nbsp-mode: normal) or (-webkit-touch-callout: none) or (font: -apple-system-body)) and (content-visibility: auto) {
  @layer webkit-301609-fix {
    ::before, ::after {
      animation: webkit-301609 0s;
    }
  }
}

คิวรี @supports กำหนดเป้าหมายเฉพาะ Safari และ @layer ช่วยลดความขัดแย้งของภาพเคลื่อนไหว

ข้อบกพร่อง #325900 ของ WebKit อาจทำให้การลบล้าง --icon-start โดยตรงไม่มีผลในบางกรณี เช่น การเปลี่ยนไอคอนเมื่อวางเมาส์เหนือ ซึ่งจะส่งผลต่อวิธีแก้ปัญหาสำหรับพร็อพเพอร์ตี้ที่จดทะเบียนซึ่งไม่รับค่าที่สืบทอดมา สำหรับ Safari ให้ลงทะเบียน --icon-start เป็นการรับค่าและรีเซ็ตในองค์ประกอบสืบทอดภายในคิวรีสไตล์ ดังนี้

@supports ((-webkit-nbsp-mode: normal) or
           (-webkit-touch-callout: none) or
           (font: -apple-system-body)) and (content-visibility: auto) {
  /* Override previous declaration */
  @property --icon-start {
    syntax: "*";
    inherits: true;
  }

  @layer webkit-325900-fix {
    @container style(--icon-start) {
      * {
        --icon-start: initial;
      }
    }
  }
}

การรีเซ็ตจะป้องกันไม่ให้ค่าไอคอนเผยแพร่ไปยังรายการสืบทอด การเก็บไว้ในเลเยอร์จะทำให้การประกาศไอคอนที่ไม่มีเลเยอร์มีความสำคัญเหนือกว่าการรีเซ็ต