มารู้จักหลักการ Specificity ใน CSS กัน

มารู้จักหลักการ Specificity ใน CSS กัน

Specificity

ต่อเนื่องจากบทความที่แล้วที่ผมได้อธิบายถึงหลักการ Cascade ไปแล้ว คราวนี้ลองมาทำความเข้าใจกับอีกหลักการหนึ่งที่คนเขียน CSS ทุกคนจะต้องเข้าใจ นั่นก็คือหลักการ Specificity หรือหลักการเฉพาะเจาะจง สรุปให้เข้าใจกันง่ายๆสำหรับหลักการ Specificity นี้ก็คือ เมื่อเว็บบราวเซอร์เจอกับคำสั่ง CSS ที่สั่งไปที่แท็กเดียวกัน เว็บบราเซอร์จะเลือกแสดงผลจากคำสั่งที่มีการเขียน Selector ที่เฉพาะเจาะจงกว่าเป็นหลัก เช่น
body p {
color: blue;
}

p {
color: yellow;
}
.
.
.
<p>วันนี้ผมมีความสุขมากๆ</p>

ถ้าอิงตามหลักการ Casecade อย่างเดียว ข้อความ”วันนี้ผมมีความสุขมากๆ”จะต้องแสดงเป็นสีเหลืองเพราะเป็นคำสั่งที่เขียนตามมาทีหลัง แต่เมื่อมีการใช้หลักการ Specificity เข้ามาประกอบด้วย ข้อความนี้จะแสดงเป็นสีฟ้าแทน ท้้งนี้เนื่องจาก Selector ที่เขียน body p (เลือกแท็ก <p> ที่อยู่ในแท็ก <body> อีกที) มีความเฉพาะเจาะจงกว่า Selector ที่เขียนแค่ p (เลือกแท็ก <p> ไหนก็ได้ในหน้านี้)

จริงๆแล้วทางคณะกรรม W3C มีหลักการในการคำนวณค่า Specificity แต่ในทางปฏิบัติแล้วเราไม่จำเป็นต้องเข้าใจการคำนวณค่าถึงขนาดนั้น ขอเพียงแค่เราเข้าใจภาพรวมของหลักการ Specificity และรู้ว่าการเขียน Selector แบบไหนมีความเฉพาะเจาะจงมากน้อยกว่ากันยังไงก็พอแล้ว

ตัวอย่างลำดับของการเขียน Select เรียงตามความเฉพาะเจาะจงหรือระดับ Specificity จากน้อยไปหามาก

p { }
(เลือกแท็ก <p> ไหนก็ได้ที่อยู่ในหน้า)

div p { }
(เลือกเฉพาะแท็ก <p> ที่อยู่ในแท็ก <div> อีกทีหนึ่งเท่านั้น)

p.intro { }
(เลือกเฉพาะแท็ก <p> ที่ Class ชื่อ intro เท่านั้น)

p.intro .important { }
(เลือกเฉพาะแท็กที่มี Class ชื่อ important ที่อยู่ภายในแท็ก <p> ที่ Class ชื่อ intro อีกทีหนึ่งเท่านั้น)

#mainmenu { }
(เลือกเฉพาะแท็กที่มี ID ชื่อ mainmenu เท่านั้น)

div#mainmenu { }
(เลือกเฉพาะแท็ก <div> ที่มี ID ชื่อ mainmenu เท่านั้น)

#mainmenu .submenu { }
(เลือกเฉพาะแท็กที่มี Class ชื่อ submenu ที่อยู่ภายในแท็กที่มี ID ชื่อ mainmenu อีกทีหนึ่งเท่านั้น)

#header #mainmenu { }
(เลือกเฉพาะแท็กที่มี ID ชื่อ mainmenu ที่อยู่ภายในแท็กที่มี ID ชื่อ header อีกทีหนึ่งเท่านั้น)

จะสังเกตได้ว่า Selector ที่มีการระบุ ID จะมีความเฉพาะเจาะจงมากกว่า Selector ที่ระบุด้วย Class ทั้งนี้เนื่องจาก ID สามารถใช้ได้กับแค่แท็กเดียวในหน้า แต่ Class สามารถใช้ได้กับหลายแท็กในหน้าเดียวกัน

การเขียนโดยใช้หลัก Specificity ให้เป็นประโยชน์ ผมแนะนำให้เริ่มเขียนจากกว้างๆก่อน แล้วค่อยๆเพิ่มความเฉพาะเจาะจงในภายหลังเมื่อเราต้องการปรับแต่งรายละเอียดการแสดงผลเพิ่มเติม เช่น

เริ่มต้นการสั่งการแสดงผลสำหรับแท็ก <p> โดยทั่วไปในหน้าก่อน เช่น
p {
font-size: 14px;
color: orange;
}

จากนั้นค่อยเพิ่มความเฉพาะเจาะจงให้กับแท็ก <p> ต่อมาในภายหลัง
p.intro {
font-size: 16px;
font-weight: bold;
color: yellow;
}

นอกจากการเข้าใจหลักการ Specificity จะมีส่วนช่วยให้เราเขียนคำสั่ง CSS ได้ดีและรอบครอบมากขึ้นแล้ว หลักการนี้ยังมีประโยชน์มากๆตอนที่เราต้องเข้าไปแก้ปัญหาเว็บบราวเซอร์ไม่แสดงผลตามคำสั่ง CSS ที่เราเขียน เช่น สมมุติว่าเรามีปัญหาแท็ก <p> ไม่ยอมแสดงผลของคำสั่ง color: yellow; ถึงแม้คุณจะเขียนคำสั่งไว้ต่อท้ายสุดของชุดคำสั่งตามหลักของ Cascade แล้วก็ตาม นั่นก็เป็นไปได้ว่าคุณกำลังเจอปัญหาว่าคำสั่งที่คุณเขียนไว้ก่อนหน้านี้มี Specificity ที่สูงกว่า ดังนั้นวิธีแก้ไขก็สามารถทำได้ง่ายๆก็คือการเพิ่มความเฉพาะเจาะจงให้กับการเขียน Selector ของคุณนั่นเอง  ในกรณีที่มีแท็ก ID ชื่อ content ครอบแท็ก <p> ก็ให้คุณเพิ่ม #content เข้าไปใน Selector เพื่อเพิ่มระดับ Specificity

#content p.intro {
font-size: 16px;
font-weight: bold;
color: yellow;
}

เท่านี้เว็บบราวเซอร์ก็จะแสดงข้อความในแท็ก <p> เป็นสีเหลืองอย่างที่คุณต้องการได้แล้ว

สรุป
หลักกการ Specificity
ถ้าบราวเซอร์เจอคำสั่ง CSS สำหรับแท็กๆเดียวกันซ้ำๆกัน บราวเซอร์จะเลือกใช้คำสั่งที่เจาะจงที่สุด

หลักการ Cascade
ถ้าบราวเซอร์เจอคำสั่ง CSS สำหรับแท็กๆเดียวกันซ้ำๆกัน บราวเซอร์จะเลือกใช้คำสั่งที่มาทีหลังสุด

แถมให้อีกนิดนึงครับ นอกจากหลักการ Specificity ในการช่วยเขียน CSS ให้ดีขึ้นได้แล้ว เรายังสามารถใช้คำสั่ง CSS ที่มีความเฉพาะเจาะจงที่แตกต่างกันได้ด้วยครับ เช่นคำสั่งที่เป็นคำสั่งลัด (Shortcut) อย่าง margin, padding, background และ list-style จะมีความเฉพาะเจาะจงน้อยกว่าคำสั่งในตระกูลเดียวกัน เช่น

margin มีความเฉพาะเจาะจงน้อยกว่า margin-top, margin-right, margin-bottom, margin-left

padding มีความเฉพาะเจาะจงน้อยกว่า padding-top, padding-right, padding-bottom, padding-left

background มีความเฉพาะเจาะจงน้อยกว่า background-color, background-image, background-repeat, background-attachment, background-position

list-style มีความเฉพาะเจาะจงน้อยกว่า list-style-image, list-style-position, list-style-type

เช่น
h4 {
margin-left: 10px;
}

body h4 {
margin: 20px 0 40px 5px;
}

ถืงแม้ตามหลัก Cascade และ Specification ของคำสั่ง body h4 จะสูงกว่าของคำสั่ง h4 กันเห็นๆ แต่แทนที่บราวเซอร์จะแสดงผล margin ซ้ายแท็ก <h4> เป็น 5px แต่กลับแสดงผลเป็น 10px นั่นเป็นเพราะ margin-left มีความเฉพาะเจาะจงมากกว่าเพราะมีการระบุไปเลยว่าเป็น margin ด้านไหน ด้วยเหตุนี้ผมจึงขอแนะนำให้เขียนโดยใช้คำสั่งลัด(shortcut)อย่าง margin, padding, background และ list-style ก่อน แล้วเก็บคำสั่งที่เฉพาะเจาะจงในตระกูลเดียวกันไว้เขียนทีหลัง เพื่อให้เราสามารถปรับแต่งคำสั่งเพิ่มเติมต่อไปในอนาคตได้ง่ายมากยิ่งขึ้นครับ

มีการตอบกลับหนึ่งครั้ง »

  1. Pingback: การเข้าใจหลักการ Cascade นั้นสำคัญไฉน « margin0auto

  2. Pingback: ID ปะทะ Class จะเลือกใช้อะไรดี? « margin0auto

  3. จากที่ผมอ่านเรื่อง Specificity กับ Cascade มา ถ้าจะบอกว่า Specificity มี priority สูงกว่า Cascade จะถูกต้องรึเปล่าครับ?

    แล้วจากตัวอย่างสุดท้ายเรื่อง Specificity
    h4 {
    margin-left: 10px;
    }

    body h4 {
    margin: 20px 0 40px 5px !important;
    }

    ตัวไหนจะเป็นตัวที่ browser เลือกครับ? :D

    • จากการตรวจสอบอีกครั้งพบว่าผมมีความเข้าใจในส่วนนี้ผิดพลาดเอง ต้องขออภัยมา ณ ที่นี้ด้วยครับ จึงขอแก้ไขให้ถูกต้องดังนี้คือ

      คำสั่ง margin เป็นแค่คำสั่งลัด (Shortcut) ของ margin-top, margin-right, margin-bottom และ margin-left เท่านั้น ไม่ได้มีความแตกต่างในด้านความเฉพาะเจาะจงอย่างที่กล่าวในบทความแต่อย่างใด ทุกอย่างยังเป็นไปตามหลักการ Cascade และ Specificity ดังนี้คือ หากเราเขียน css สั่งแท็ก h4 ตามนี้เช่น

      h4 {
      margin-left: 100px;
      }

      h4 {
      margin: 20px 0 40px 5px;
      }

      บราวเซอร์ก็จะแสดงข้อความในแท็ก h4 ให้มีค่า margin ด้านซ้ายเป็น 5px ตามหลักการ Cascade แต่หากเราปรับการเขียนใหม่เป็นแบบนี้

      body h4 {
      margin-left: 100px;
      }

      h4 {
      margin: 20px 0 40px 5px;
      }

      บราวเซอร์ก็จะแสดงข้อความในแท็ก h4 ให้มีค่า margin ด้านซ้าอยเป็น 100px ตามหลักการ Specificity ครับ และหากเราปรับการเขียนใหม่โดยเพิ่ม !important เข้าไปอย่างนี้

      body h4 {
      margin-left: 100px;
      }

      h4 {
      margin: 20px 0 40px 5px !important;
      }

      บราวเซอร์ก็จะแสดงข้อความในแท็ก h4 ให้มีค่า margin ด้านซ้ายเป็น 5px ตามเดิมครับ ขออภัยในความผิดพลาดนี้อีกครั้งหนึ่งครับ Y_Y

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Connecting to %s