ลักษณะเฉพาะ

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,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
องค์ประกอบจะเพิ่มความเฉพาะเจาะจงแบบองค์ประกอบ (คอมโพเนนต์ "C") ตัวเลือกนี้มี 2 องค์ประกอบ จึงมีความเฉพาะเจาะจงที่ (0,0,2)
article.card.dark
องค์ประกอบจะเพิ่มความเฉพาะเจาะจงแบบองค์ประกอบ (คอมโพเนนต์ "C") และคลาสจะเพิ่มความเฉพาะเจาะจงแบบคลาส (คอมโพเนนต์ "B") การมีคลาส 2 รายการและองค์ประกอบ 1 รายการทําให้ตัวเลือกนี้มีความเฉพาะเจาะจง (0,2,1)
article:hover a[href]
องค์ประกอบจะเพิ่มความเฉพาะเจาะจงแบบองค์ประกอบ (คอมโพเนนต์ "C") ส่วนคลาสจำลองและแอตทริบิวต์จะเพิ่มความเฉพาะเจาะจงแบบคลาส (คอมโพเนนต์ "B") มีตัวเลือกองค์ประกอบ 2 รายการ (2 × (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 รายการมีความเฉพาะเจาะจงเท่ากัน ในกรณีนี้ การแสดงโฆษณาตามลำดับขั้นจะกลับไปที่ขั้นตอนลําดับการแสดง

แหล่งข้อมูล