การเลือกเทคนิคไอคอน
การจัดเก็บและการแสดงผลไอคอนเป็นตัวเลือกที่แยกกัน เช่น สไปรต์ 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.targetforced-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;
}
}
}
}
การรีเซ็ตจะป้องกันไม่ให้ค่าไอคอนเผยแพร่ไปยังรายการสืบทอด การเก็บไว้ในเลเยอร์จะทำให้การประกาศไอคอนที่ไม่มีเลเยอร์มีความสำคัญเหนือกว่าการรีเซ็ต