The CSS Podcast - 003: Specificity
สมมติว่าคุณกําลังทํางานกับ HTML และ CSS ต่อไปนี้
<button class="branding">Hello, Specificity!</button>
.branding {
color: blue;
}
button {
color: red;
}
มีกฎ 2 ข้อที่กำหนดเป้าหมายไปยังองค์ประกอบเดียวกัน กฎแต่ละข้อมีการประกาศที่ต้องการตั้งค่าสีของปุ่ม โดยกฎหนึ่งพยายามทำให้ปุ่มเป็นสีแดง และอีกกฎหนึ่งพยายามทำให้ปุ่มเป็นสีน้ำเงิน การประกาศใดมีผลกับองค์ประกอบ
การทำความเข้าใจอัลกอริทึมความเฉพาะเจาะจงของ CSS เป็นกุญแจสำคัญในการทำความเข้าใจวิธีที่ CSS ตัดสินใจระหว่างประกาศที่แข่งขันกัน
ความเฉพาะเจาะจงเป็นหนึ่งในระยะที่แตกต่างกันของการแสดงโฆษณาตามลำดับขั้น ซึ่งเราได้พูดถึงในโมดูลที่แล้วเกี่ยวกับการแสดงโฆษณาตามลำดับขั้น
การให้คะแนนความเฉพาะเจาะจง
กฎตัวเลือกแต่ละรายการภายในต้นทางจะได้รับคะแนน คุณอาจมองความเฉพาะเจาะจงเป็นคะแนนรวม และตัวเลือกแต่ละประเภทจะได้รับคะแนนตามคะแนนนั้น การประกาศจากกฎที่มีความเฉพาะเจาะจงสูงสุดจะเป็นผู้ชนะ
ในแง่ความเฉพาะเจาะจงของโปรเจ็กต์จริง การปรับสมดุลคือการตรวจสอบว่ากฎ CSS ที่คุณคาดหวังให้ใช้งานได้ใช้งานได้จริง ในขณะเดียวกันก็รักษาคะแนนให้ต่ำอยู่เสมอเพื่อป้องกันความซับซ้อน ความเฉพาะเจาะจงควรสูงเท่าที่จำเป็นเท่านั้น แทนที่จะมุ่งเน้นที่ความเฉพาะเจาะจงสูงสุด ในอนาคต เราอาจต้องใช้ CSS ที่สำคัญกว่าจริงๆ หากคุณใช้ความเฉพาะเจาะจงสูงสุด จะทำให้งานนั้นยากขึ้น
ลักษณะเฉพาะไม่ใช่ตัวเลขทศนิยม แต่เป็นชุด 3 รายการที่ประกอบด้วย A, B และ C
A: ความเฉพาะเจาะจงที่คล้ายกับรหัสB: ความเฉพาะเจาะจงที่คล้ายกับคลาสC: ความเฉพาะเจาะจงที่คล้ายกับองค์ประกอบ
ซึ่งมักจะแสดงโดยใช้เครื่องหมาย (A,B,C) เช่น (1,0,2)
สัญกรณ์ A-B-C สำรองก็ใช้กันโดยทั่วไปเช่นกัน
วิธีเปรียบเทียบความเฉพาะเจาะจง
ระบบจะเปรียบเทียบความเฉพาะเจาะจงโดยเปรียบเทียบองค์ประกอบ 3 รายการตามลําดับ ดังนี้ ความเฉพาะเจาะจงที่มีค่า A มากกว่าจะมีความเฉพาะเจาะจงมากกว่า หากค่า A 2 ค่าเท่ากัน ความเฉพาะเจาะจงที่มีค่า B มากกว่าจะมีความเฉพาะเจาะจงมากกว่า หากค่า B 2 ค่าเท่ากัน ความเฉพาะเจาะจงที่มีค่า C มากกว่าจะมีความเฉพาะเจาะจงมากกว่า หากค่าทั้งหมดเท่ากัน ความเฉพาะเจาะจง 2 รายการจะเท่ากัน
ตัวอย่างเช่น ระบบจะถือว่า (1,0,0) มีความเฉพาะเจาะจงมากกว่า (0,4,3) เนื่องจากค่า A ใน (1,0,0) (ซึ่งเป็น 1) มากกว่าค่า A จาก (0,4,3) (ซึ่งเป็น 0)
ตัวเลือกมีผลต่อความเฉพาะเจาะจง
แต่ละส่วนในชุดค่าผสม 3 รายการของความเฉพาะเจาะจงจะเริ่มต้นด้วยค่า 0 ดังนั้นความเฉพาะเจาะจงเริ่มต้นจึงเป็น (0,0,0)
แต่ละส่วนของตัวเลือกจะเพิ่มความเฉพาะเจาะจง ซึ่งจะเพิ่มค่าของ A, B หรือ C โดยขึ้นอยู่กับประเภทของตัวเลือก
ตัวเลือกส่วนกลาง
ตัวเลือกแบบสากล (*)
จะเพิ่มความเฉพาะเจาะจงเป็น 0 โดยค่าของตัวเลือกจะยังคงมีความเฉพาะเจาะจงเริ่มต้นที่ (0,0,0)
* {
color: red;
}
ตัวเลือกองค์ประกอบหรือองค์ประกอบจำลอง
ตัวเลือกองค์ประกอบ (ประเภท) หรือองค์ประกอบจำลองจะเพิ่มความเฉพาะเจาะจงแบบองค์ประกอบ ซึ่งจะเพิ่มคอมโพเนนต์ C ขึ้น 1
ตัวอย่างต่อไปนี้มีความเฉพาะเจาะจงโดยรวมเท่ากับ (0,0,1)
ตัวเลือกประเภท
div {
color: red;
}
ตัวเลือกองค์ประกอบจำลอง
::selection {
color: red;
}
ตัวเลือกคลาส คลาสจำลอง หรือแอตทริบิวต์
ตัวเลือกคลาส, คลาสจำลอง หรือแอตทริบิวต์จะเพิ่มความเฉพาะเจาะจงแบบคลาส ซึ่งจะเพิ่มคอมโพเนนต์ B ขึ้น 1
ตัวอย่างต่อไปนี้มีความเฉพาะเจาะจง (0,1,0)
ตัวเลือกคลาส
.my-class {
color: red;
}
ตัวเลือกคลาสจำลอง
:hover {
color: red;
}
ตัวเลือกแอตทริบิวต์
[href='#'] {
color: red;
}
ตัวเลือกรหัส
ตัวเลือกรหัสจะเพิ่มความเฉพาะเจาะจงแบบรหัส ซึ่งจะเพิ่มคอมโพเนนต์ A ขึ้น 1 รายการ ตราบใดที่คุณใช้ตัวเลือกรหัส (#myID) ไม่ใช่ตัวเลือกแอตทริบิวต์ ([id="myID"])
ในตัวอย่างนี้ ความเฉพาะเจาะจงคือ (1,0,0)
#myID {
color: red;
}
ตัวเลือกอื่นๆ
CSS มีตัวเลือกมากมาย รายการเหล่านี้ไม่ได้เพิ่มความเฉพาะเจาะจงเสมอไป
เช่น คลาสจำลอง :not() ไม่ได้เพิ่มอะไรในการคำนวณความเฉพาะเจาะจง
อย่างไรก็ตาม ระบบจะเพิ่มตัวเลือกที่ส่งเป็นอาร์กิวเมนต์ลงในการคํานวณความเฉพาะเจาะจง
div:not(.my-class) {
color: red;
}
นอกจากนี้ คลาสจำลอง [:is()](https://developer.mozilla.org/en-US/docs/Web/CSS/:is) ก็ไม่ได้เพิ่มลงในการคํานวณความเฉพาะเจาะจง เช่นเดียวกับ :not() ฟังก์ชันนี้จะพิจารณาความเฉพาะเจาะจงของอาร์กิวเมนต์ที่เฉพาะเจาะจงที่สุด
:is(h1, h2, h3) {
color: blue;
}
ตัวอย่างนี้มีระดับความเฉพาะเจาะจง (0,0,1) เนื่องจากมีตัวเลือก (type) เพียงประเภทเดียว
เมื่อเพิ่ม id ความเฉพาะเจาะจงจะเพิ่มขึ้นเป็น (1,0,0)
:is(h1, h2, h3, #my-heading) {
color: blue;
}
[:where()](https://developer.mozilla.org/docs/Web/CSS/:where) คลาสจำลอง
จะแตกต่างออกไป ไม่ว่าอาร์กิวเมนต์ใดจะมีความเฉพาะเจาะจงเพียงใด อาร์กิวเมนต์ดังกล่าวก็มีความเฉพาะเจาะจงเป็น (0,0,0) เสมอ
:where(h1, h2, h3, #my-heading) {
color: blue;
}
รูปแบบที่มีความเฉพาะเจาะจงต่ำซึ่งใช้ :where() จะช่วยให้คุณลบล้างรูปแบบเหล่านี้ด้วยตัวเลือกพื้นฐานในภายหลังในสไตล์ชีตได้
:where(#my-content) {
color: red;
}
p {
color: blue;
}
แม้ว่า :where() จะมี id ในรายการอาร์กิวเมนต์ แต่ก็ยังมีความเฉพาะเจาะจงของ (0, 0, 0) เท่านั้น ดังนั้นตัวเลือก p พื้นฐานจึงลบล้างและข้อความจะเป็น blue
ทดสอบความเข้าใจ
ทดสอบความรู้เกี่ยวกับการให้คะแนนความเฉพาะเจาะจง
a[href="#"] มีความเฉพาะเจาะจงอย่างไร
(0,0,1)a มีมูลค่า (0,0,1) แต่ [href="#"] มีมูลค่า (0,1,0)(0,1,0)a มีมูลค่า (0,0,1) แต่ [href="#"] มีมูลค่า (0,1,0)(0,1,1)a มีค่าเท่ากับ (0,0,1) และ [href="#"] มีค่าเท่ากับ (0,1,0) รวมความเฉพาะเจาะจงทั้งหมดเท่ากับ (0,1,1)ปัจจัยที่ไม่ส่งผลต่อความเฉพาะเจาะจง
ความเข้าใจผิดที่พบบ่อยเกี่ยวกับปัจจัยต่อไปนี้ที่ส่งผลต่อความเฉพาะเจาะจงมีดังนี้
แอตทริบิวต์ของสไตล์แบบอินไลน์
CSS ที่นําไปใช้กับแอตทริบิวต์ style ขององค์ประกอบโดยตรงจะไม่ส่งผลต่อความเฉพาะเจาะจง เนื่องจากเป็นขั้นตอนอื่นในการแสดงผลตามลําดับชั้นที่ประเมินก่อนความเฉพาะเจาะจง
<div style="color: red"></div>
หากต้องการลบล้างการประกาศนี้จากภายในสไตล์ชีต คุณต้องใช้การประกาศที่ชนะในขั้นตอนก่อนหน้าของลำดับชั้น
เช่น คุณอาจเพิ่ม !important เข้าไปเพื่อให้เป็นส่วนหนึ่งของต้นทาง !important ที่มีการเขียน
การประกาศ !important รายการ
!important ที่ท้ายการประกาศ CSS จะไม่ส่งผลต่อความเฉพาะเจาะจง แต่จะนำการประกาศไปไว้ในต้นทางอื่น ซึ่งก็คือ !important ที่เขียน
ในตัวอย่างต่อไปนี้ ความเฉพาะเจาะจงของ .my-class ไม่เกี่ยวข้องกับการประกาศ !important ที่จะชนะ
.my-class {
color: red !important;
color: white;
}
เมื่อการประกาศ 2 รายการเป็น !important ระบบจะใช้ความเฉพาะเจาะจงอีกครั้งเนื่องจากขั้นตอนต้นทางจากการแสดงผลตามลำดับขั้นยังไม่สามารถระบุผู้ชนะได้
.branding {
color: blue !important;
}
button {
color: red !important;
}
ความเฉพาะเจาะจงในบริบท
เมื่อใช้ตัวเลือกที่ซับซ้อนหรือแบบผสม แต่ละส่วนของตัวเลือกนั้นจะเพิ่มความเฉพาะเจาะจง ลองดูตัวอย่าง HTML ต่อไปนี้
<a class="my-class another-class" href="#">A link</a>
ลิงก์นี้มี 2 ชั้นเรียน
กฎใน CSS ต่อไปนี้มีความเฉพาะเจาะจงของ (0,0,1)
a {
color: red;
}
หากคุณอ้างอิงคลาสใดคลาสหนึ่งในตัวเลือก คลาสนั้นจะมีความเฉพาะเจาะจงของ (0,1,1) ดังนี้
a.my-class {
color: green;
}
เพิ่มคลาสอื่นลงในตัวเลือก ตอนนี้คลาสมีความเฉพาะเจาะจงของ (0,2,1)
a.my-class.another-class {
color: rebeccapurple;
}
เพิ่มแอตทริบิวต์ href ลงในตัวเลือก แล้วตอนนี้ตัวเลือกจะมีความเฉพาะเจาะจงของ (0,3,1) ดังนี้
a.my-class.another-class[href] {
color: goldenrod;
}
สุดท้าย ให้เพิ่ม:hoverคลาสจำลองลงในรายการทั้งหมดนั้น
ตัวเลือกจะมีความเฉพาะเจาะจงของ (0,4,1) ดังนี้
a.my-class.another-class[href]:hover {
color: lightgrey;
}
ทดสอบความเข้าใจ
ทดสอบความรู้เกี่ยวกับการให้คะแนนความเฉพาะเจาะจง
ตัวเลือกใดต่อไปนี้มีความเฉพาะเจาะจงของ (0,2,1)
article > section(0,0,2)article.card.dark(0,2,1)article:hover a[href](0,0,1)), ตัวเลือกแอตทริบิวต์ (มูลค่า (0,0,1)) และตัวเลือกคลาส (มูลค่า (0,0,1)) ซึ่งทําให้ตัวเลือกนี้มีความเฉพาะเจาะจงทั้งหมด (0,2,2)การเพิ่มความเฉพาะเจาะจงอย่างมีเหตุผล
สมมติว่าคุณมี CSS ที่มีลักษณะดังนี้
.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
ด้วย HTML ที่มีลักษณะดังนี้
<button class="my-button" onclick="alert('hello')">Click me</button>
ปุ่มมีพื้นหลังสีเทาเนื่องจากตัวเลือกที่ 2 มีความเฉพาะเจาะจงของ (0,1,1)
เนื่องจากมีตัวเลือกประเภท (button) 1 รายการ ซึ่งก็คือ (0,0,1) และตัวเลือกแอตทริบิวต์ ([onclick]) ซึ่งก็คือ (0,1,0)
กฎก่อนหน้า .my-button เท่ากับ (0,1,0)เนื่องจากมีตัวเลือกคลาส 1 รายการ ซึ่งมีความเฉพาะเจาะจงน้อยกว่า (0,1,1)
หากต้องการเพิ่มประสิทธิภาพของกฎนี้ ให้ใช้ตัวเลือกคลาสซ้ำ ดังนี้
.my-button.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
ตอนนี้ปุ่มจะมีพื้นหลังสีน้ำเงินเนื่องจากตัวเลือกใหม่มีความเฉพาะเจาะจง (0,2,0)
ในกรณีที่มีความละเอียดเท่ากัน ระบบจะกลับไปที่ขั้นตอนถัดไปในการแสดงโฆษณาตามลำดับขั้น
ต่อไปเราจะใช้ตัวอย่างปุ่มนี้ เปลี่ยน CSS เป็นดังนี้
.my-button {
background: blue;
}
[onclick] {
background: grey;
}
ปุ่มมีพื้นหลังสีเทาเนื่องจากตัวเลือกทั้ง 2 รายการมีความเฉพาะเจาะจงเหมือนกันที่ (0,1,0)
หากคุณเปลี่ยนกฎตามลําดับแหล่งที่มา ปุ่มจะเปลี่ยนเป็นสีน้ำเงิน
[onclick] {
background: grey;
}
.my-button {
background: blue;
}
เนื่องจากตัวเลือกทั้ง 2 รายการมีความเฉพาะเจาะจงเท่ากัน ในกรณีนี้ การแสดงโฆษณาตามลำดับขั้นจะกลับไปที่ขั้นตอนลําดับการแสดง