Fundamentals
Cascade & Inheritance
แยกแยะสองกลไกที่สับสนกันบ่อย — cascade ที่ตัดสินว่า rule ไหนชนะเมื่อหลาย rule ตรงกัน กับ inheritance ที่ส่งค่าจาก parent สู่ child อัตโนมัติ
1) ปัญหา: เขียนแล้วสีไม่ออก กับ ไม่ได้เขียนแต่สีมาเอง
เวลาขึ้นต้นเขียน CSS คุณจะเจอสองอาการที่ดูเหมือนขัดกัน: 1. **เขียน rule ไปแล้วแต่ style ไม่ออก** — element ยังเป็นสีเดิม ทั้งที่เพิ่ม rule ใหม่ลงไปแล้ว 2. **ไม่ได้เขียน rule ให้ element นั้นเลยแต่ style มาเอง** — ย่อหน้าในกล่องกลายเป็นสีเดียวกับกล่อง โดยที่คุณไม่เคยกำหนดสีให้ย่อหน้า สองอาการนี้มาจากกลไกคนละตัว: อาการแรกคือ **cascade** กำลังตัดสินว่า rule ไหนชนะ ส่วนอาการที่สองคือ **inheritance** กำลังส่งค่าจาก parent ลงสู่ child ลองเล่นตัวอย่างด้านล่างก่อน แล้วทายผลไว้: **ทายก่อนเปิด preview:** h3 และ p ที่อยู่ใน .parent-demo จะแสดงสีอะไร ทั้งที่ไม่มี CSS กำหนดให้พวกมันโดยตรง? แล้ว p.cascade-demo ซึ่งโดนทั้ง rule p และ rule .cascade-demo จะเป็นสีอะไร?
- เพิ่ม rule ใหม่แล้วไม่ทำงาน — เพราะมี rule อื่นที่ match element เดียวกันและมีน้ำหนักชนะอยู่
- ลบ rule ออกแล้ว element เปลี่ยนสีทันที — เพราะ cascade มี rule อื่นรอแทนอยู่แล้ว
- ไม่ได้กำหนด style ให้ element ลูก แต่ลูกเปลี่ยนตาม parent — inheritance ทำงานเบื้องหลัง
- สับสนว่าปัญหาที่เจอเป็น "กฎชนกัน" หรือ "ค่าส่งต่ออัตโนมัติ" — บทนี้จะแยกให้ชัด
2) แนวคิดหลัก: cascade ตอบ "กฎไหนชนะ" — inheritance ตอบ "ค่าไหนส่งต่อ"
กลไกทั้งสองทำงานคนละชั้นของกระบวนการ: **Cascade (แคสเคด)** คือกระบวนการที่เบราว์เซอร์ใช้ตัดสินว่า เมื่อมีหลาย rule match กับ element เดียวกัน rule ไหนมีผลจริง — คุณเรียนตัวชี้ขาดตัวหนึ่งมาแล้ว นั่นคือ specificity ของ selector แต่ cascade ยังมีเงื่อนไขอีกสองขั้นเรียงตามลำดับ **Inheritance (การสืบทอด)** คือกลไกที่ element ลูกได้รับค่าของ property บางอย่างจาก element พ่อแม่โดยอัตโนมัติ เมื่อไม่มี rule ใดกำหนด property นั้นให้ลูกโดยตรง — คุณไม่ต้องเขียนซ้ำทุก element จำกรอบสองประโยคนี้ไว้: — Cascade ตอบว่า "กฎไหนชนะ?" — Inheritance ตอบว่า "ค่าไหนส่งต่อได้?"
3) กลไกของ cascade: importance → specificity → source order
สำหรับ element หนึ่ง ๆ เบราว์เซอร์รวบรวม rule ทุกตัวที่ selector match กับมัน แล้วคัดผู้ชนะเป็นสามขั้น เรียงตามลำดับ:
- **Importance** — rule ที่มี !important อยู่ชั้นบนสุด ข้ามการเทียบน้ำหนักทั้งหมด (เรียนรายละเอียดในบท specificity แล้ว — ที่นี่แค่จัดตำแหน่งในลำดับ)
- **Specificity** — ในกลุ่มที่เหลือ selector ที่เจาะจงกว่าชนะ โดยเทียบ (a, b, c, d) จากซ้ายไปขวา
- **Source order** — ถ้าเทียบกันทุกหลักแล้วเสมอกัน rule ที่ประกาศทีหลังในไฟล์ CSS ชนะ
**ทายก่อนดูโค้ด:** ถ้า element เดียวกันถูก `.alert { color: orange; }` และ `.warning { color: blue; }` ครอบพร้อมกัน และสอง rule นี้ specificity เท่ากัน (0,0,1,0) เท่ากัน ใครเขียนทีหลังใครชนะ?
specificity เท่ากันเมื่อไร source order จึงเป็นตัวตัดสิน — ไล่ตรวจจากขั้นบนลงล่างเสมอ
4) กลไกของ inheritance: property ที่ส่งต่อได้ กับที่ต้องกำหนดเอง
ไม่ใช่ทุก property จะส่งต่อจาก parent สู่ child — CSS แบ่งไว้ตายตัวว่า property ไหน inherit ได้ และ property ไหนไม่ inherit: — ถ้า property นั้น **inherit ได้** และ element ลูกไม่มี rule กำหนดโดยตรง ลูกจะใช้ค่าเดียวกับ parent ที่ใกล้ที่สุด — ถ้า property นั้น **inherit ไม่ได้** element ลูกจะใช้ค่าเริ่มต้นของตัวเองเสมอ (เช่น padding ของทุก element เริ่มต้นที่ 0)
| กลุ่ม property | ตัวอย่าง | inherit หรือไม่ |
|---|---|---|
| สีและตัวอักษร | color, font-family, font-size, font-weight, line-height | inherit ได้ |
| การจัดข้อความ | text-align, letter-spacing | inherit ได้ |
| กล่องและระยะห่าง | margin, padding, width, height | ไม่ inherit |
| กรอบและพื้นหลัง | border, background, border-radius | ไม่ inherit |
เขียนครั้งเดียวที่ .card — สีและฟอนต์ไหลลงสู่ลูกทุกชั้น แต่กรอบกับระยะต้องกำหนดเองที่ element เป้าหมาย (หมายเหตุ: border และ padding เป็นกลุ่ม Box Model ที่ไม่ inherit ซึ่งจะได้เรียนเต็มในบทที่ 11–12; ส่วน font-family จะได้เรียนเต็มในบทที่ 19 — ที่นี่นำมาเปรียบเทียบเพื่อให้เห็นพฤติกรรมการสืบทอดชัดเจน)
5) ทำงานร่วมกัน: rule ตรงชนะค่า inherit เสมอ
คำถามที่พบบ่อยคือ: "ตั้งสีไว้ที่ div แล้วทำไม p ข้างในไม่เป็นสีนั้น" — เพราะ p มี rule ตรงของตัวเอง (เช่น p { color: gray; }) ค่าที่จะ inherit จาก div เป็นเพียง**ตัวสำรอง**ที่ใช้เมื่อ p ไม่มี rule ตรงเท่านั้น rule ตรงจะชนะเสมอ ไม่ว่า parent จะตั้งค่าอะไรไว้ก็ตาม เวลาสีไม่ออก ให้ไล่สองคำถามนี้: 1. element นี้มี rule ตรง match อยู่ไหม — ถ้ามี ให้ดู cascade: importance → specificity → source order 2. ถ้าไม่มี rule ตรง — property นี้ inherit ได้ไหม ถ้าได้ ให้ดู parent ที่ใกล้ที่สุด ถ้าไม่ได้ ให้ดูค่าเริ่มต้นของ property
ทำให้ p ใน .content เป็นสีน้ำเงิน — แก้ที่ parent หรือที่ p?
ฝั่งซ้ายพยายามบังคับด้วย !important ที่ .content แต่ไม่เกิดผล — เพราะ !important เปลี่ยนเฉพาะค่าของ element ที่ rule นั้น match (.content ตัวแม่) ค่าที่ p ได้จาก inheritance แพ้ rule ตรงของ p เสมอ ฝั่งขวาเขียน rule ตรงให้ p ด้วย class ที่มี specificity ชนะ p
p ยังเป็นสีเทา — !important ทำงานใน cascade ของ .content เอง ไม่ได้ทำให้ค่าที่ inherit ไปแรงขึ้น
.message (0,0,1,0) ชนะ p (0,0,0,1) — p ที่มี class="message" ใน HTML จึงเป็นสีน้ำเงินโดยไม่ต้องพึ่ง inherit
Lab 1 — ทำตาม: ให้ parent เป็นคนกำหนดสีและฟอนต์
ตามตัวอย่างในหัวข้อที่ผ่านมา ให้เขียน color และ font-family ไว้ที่ .article เพียงที่เดียว — h2 และ p ที่อยู่ข้างในจะรับค่ามาเองผ่าน inheritance โดยไม่ต้องมี rule กำหนดให้โดยตรง
Lab 2 — แก้: ย้าย border และ padding ไปไว้ที่ข้อความ
สเปกบอกว่า p.card-text สองบรรทัดต้องมีกรอบเส้นประและระยะรอบข้อความของตัวเอง แต่ starter เขียน border กับ padding ไว้ที่ .card — ผลคือกรอบใหญ่ล้อมทั้งการ์ด ไม่ใช่กรอบเล็ก ๆ รอบข้อความ เพราะ border กับ padding เป็น property ที่ไม่ inherit จึงไม่มีทางส่งต่อให้ p ได้ ต้องย้ายไปประกาศที่ .card-text
Lab 3 — แก้โจทย์: ชนะ rule ของ p ด้วย specificity โดยไม่แตะของเดิม
p.message เป็นสีเทา ทั้งที่ .content ตั้งสีน้ำเงินไว้ — เพราะ p.message ถูก rule p { } กำหนดสีตรง ค่าที่จะ inherit จาก .content จึงแพ้ rule ตรงเสมอ วิธีแก้คือเพิ่ม rule ตรงให้ p.message ด้วย class selector ที่ specificity ชนะ p
ตรวจความเข้าใจและก้าวต่อไป
ตอบคำถามสั้น ๆ เพื่อเช็กว่าคุณแยก cascade ออกจาก inheritance และไล่ที่มาของ style ที่ไม่ตรงกับที่คาดได้หรือยัง ก่อนไปเรียนเรื่องหน่วยวัดในบทถัดไป
ตรวจความเข้าใจ: Cascade & Inheritance
HTML มี <div class="card"> ที่กำหนด color: #1e40af และภายในมี <p> ที่ไม่มี rule กำหนดสีโดยตรง — <p> นี้จะแสดงสีอะไร?
cascade ตัดสินผู้ชนะระหว่าง rule ที่ match element เดียวกัน ด้วยขั้นตอนใด?
ข้อใดเป็นจริงเกี่ยวกับ cascade และ inheritance (เลือกทุกข้อที่ถูก)
element ลูกที่ไม่มี rule ตรง จะรับค่าของ property ที่ inherit ได้จาก ____ ที่ใกล้ที่สุด — เติมคำศัพท์ภาษาอังกฤษที่เรียนในบทนี้
- Cascade = กฎไหนชนะ — importance → specificity → source order
- Inheritance = ค่าไหนส่งต่อ — เฉพาะ inherited property เช่น color และ font-family
- border, padding, margin, width, height ไม่ inherit — ต้องกำหนดเองที่ element เป้าหมาย
- rule ตรงชนะค่า inherit เสมอ — ไล่สีที่ไม่ออกด้วยคำถาม "มี rule ตรงไหม" ก่อน
- ก้าวต่อไป: ในบทถัดไป 'CSS Units (px, %, em, rem, vw, vh...)' เราจะเรียนการเลือกหน่วยวัด — ค่าตายตัวอย่าง px กับค่าสัมพัทธ์อย่าง rem, em และ % ที่ขยับตาม context (สมมติฐานความรู้ก่อนหน้า: แยก cascade ออกจาก inheritance และเข้าใจว่า rule ตรงชนะค่า inherit เสมอจากบทนี้ — เพราะค่าที่เป็น % หรือ em จะถูกคำนวณเทียบกับค่า font-size หรือขนาด parent ซึ่งต้องรู้ก่อนว่าค่าที่ element ได้รับมาเป็นอย่างไร)