The CSS Podcast - 015: Pseudo-classes
สมมติว่าคุณมีแบบฟอร์มลงชื่อสมัครรับอีเมล
และต้องการให้ช่องแบบฟอร์มอีเมลมีเส้นขอบสีแดงหากมีอีเมลที่ไม่ถูกต้อง
คุณจะทำได้อย่างไร
คุณสามารถใช้:invalid
คลาสสมมติ CSS
ซึ่งเป็นหนึ่งในคลาสสมมติหลายรายการที่เบราว์เซอร์มีให้
คลาสจำลองช่วยให้คุณใช้สไตล์ตามการเปลี่ยนแปลงสถานะและปัจจัยภายนอกได้ ซึ่งหมายความว่าดีไซน์ของคุณสามารถตอบสนองต่อข้อมูลที่ผู้ใช้ป้อน เช่น อีเมลที่ไม่ถูกต้อง ซึ่งจะกล่าวถึงในโมดูลตัวเลือก และโมดูลนี้จะอธิบายรายละเอียดเพิ่มเติมให้คุณ
คลาสเสมือนจะเชื่อมต่อกับสถานะที่เฉพาะเจาะจงซึ่งองค์ประกอบอาจมี แทนที่จะจัดรูปแบบส่วนต่างๆ ขององค์ประกอบนั้นโดยทั่วไป ซึ่งแตกต่างจากองค์ประกอบเสมือน ซึ่งคุณดูข้อมูลเพิ่มเติมได้ในโมดูลก่อนหน้า
สถานะแบบอินเทอร์แอกทีฟ
Pseudo-class ต่อไปนี้จะมีผลเนื่องจากการโต้ตอบที่ผู้ใช้มีกับหน้าเว็บ
:hover
หากผู้ใช้มีอุปกรณ์ชี้ เช่น เมาส์หรือแทร็กแพด
และวางอุปกรณ์ไว้เหนือองค์ประกอบ
คุณสามารถเชื่อมต่อกับสถานะนั้นด้วย
:hover
เพื่อใช้รูปแบบ
ซึ่งเป็นวิธีที่มีประโยชน์ในการบอกเป็นนัยว่าโต้ตอบกับองค์ประกอบได้
:active
สถานะนี้จะทริกเกอร์เมื่อมีการโต้ตอบกับองค์ประกอบอยู่ เช่น การคลิก ก่อนที่จะปล่อยการคลิก หากใช้อุปกรณ์ชี้ เช่น เมาส์ สถานะนี้คือเมื่อการคลิกเริ่มต้นและยังไม่ได้ปล่อย
:focus
, :focus-within
และ :focus-visible
หากองค์ประกอบรับโฟกัสได้ เช่น <button>
คุณจะโต้ตอบกับสถานะนั้นได้ด้วย
คลาสเสมือน :focus
นอกจากนี้ คุณยังโต้ตอบได้หากองค์ประกอบย่อยขององค์ประกอบได้รับโฟกัสด้วย
:focus-within
องค์ประกอบที่โฟกัสได้ เช่น ปุ่ม จะแสดงวงแหวนโฟกัสเมื่ออยู่ในโฟกัส แม้ว่าจะคลิกแล้วก็ตาม ในสถานการณ์เช่นนี้ นักพัฒนาแอปจะใช้ CSS ต่อไปนี้
button:focus {
outline: none;
}
CSS นี้จะนำวงแหวนโฟกัสของเบราว์เซอร์เริ่มต้นออกเมื่อองค์ประกอบได้รับโฟกัส
ซึ่งทำให้เกิดปัญหาด้านการช่วยเหลือพิเศษสำหรับผู้ใช้ที่ไปยังส่วนต่างๆ ของหน้าเว็บด้วยแป้นพิมพ์
หากไม่มีรูปแบบโฟกัส
ผู้ใช้จะติดตามตำแหน่งที่โฟกัสอยู่ไม่ได้เมื่อใช้ปุ่ม Tab
ด้วย :focus-visible
คุณสามารถนำเสนอรูปแบบโฟกัสเมื่อองค์ประกอบได้รับโฟกัสโดยใช้แป้นพิมพ์
ในขณะที่ใช้กฎ outline: none
เพื่อป้องกันไม่ให้เกิดขึ้นเมื่ออุปกรณ์พอยน์เตอร์โต้ตอบกับองค์ประกอบ
button:focus {
outline: none;
}
button:focus-visible {
outline: 1px solid black;
}
:target
คลาสเทียม :target
จะเลือกองค์ประกอบที่มี id
ที่ตรงกับส่วนย่อยของ URL
สมมติว่าคุณมี HTML ดังนี้
<article id="content">
<!-- ... -->
</article>
คุณแนบสไตล์กับองค์ประกอบนั้นได้เมื่อ URL มี #content
#content:target {
background: yellow;
}
ซึ่งมีประโยชน์ในการไฮไลต์พื้นที่ที่อาจมีการลิงก์ถึงโดยเฉพาะ เช่น เนื้อหาหลักในเว็บไซต์ โดยใช้ลิงก์ข้าม
สถานะประวัติ
:link
คุณใช้:link
คลาสเสมือนกับองค์ประกอบ <a>
ใดก็ได้ที่มีค่า href
ซึ่งยังไม่ได้เข้าชม
:visited
คุณจัดรูปแบบลิงก์ที่ผู้ใช้เข้าชมแล้วได้โดยใช้คลาสเสมือน
:visited
ซึ่งเป็นสถานะตรงข้ามกับ :link
แต่คุณจะมีพร็อพเพอร์ตี้ CSS ให้ใช้น้อยกว่าด้วยเหตุผลด้านความปลอดภัย
คุณจัดรูปแบบได้เฉพาะ color
, background-color
,
border-color
, outline-color
และสีของ SVG fill
และ stroke
ลำดับมีความสำคัญ
หากคุณกำหนด:visited
สไตล์
คลาสหลอกของลิงก์จะลบล้างสไตล์ดังกล่าวได้โดยมีความเฉพาะเจาะจงอย่างน้อยเท่ากัน
ด้วยเหตุนี้ เราจึงขอแนะนำให้คุณใช้กฎ LVHA ในการจัดรูปแบบลิงก์ด้วยคลาสเสมือนตามลำดับต่อไปนี้
:link
, :visited
, :hover
, :active
a:link {}
a:visited {}
a:hover {}
a:active {}
สถานะของแบบฟอร์ม
Pseudo-class ต่อไปนี้สามารถเลือกองค์ประกอบของแบบฟอร์ม ในสถานะต่างๆ ที่องค์ประกอบเหล่านี้อาจอยู่ในระหว่างการโต้ตอบกับองค์ประกอบเหล่านั้น
:disabled
และ :enabled
หากเบราว์เซอร์ปิดใช้องค์ประกอบของแบบฟอร์ม
เช่น <button>
คุณสามารถเชื่อมต่อกับสถานะนั้นได้ด้วย
คลาสเสมือน :disabled
:enabled
คลาสเสมือนพร้อมใช้งานสำหรับสถานะตรงข้าม
แม้ว่าองค์ประกอบของแบบฟอร์มจะ:enabled
โดยค่าเริ่มต้น
คุณจึงอาจไม่จำเป็นต้องใช้คลาสเสมือนนี้
:checked
และ :indeterminate
:checked
คลาสเทียมจะพร้อมใช้งานเมื่อองค์ประกอบแบบฟอร์มที่รองรับ
เช่น ช่องทำเครื่องหมายหรือปุ่มตัวเลือกอยู่ในสถานะที่เลือก
:checked
สถานะเป็นสถานะไบนารี (จริงหรือเท็จ)
แต่ช่องทำเครื่องหมายมีสถานะกลางเมื่อไม่ได้เลือกหรือยกเลิกการเลือก
ซึ่งเรียกว่าสถานะ
:indeterminate
ตัวอย่างของสถานะนี้คือเมื่อคุณมีตัวควบคุม "เลือกทั้งหมด" ที่เลือกช่องทําเครื่องหมายทั้งหมดในกลุ่ม หากผู้ใช้ยกเลิกการเลือกช่องทำเครื่องหมายใดช่องหนึ่ง ช่องทำเครื่องหมายรูทจะไม่แสดง "ทั้งหมด" ที่เลือกอีกต่อไป จึงควรเปลี่ยนเป็นสถานะไม่แน่นอน
องค์ประกอบ <progress>
ยังมีสถานะไม่แน่นอนที่จัดรูปแบบได้ด้วย
Use Case ที่พบบ่อยคือการทำให้แถบมีลักษณะเป็นลายทางเพื่อระบุว่าไม่ทราบว่าต้องใช้เวลาอีกเท่าใด
:placeholder-shown
หากฟิลด์แบบฟอร์มมีแอตทริบิวต์ placeholder
และไม่มีค่า
คุณจะใช้คลาสเทียม :placeholder-shown
เพื่อแนบสไตล์กับสถานะนั้นได้
ทันทีที่มีเนื้อหาในฟิลด์ ไม่ว่าจะมี placeholder
หรือไม่ก็ตาม สถานะนี้จะไม่มีผลอีกต่อไป
สถานะการตรวจสอบ
คุณตอบสนองต่อการตรวจสอบความถูกต้องของแบบฟอร์ม HTML ได้ด้วย Pseudo-classes เช่น
:valid
:invalid
และ
:in-range
คลาสเสมือน :valid
และ :invalid
มีประโยชน์สำหรับบริบท
เช่น ช่องอีเมลที่มี pattern
ที่ต้องตรงกัน
เพื่อให้เป็นช่องที่ถูกต้อง
สถานะค่าที่ถูกต้องนี้จะแสดงต่อผู้ใช้
เพื่อช่วยให้ผู้ใช้ทราบว่าสามารถไปยังช่องถัดไปได้อย่างปลอดภัย
:in-range
คลาสจำลองจะพร้อมใช้งานหากอินพุตมี min
และ max
เช่น อินพุตตัวเลขและค่าอยู่ในขอบเขตเหล่านั้น
แบบฟอร์ม HTML
ช่วยให้คุณกำหนดได้ว่าต้องกรอกฟิลด์ใดด้วยแอตทริบิวต์ required
:required
คลาสเสมือนจะใช้ได้กับช่องที่ต้องกรอก
เลือกช่องที่ไม่บังคับได้ด้วยคลาสเทียม
:optional
การเลือกองค์ประกอบตามดัชนี ลำดับ และการเกิด
มีกลุ่มคลาสเสมือนที่เลือกรายการตามตำแหน่งในเอกสาร
:first-child
และ :last-child
หากต้องการค้นหารายการแรกหรือรายการสุดท้าย
คุณสามารถใช้
:first-child
และ
:last-child
คลาสจำลองเหล่านี้จะแสดงผลองค์ประกอบแรกหรือองค์ประกอบสุดท้ายในกลุ่มขององค์ประกอบร่วม
:only-child
นอกจากนี้ คุณยังเลือกองค์ประกอบที่ไม่มีองค์ประกอบระดับเดียวกันได้ด้วย
โดยใช้
:only-child
Pseudo-Class
:first-of-type
และ :last-of-type
คุณเลือก
:first-of-type
และ
:last-of-type
ได้ ซึ่งในตอนแรก
อาจดูเหมือนว่าทำหน้าที่เดียวกันกับ :first-child
และ :last-child
แต่ลองพิจารณา HTML นี้
<div class="my-parent">
<p>A paragraph</p>
<div>A div</div>
<div>Another div</div>
</div>
และ CSS นี้
.my-parent div:first-child {
color: red;
}
ไม่มีองค์ประกอบใดที่จะเป็นสีแดงเนื่องจากองค์ประกอบย่อยแรกเป็นย่อหน้า ไม่ใช่ div
คลาสเสมือน :first-of-type
มีประโยชน์ในบริบทนี้
.my-parent div:first-of-type {
color: red;
}
แม้ว่า <div>
แรกจะเป็นองค์ประกอบย่อยที่ 2 แต่ก็ยังเป็นองค์ประกอบแรกของประเภทภายในองค์ประกอบ .my-parent
ดังนั้นกฎนี้จะทำให้องค์ประกอบดังกล่าวมีสีแดง
:nth-child
และ :nth-of-type
คุณไม่จำเป็นต้องจำกัดเฉพาะลูกคนแรกและคนสุดท้าย รวมถึงประเภทของลูก
คลาสเสมือน :nth-child
และ :nth-of-type
ช่วยให้คุณระบุองค์ประกอบที่ดัชนีหนึ่งๆ ได้
การจัดทำดัชนีในตัวเลือก CSS จะเริ่มต้นที่ 1
คลาสเสมือน :nth-last-child()
และ :nth-last-of-type()
จะนับจากท้ายแทนที่จะนับจากต้น
คุณยังส่งค่ามากกว่าดัชนีไปยัง Pseudo-Class เหล่านี้ได้ด้วย
หากต้องการเลือกองค์ประกอบคู่ทั้งหมด คุณสามารถใช้ :nth-child(even)
ได้
นอกจากนี้ คุณยังสร้างตัวเลือกที่ซับซ้อนมากขึ้นซึ่งค้นหารายการในช่วงเวลาที่เว้นระยะอย่างสม่ำเสมอได้ โดยใช้รูปแบบย่อย An+B
li:nth-child(3n+3) {
background: yellow;
}
ตัวเลือกนี้จะเลือกทุกๆ รายการที่ 3
โดยเริ่มจากรายการที่ 3
n
ในนิพจน์นี้คือดัชนี
ซึ่งเริ่มต้นที่ 0 และ 3 (3n
) คือจำนวนที่คุณคูณดัชนีนั้น
สมมติว่าคุณมีไอเทม <li>
จำนวน 7 รายการ
รายการแรกที่เลือกคือ 3 เนื่องจาก 3n+3
แปลงเป็น (3 * 0) + 3
การวนซ้ำครั้งถัดไปจะเลือกรายการที่ 6 เนื่องจากตอนนี้ n
เพิ่มขึ้นเป็น 1
จึงเป็น (3 * 1) + 3)
นิพจน์นี้ใช้ได้กับทั้ง :nth-child
และ :nth-of-type
:nth-child()
และ :nth-last-child()
ยังรองรับไวยากรณ์ "of S" ที่ช่วยให้คุณกรองการจับคู่ด้วยตัวเลือกได้เช่นเดียวกับ :nth-of-type()
li:nth-of-type(even)
มีค่าเท่ากับ :nth-child(even of li)
แม้ว่า :nth-of-type
จะอนุญาตให้คุณกรองตามประเภทองค์ประกอบเท่านั้น (เช่น li
หรือ p
) แต่ไวยากรณ์ "of S" จะอนุญาตให้คุณกรองในตัวเลือกใดก็ได้
หากมีตาราง คุณอาจต้องการเพิ่มแถบในทุกๆ แถว แม้ว่าคุณจะกำหนดเป้าหมายทุกๆ แถวด้วยtr:nth-child(even)
ได้ แต่จะใช้ไม่ได้หากคุณกรองบางแถวออก หากใช้การกรองโดยใช้แอตทริบิวต์ hidden
คุณจะเพิ่ม of :not([hidden])
ลงในตัวเลือกเพื่อกรองรายการที่ซ่อนไว้ล่วงหน้าก่อนที่จะเลือกแถวคู่ได้
tr:nth-child(even of :not([hidden])){
background: lightgrey;
}
คุณลองใช้ตัวเลือกประเภทนี้ได้ในเครื่องมือทดสอบ nth-child หรือเครื่องมือเลือกจำนวน
:only-of-type
สุดท้ายนี้ คุณสามารถค้นหาองค์ประกอบเดียวของประเภทหนึ่งๆ ในกลุ่มองค์ประกอบที่อยู่ระดับเดียวกันได้ด้วย
:only-of-type
ซึ่งจะมีประโยชน์หากคุณต้องการเลือกรายการที่มีเพียง 1 รายการ
หรือหากต้องการค้นหาองค์ประกอบตัวหนาเพียงรายการเดียวในย่อหน้า
ค้นหาองค์ประกอบที่ว่างเปล่า
บางครั้งการระบุองค์ประกอบที่ว่างเปล่าโดยสมบูรณ์ก็มีประโยชน์ และมี Pseudo-Class สำหรับการดำเนินการดังกล่าวด้วย
:empty
หากองค์ประกอบไม่มีองค์ประกอบย่อย ระบบจะใช้เพชรโดคลาส :empty
กับองค์ประกอบนั้น
อย่างไรก็ตาม องค์ประกอบย่อยไม่ได้เป็นเพียงองค์ประกอบ HTML หรือโหนดข้อความเท่านั้น แต่ยังเป็นช่องว่างได้ด้วย
ซึ่งอาจทำให้สับสนเมื่อคุณกำลังแก้ไขข้อบกพร่องของ HTML ต่อไปนี้และสงสัยว่าเหตุใดจึงใช้กับ :empty
ไม่ได้
<div>
</div>
เนื่องจากมีช่องว่างระหว่างแท็กเปิดและแท็กปิด <div>
:empty
จึงใช้งานไม่ได้
:empty
คลาสเสมือนอาจมีประโยชน์หากคุณควบคุม HTML ได้น้อยและต้องการซ่อนองค์ประกอบที่ว่างเปล่า
เช่น เครื่องมือแก้ไขเนื้อหาแบบ WYSIWYG
ในที่นี้ ผู้แก้ไขได้เพิ่มย่อหน้าที่ว่างเปล่า
<article class="post">
<p>Donec ullamcorper nulla non metus auctor fringilla.</p>
<p></p>
<p>Curabitur blandit tempus porttitor.</p>
</article>
:empty
ช่วยให้คุณค้นหาและซ่อนข้อมูลดังกล่าวได้
.post :empty {
display: none;
}
การค้นหาและยกเว้นหลายองค์ประกอบ
คลาสเสมือนบางคลาสช่วยให้คุณเขียน CSS ได้กะทัดรัดยิ่งขึ้น
:is()
หากต้องการค้นหาองค์ประกอบย่อย h2
, li
และ img
ทั้งหมดในองค์ประกอบ .post
คุณอาจคิดที่จะเขียนรายการตัวเลือกดังนี้
.post h2,
.post li,
.post img {
…
}
คุณสามารถเขียนเวอร์ชันที่กระชับกว่าได้ด้วย:is()
คลาสหลอก
.post :is(h2, li, img) {
/* ... */
}
คลาสเสมือน :is
ไม่เพียงกะทัดรัดกว่ารายการตัวเลือก แต่ยังมีความยืดหยุ่นมากกว่าด้วย
ในกรณีส่วนใหญ่
หากมีข้อผิดพลาดหรือตัวเลือกที่ไม่รองรับในรายการตัวเลือก
รายการตัวเลือกทั้งหมดจะใช้งานไม่ได้อีกต่อไป
หากมีข้อผิดพลาดในตัวเลือกที่ส่งผ่านในคลาสเทียม :is
ระบบจะละเว้นตัวเลือกที่ไม่ถูกต้อง แต่จะใช้ตัวเลือกที่ถูกต้อง
:not()
นอกจากนี้ คุณยังยกเว้นรายการด้วยคลาสเทียม :not()
ได้ด้วย
เช่น คุณสามารถใช้เพื่อจัดรูปแบบลิงก์ทั้งหมดที่ไม่มีแอตทริบิวต์ class
a:not([class]) {
color: blue;
}
:not
คลาสจำลองยังช่วยปรับปรุงการช่วยเหลือพิเศษได้ด้วย
เช่น <img>
ต้องมี alt
แม้ว่าจะเป็นค่าว่างก็ตาม
เพื่อให้คุณเขียนกฎ CSS ที่เพิ่มเส้นขอบสีแดงหนาให้กับรูปภาพที่ไม่ถูกต้องได้
img:not([alt]) {
outline: 10px red;
}
:has()
จะเกิดอะไรขึ้นหากคุณต้องการจัดรูปแบบองค์ประกอบตามสิ่งที่อยู่ภายในองค์ประกอบนั้น คุณใช้:has()
คลาสจำลองเพื่อทำสิ่งนั้นได้ เช่น คุณอาจต้องการใช้สไตล์กับปุ่มที่มีไอคอน
button:has(svg) {
/* ... */
}
ในการกำหนดค่าพื้นฐานที่สุด เช่น ในตัวอย่างก่อนหน้า คุณสามารถคิดว่า :has()
เป็นตัวเลือกหลัก นอกจากนี้ คุณยังใช้ตัวเลือกองค์ประกอบหลักที่ตรงกันร่วมกับตัวเลือกอื่นๆ เพื่อกำหนดเป้าหมายองค์ประกอบอื่นๆ ได้ด้วย
form:has(input:valid) label {
font-weight: bold;
}
form:has(input:valid) label::after {
content: "✅";
}
ในตัวอย่างนี้ เราจะใช้สไตล์กับองค์ประกอบป้ายกำกับและองค์ประกอบเสมือน label::after
เมื่ออินพุตของแบบฟอร์มมีคลาสเสมือน valid
:has()
คลาสเสมือน:has()
จะซ้อนอยู่ภายใน:has()
คลาสเสมือน:has()
อื่นไม่ได้ แต่ใช้ร่วมกับคลาสเสมือนอื่นๆ ได้
:is(h1, h2, h3):has(a) {
/* ... */
}
รายการตัวเลือกไม่ยอมให้มีข้อผิดพลาด ดังนั้นหากตัวเลือกใดในรายการไม่ถูกต้อง ระบบจะละเว้นกฎสไตล์ทั้งหมด
.my-element:has(img, ::before) {
/* any styles here will be discarded since pseudo elements can't be included in the :has() selector list */
}
ทดสอบความเข้าใจ
ทดสอบความรู้เกี่ยวกับคลาสเสมือน
คลาสเสมือนจะทำหน้าที่ราวกับว่ามีการใช้คลาสกับองค์ประกอบแบบไดนามิก ในขณะที่องค์ประกอบเสมือนจะทำหน้าที่กับองค์ประกอบนั้นๆ เอง
:
แบบเดี่ยวหรือคู่เป็นอักขระสำคัญที่ใช้แยกความแตกต่างในตัวเลือกข้อใดต่อไปนี้เป็นคลาสเสมือนฟังก์ชัน
:is()
:target
()
ต่อท้ายเพื่อระบุว่ายอมรับพารามิเตอร์:empty
()
ต่อท้ายเพื่อระบุว่ายอมรับพารามิเตอร์:not()
Pseudo-class ใดต่อไปนี้เกิดจากการโต้ตอบของผู้ใช้
:hover
:press
:squeeze
:target
:focus-within
<form>
ใดต่อไปนี้คือคลาสเทียมของสถานะ
:enabled
:fresh
:indeterminate
:checked
:in-range
:loading
:valid