คุณคิดว่าคุณได้เรียนพื้นฐานเรื่อง id, class และ descendant selector แล้วคิดว่าพอ? ถ้าคำตอบนั้นคือใช่ นั่นแปลว่าคุณพลาดในเรื่องความยืดหยุ่นจำนวนมากที่คุณจะได้ใช้แล้ว ขณะที่ selector จำนวนมากในบทความนี้อยู่ใน CSS3 specification และใช้ได้เฉพาะบราวเซอร์รุ่นใหม่ล่าสุดเท่านั้น บางทีคุณอาจจะต้องบอกกับตัวคุณเองทีหลังว่า คุณน่าจะจำมันได้ตั้งนานแล้ว Show
1. ** { margin: 0; padding: 0; } เริ่มง่ายๆ ตัวแรกเลยสำหรับมือใหม่ ก่อนที่คุณจะเจอ selector ขั้นสูงกว่านี้ต่อ สัญลักษณ์ดอกจันทร์ (*) นั้น select ทุกๆ element บน page นักพัฒนาจำนวนมากจะใช้เทคนิคนี้ในการ Set ค่า
#container * { border: 1px solid black; } ตัวอย่างนี้จะ select ทุกๆ element ที่เป็นลูกของ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
2. #X#container { width: 960px; margin: auto; } ใส่เครื่องหมายสี่เหลี่ยม (#) ไว้ด้านหน้านั้นแปลว่าให้เรา select โดยใช้
แสดงตัวอย่าง บราวเซอร์ที่รองรับ
3. .X.error { color: red; } นี่คือ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
4. X Yli a { text-decoration: none; } ถัดไปคือ selector ที่ต้องช่วยใส่ใจกันให้มากๆ มันชื่อ
แสดงตัวอย่าง บราวเซอร์ที่รองรับ
5. Xa { color: red; } ul { margin-left: 0; } แล้วถ้าคุณต้องการระบุทุกๆ element
บน page โดยใช้ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
6. X:visited and X:linka:link { color: red; } a:visted { color: purple; } เราใช้ นอกจากนี้ เราใช้ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
7. X + Yul + p { color: red; } นี่เรียกว่า
adjacent selector มันจะระบุเฉพาะ element ที่อยู่ชิดถัดจาก element ต้นทาง (อยู่ชิดติดกันจริงๆ) ในกรณีนี้ เฉพาะ paragraph แรกที่อยู่ชิดต่อหลังจาก แสดงตัวอย่าง บราวเซอร์ที่รองรับ
8. X > Ydiv#container > ul { border: 1px solid black; } ความแตกต่างระหว่าง
<div id="container"> <ul> <li> List Item <ul> <li> Child </li> </ul> </li> <li> List Item </li> <li> List Item </li> <li> List Item </li> </ul> </div> selector ด้วยเหตุนี้ จะก่อให้ส่งผลให้โค้ดทำงานได้มีประสิทธิภาพมากขึ้นในการใช้ child combinator อันนี้ ในความเป็นจริง มันเหมาะอย่างยิ่งในกรณีที่คุณทำงานกับ CSS engine ที่อยู่ในภาษา JavaScript แสดงตัวอย่าง บราวเซอร์ที่รองรับ
9. X ~ Yul ~ p { color: red; } นี่คือ sibling combinator ที่ดูคล้ายกับ X + Y อย่างไรก็ตามมันจะยืดหยุ่นกว่า ขณะที่ adjacent selector ( แสดงตัวอย่าง บราวเซอร์ที่รองรับ
10. X[title]a[title] { color: green; } อันนี้เรียกว่า attribute selector ในตัวอย่างด้านบน มันจะเลือกเฉพาะ
tag a ที่มีแอตทริบิวต์ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
11. X[href="foo"]a[href="https://net.tutsplus.com"] { color: #1f6053; /* nettuts green */ } โค้ดด้านบนนั้นจะ style ทุกๆ tag a ที่ link ไปที่ https://net.tutsplus.com มันจะทำให้ลิ้งค์นั้นมีสีเขียวเข้ม tag a อื่นๆ นั้นจะไม่ได้รับผลกระทบ
มันทำงานได้ดี แม้ว่า ค่อนข้างตรงไปหน่อย ถ้าลิ้งที่โดยตรงไปยัง Nettuts+ แต่เขียน path ในรูปแบบ nettuts.com แทนที่จะเป็น url แบบเต็มหล่ะ ถ้าเป็นแบบนั้น เราสามารถใช้ syntax ของ regular expression แทนได้ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
12. X[href*="nettuts"]a[href*="tuts"] { color: #1f6053; /* nettuts green */ } นั่นแหละ ที่เราต้องการ เครื่องหมายดอกจันทร์ระบุว่า ค่านั้นจะ ปรากฏที่ไหน ก็ได้ใน attribute โดยวิธีนี้เอง ทำให้การระบุครอบคลุมถึง nettuts.com net.tutsplus.com และก็ tutsplus.com จำไว้ว่าการใช้แบบนี้ค่อนข้างกว้าง ถ้า tag a นั้น link ไป site ที่ไม่ใช่ Envato ถึงแม้มี tuts นั้นอยู่ใน url หล่ะ มันก็โดนเลือกด้วย ฉะนั้นเมื่อคุณต้องการระบุให้ชัดเจนเข้าไปอีก ก็ให้ใช้ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
13. X[href^="http"]a[href^="http"] { background: url(path/to/external/icon.png) no-repeat; padding-left: 10px; } เคยแปลกใจไหมว่าบางเว็บไซต์นั้นสามารถแสดง icon เล็กๆ ถัดจาก link ที่ออกไปยังเว็บไซต์ภายนอก ผมมั่นใจว่าคุณต้องเคยเห็นมาก่อน มันเป็นตัวแจ้งเตือนที่ดีที่บอกว่า คุณจะออกไปเว็บอื่นแล้วนะ สัญลักษณ์ ^
อันนี้ มันถูกใช้โดยทั่วไปใน regular expression เพื่อบ่งบอกจุดเริ่มต้นของ string ถ้าเราต้องการระบุ tag a ทั้งหมดที่มี
และก็ ถ้าคุณต้องการ style เจ้า tag a ทั้งหมดที่ link ไปยังรูปภาพ ในกรณีนี้ให้ใช้การค้นหาแบบ จุดสิ้นสุด ของ string แทน (ซึ่งจะกล่าวถัดไป) แสดงตัวอย่าง บราวเซอร์ที่รองรับ
14. X[href$=".jpg"]a[href$=".jpg"] { color: red; } อีกครั้ง เราใช้สัญลักษณ์จาก regular expression แสดงตัวอย่าง บราวเซอร์ที่รองรับ
15. X[data-*="foo"]a[data-filetype="image"] { color: red; } อ้างอิงกลับไปยังข้อที่สิบสี่ด้านบน แล้วถ้าเราต้องการเอาทุกๆ image type หล่ะ ( a[href$=".jpg"], a[href$=".jpeg"], a[href$=".png"], a[href$=".gif"] { color: red; } แต่นั่นมันดูแสนเหนื่อยใจและไร้ประสิทธิภาพ ความเป็นไปได้อื่นๆ เช่นการใช้ custom attribute แล้วถ้าเราเพิ่ม data-filetype attribute ของเราเองไปที่ tag a แต่ละอันที่ link ไปยังรูปภาพหล่ะ <a href="path/to/image.jpg" data-filetype="image"> Image Link </a> จากนั้น เมื่อเข้าที่เข้าทางแล้ว เราสามารถใช้ attribute selector ทั่วไปในการระบุ tag a เหล่านั้น a[data-filetype="image"] { color: red; } แสดงตัวอย่าง บราวเซอร์ที่รองรับ
16. X[foo~="bar"]a[data-info~="external"] { color: red; } a[data-info~="image"] { border: 1px solid black; } มันเป็น selector แบบพิเศษแบบหนึ่งที่จะทำให้เพื่อนคุณประทับใจ มีคนไม่กี่คนที่รู้ trick นี้ สัญลักษณ์ตัวหนอนหรือ tilda symbol ( ไปที่ custom attribute ข้อ 15 ด้านบน เราสามารถสร้าง "<a href="path/to/image.jpg" data-info="external image"> Click Me, Fool </a> ด้วยการใส่ค่าไปใน markup เราสามารถระุบ tag ใดๆ ที่มีค่าเหล่านั้น ด้วยการใช้เทคนิคจาก attribute selector อันนี้ /* Target data-info attr that contains the value "external" */ a[data-info~="external"] { color: red; } /* And which contain the value "image" */ a[data-info~="image"] { border: 1px solid black; } ง่ายใช่ไหมหล่ะ? แสดงตัวอย่าง บราวเซอร์ที่รองรับ
17. X:checkedinput[type=radio]:checked { border: 1px solid black; } pseudo class นี้เพียงแค่ระบุ element ของ user interface ที่ได้รับการเลือก (checked) เช่น radio button หรือ checkbox มันก็น่าจะเข้าใจง่ายๆ ตามนั้น... แสดงตัวอย่าง บราวเซอร์ที่รองรับ
18. X:afterpseudo class หลายคนเห็นพวกมันครั้งแรกเมื่อต้องเจอกับเทคนิคที่เรียกว่า clear-fix hack .clearfix:after { content: ""; display: block; clear: both; visibility: hidden; font-size: 0; height: 0; } .clearfix { *display: inline-block; _height: 1%; } clear-fix hack นี้ใช้ pseudo class สำหรับการใช้งานแบบสร้างสรรค์อื่นๆ โปรดดูที่ เทคนิคสั้นๆ ในการสร้างแสงเงา (quick tip on creating shadows)
บราวเซอร์ที่รองรับ
19. X:hoverdiv:hover { background: #e3e3e3; } โอ้ และก็มาถึง คุณก็รู้อันนี้
มันเป็น official term ที่เรียกว่า
คุณมักจะได้ใช้ selector ตัวนี้บ่อยๆ เช่นการทำ a:hover { border-bottom: 1px solid black; }
บราวเซอร์ที่รองรับ
20. X:not(selector)div:not(#container) { color: blue; } pseudo class แบบ หรือ ถ้าผมต้องการเลือกทุกๆ element ยกเว้น tag paragraph เราจะใช้โค้ดนี้จัดการ (ซึ่งแน่นอน ไม่แนะนำให้ใช้) *:not(p) { color: green; } แสดงตัวอย่าง บราวเซอร์ที่รองรับ
21. X::pseudoElementp::first-line { font-weight: bold; font-size: 1.2em; } เราสามารถใช้ pseudo element (ที่แสดงโดยสัญลักษณ์ ::) เพื่อ style บน element เช่นใช้กับบรรทัดแรก หรือ อักษรตัวแรก จำไว้ว่าต้องใส่ที่ block level element เท่านั้นเพื่อที่จะให้มันแสดงผล
ระบุตัวอักษรตัวแรกของ Paragraphp::first-letter { float: left; font-size: 2em; font-weight: bold; font-family: cursive; padding-right: 2px; } โค้ดด้านบนบอกว่า เราจะไปที่ทุกๆ paragraph บน page จากนั้นระบุแค่ตัวอักษรตัวแรกของ element paragraph เท่านั้น มันใช้บ่อยเหมือนกับสไตล์ของบทความในหนังสือพิมพ์ที่มักทำให้ตัวอักษรตัวแรกดูใหญ่ ระบุบรรทัดแรกของ Paragraphp::first-line { font-weight: bold; font-size: 1.2em; } คล้ายๆกัน pseudo element
แสดงตัวอย่าง บราวเซอร์ที่รองรับ
22. X:nth-child(n)li:nth-child(3) { color: red; } จำได้ไหมว่าเราไม่มีวิธีที่จะระบุ element ในกลุ่มที่เราเลือกออกมา สังเกตว่า nth-child นั้นจะรับค่า integer ที่ parameter ไม่ใช่ zero-based เช่น ถ้าคุณต้องการระบุ item อันที่สอง ก็ใช้ li:nth-child(2) ตรงๆ ไปเลย คุณยังสามารถใช้ตัวแปรเพื่อ select ได้อย่างเช่น เราใช้ li:nth-child(4n) เพื่อ select ทุกๆ list item อันที่ 4 แสดงตัวอย่าง บราวเซอร์ที่รองรับ
23. X:nth-last-child(n)li:nth-last-child(2) { color: red; } แล้วถ้าเรามี
list ขนาดใหญ่ที่มี item อยู่เป็นจำนวนมากแหละ สมมุติเราต้องการ item อันที่ 2 จากท้ายที่อยู่ใน เทคนิคนี้ใช้ได้เกือบเหมือนกับข้อ 22 ด้านบน อย่างไรก็ตามเทคนิคนี้เริ่มจากข้างหลังแทน แสดงตัวอย่าง บราวเซอร์ที่รองรับ
24. X:nth-of-type(n)ul:nth-of-type(3) { border: 1px solid black; } จะมีบางครั้งแทนที่คุณจะ select โดยใช้ จินตนาการว่า mark-up นั้นประกอบไปด้วย unordered list 5 อัน ถ้าคุณต้องการ style เพียงแค่ ul ตัวที่สาม และไม่มี id เฉพาะเกี่ยวข้องด้วย คุณควรใช้ nth-of-type(n) pseudo-class ในโค้ดด้านบน เพียงแค่ แสดงตัวอย่าง บราวเซอร์ที่รองรับ
25. X:nth-last-of-type(n)ul:nth-last-of-type(3) { border: 1px solid black; } และใช่ เพื่อให้คู่กัน เราสามารถใช้ nth-last-of-type เพื่อเริ่มด้านหลัง ไปที่ element ที่เราต้องการแทน บราวเซอร์ที่รองรับ
26. X:first-childul li:first-child { border-top: none; } pseudo class แบบนี้จะทำให้เราระบุแค่ child ตัวแรกของ element parent บ่อยครั้งคุณจะใช้มันในการเอา border ออกจาก item ตัวแรกและตัวสุดท้าย ตัวอย่าง ลองคิดว่าถ้าคุณมี list ของแถวจำนวนหนึ่ง แต่ละอันมี style นักออกแบบจำนวนมากใส่ class แสดงตัวอย่าง บราวเซอร์ที่รองรับ
27. X:last-childul > li:last-child { color: green; } ตรงข้ามกับ first-child โดยที่ last-child จะระบุ item ตัวสุดท้ายของ element parent แทน ตัวอย่างลองดูตัวอย่างง่ายๆ ที่จะอธิบายความเป็นไปได้ของการใช้ class เหล่านี้ เราจะทำการสร้างและทำการ style list item Markup<ul> <li> List Item </li> <li> List Item </li> <li> List Item </li> </ul> ไม่มีอะไรพิเศษ แค่ list ธรรมดา CSSul { width: 200px; background: #292929; color: white; list-style: none; padding-left: 0; } li { padding: 10px; border-bottom: 1px solid black; border-top: 1px solid #3c3c3c; } style ที่เขียนนี้จะใส่สี background เอา padding ที่เป็น browser-default บน element
ปัญหาเดียวสำหรับภาพด้านบนก็คือ border จะถูกใส่ทุกๆ top และ bottom ของ unordered list ด้วย ซึ่งไม่ใช่ที่เราต้องการ ให้ใช้ pseudo li:first-child { border-top: none; } li:last-child { border-bottom: none; } นั่นแหละ! แก้ได้แล้ว แสดงตัวอย่าง บราวเซอร์ที่รองรับ
ใช่แล้ว - IE8 support แค่ 28. X:only-childdiv p:only-child { color: red; } ในความเป็นจริง คุณจะไม่ค่อยพบว่าคุณใช้ pseudo class มันช่วยให้คุณระบุ element ที่เป็นลูกตัวเดียวของ parent เท่านั้น (ตามชื่อ only child) ตัวอย่าง ลองดูโค้ดด้านบน เพียงแค่ paragraph ที่เป็นลูกตัวเดียวของ div นั้นจะมีสีแดง ลองดู markup ต่อไปนี้ก็ได้ <div><p> My paragraph here. </p></div> <div> <p> Two paragraphs total. </p> <p> Two paragraphs total. </p> </div> ในกรณีนี้ paragraph ภายใน แสดงตัวอย่าง บราวเซอร์ที่รองรับ
29. X:only-of-typeli:only-of-type { font-weight: bold; } pseudo class อันนี้สามารถใช้ได้หลากหลาย มันจะระบุ element ที่ไม่มีพี่น้อง (sibling) ภายใน parent ที่ครอบมัน จากตัวอย่าง ลองระบุ ul ทั้งหมดที่มีแค่ list อันเดียว แรกเลย
ถามตัวคุณเองก่อนว่าจะทำได้อย่างไร คุณสามารถใช้ ul > li:only-of-type { font-weight: bold; } แสดงตัวอย่าง บราวเซอร์ที่รองรับ
30. X:first-of-typepseudo class first-of-type ทั้งจะช่วยให้เราเลือกพี่น้องแรก (first sibling) ภายใน type ของมัน เริ่มทดสอบเพื่อให้เข้าใจมากขึ้น เราจะมาทดลองกัน Copy mark-up ต่อไปนี้ไปที่ code editor ของคุณ <div> <p> My paragraph here. </p> <ul> <li> List Item 1 </li> <li> List Item 2 </li> </ul> <ul> <li> List Item 3 </li> <li> List Item 4 </li> </ul> </div> และก็ อย่าเพิ่งอ่านอะไรถัดไปนะ ลองเดาว่าจะทำอย่างไรจึงจะเลือกเฉพาะ "List item อันที่ 2" ได้ เมื่อคุณพบคำตอบแล้ว (หรือยอมแพ้ 555+) อ่านต่อเลย เฉลยวิธีที่ 1มีวิธีการมากมายที่จะแก้ปัญหา เราจะ review แค่บางอัน เริ่มจากการใช้ ul:first-of-type > li:nth-child(2) { font-weight: bold; } โค้ดสั้นกระชับนี้บอกว่า "ค้นหา unordered list ตัวแรกใน page จากนั้นหาเฉพาะที่มีลูกที่เป็น list ตามมา จากนั้น เอาแค่ตัวที่สองที่อยู่ในนั้น เฉลยวิธีที่ 2ตัวเลือกอื่นคือใช้ adjacent selector p + ul li:last-child { font-weight: bold; } ในเหตุการณ์นี้ เราจะหา เฉลยวิธีที่ 3เราสามารถรู้สึกได้ทั้งรำคาญหรือสนุก? ตราบที่เราต้องการ selector เหล่านี้ ul:first-of-type li:nth-last-child(1) { font-weight: bold; } ครั้งนี้ เราเลือก ul ตัวแรกบน page จากนั้นค้นหา list item ตัวแรก แต่ว่าเริ่มจากท้ายนะ! :) แสดงตัวอย่าง บราวเซอร์ที่รองรับ
สุดท้ายถ้าคุณกังวลเกี่ยวกับ browser รุ่นเก่าๆ เช่น Internet Explorer 6 คุณก็ต้องระวังในการใช้ selector ใหม่ๆ เหล่านี้ด้วย แต่อย่างว่า ถ้ามันทำให้คุณถูกขวางกั้นจากการเรียนรู้สิ่งเหล่านี้ หรือเหมือนคุณไม่ค่อยสบายใจ ไงก็ลองเช็ค browser-compatibility จากที่นี่ดู หรือว่าคุณอาจใช้ Dean Edward's excellent IE9.js script เพิ่มเข้าไปในโค้ดของคุณเพื่อทำให้ browser รุ่นเก่าๆ support เจ้า selector เหล่านี้ได้ จากนั้น เมื่อคุณทำงานกับไลบารี่ Javascript เช่น jQuery ที่แสนโด่งดัง จำไว้เสมอ ถ้าเป็นไปได้ให้พยายามใช้ native CSS3 selector เพียวๆก่อน แทนที่จะใช้จากตัว library มันจะทำให้ code ของคุณทำงานได้ไวขึ้น เพราะ engine ของ selector สามารถถูก parse ได้โดยตรง (native parsing) เอาหล่ะ! ขอบคุณที่อ่านและติดตาม ผมหวังว่าคุณจะได้ trick ดีๆ ไปบ้าง ไม่มากก็น้อยหล่ะ! |