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)
* {
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;
}
ตัวเลือกรหัส
ตัวเลือกรหัสจะเพิ่มความเฉพาะเจาะจงแบบรหัส ซึ่งจะเพิ่มคอมโพเนนต์ C
ขึ้น 1 รายการ ตราบใดที่คุณใช้ตัวเลือกรหัส (#myID
) ไม่ใช่ตัวเลือกแอตทริบิวต์ ([id="myID"]
)
ในตัวอย่างนี้ ความเฉพาะเจาะจงคือ (1,0,0)
#myID {
color: red;
}
ตัวเลือกอื่นๆ
CSS มีตัวเลือกมากมาย รายการเหล่านี้ไม่ได้เพิ่มความเฉพาะเจาะจงเสมอไป
เช่น คลาสจำลอง :not()
ไม่ได้เพิ่มอะไรในการคำนวณความเฉพาะเจาะจง
อย่างไรก็ตาม ระบบจะเพิ่มตัวเลือกที่ส่งเป็นอาร์กิวเมนต์ลงในการคํานวณความเฉพาะเจาะจง
div:not(.my-class) {
color: red;
}
ตัวอย่างนี้มีระดับความเฉพาะเจาะจงเป็น (0,1,1)
เนื่องจากมีตัวเลือกประเภท 1 รายการ (div
) และคลาส 1 รายการภายใน :not()
ทดสอบความเข้าใจ
ทดสอบความรู้เกี่ยวกับการให้คะแนนความเฉพาะเจาะจง
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,1)
รวมความเฉพาะเจาะจงทั้งหมดเท่ากับ (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 รายการมีความเฉพาะเจาะจงเท่ากัน ในกรณีนี้ การแสดงโฆษณาตามลำดับขั้นจะกลับไปที่ขั้นตอนลําดับการแสดง