CSS Tabs เหมาะสำหรับแสดงข้อมูลที่เกี่ยวข้องในที่เดียว navigate ง่าย ดูเหมือน tabbed dividers ใน recipe box หรือ binder ตัวอย่างเว็บไซต์ที่ใช้ tabbed navigation:
- Southwest Airlines ใช้ tabs ให้นำทางระหว่าง check-in, book flight, เพิ่ม hotel
- Enterprise ใช้ tabs สำหรับ navigation เลือก rent หรือ buy และ learn services
สังเกตเว็บทั้งสอง คิดถึง pros ของ UI component นี้ แก้ปัญหาอะไร? ข้อมูลประเภทไหนเหมาะกับ tabbed navigation?
เมื่อต้องการ UI structure จัดระเบียบ text/ข้อมูลเป็น meaningful components แสดงบนหน้าจอโดยไม่佔พื้นที่มาก tabbed navigation เป็นตัวเลือกดี เราจะพูดเพิ่มเมื่อได้ใช้ JavaScript, jQuery, Bootstrap แต่มี implementation ที่ใช้แค่ HTML และ pure CSS มาเริ่มกัน:
Setup HTML:
สร้าง boilerplate HTML พร้อม container ใน body เป็น main container เรียก class="tabs" HTML ควรเป็น:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Tabs</title> <style> /* No CSS to display yet */ </style> </head> <body> <div class="tabs"></div> <body> </html>
ภายใน "tabs" <div> ใส่
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Tabs</title> <style> /* No CSS to display yet */ </style> </head> <body> <div class="tabs"> <div class="tab"> /* THIS IS OUR PLAN IN ACTION*/ /*input */ <input type="radio" id="tab-1" name="tab-group-1" checked/> /*label for input */ <label for="tab-1">Label 1</label> /* content */ <div class="content">Our content will go here</div> </div> <div class="tab"> <input type="radio" id="tab-2" name="tab-group-1" checked/> <label for="tab-2">Label 2</label> <div class="content gryffindor">Our content will go here</div> </div> <div class="tab">Try these two on your own! Follow the same convention as above for your class names and ids - I am using a HP theme, but name them whatever you'd like!</div> <div class="tab"></div> </div> <body> </html>
ภายใน class content จะเป็น content ใช้ associated content บน tab เดียวกัน
เริ่มเขียน CSS:
เขียน CSS เริ่มจาก biggest container ลงมาสูงสุด minimum ที่ต้องทำ:
- Wild card selector ตั้ง box-sizing: border-box
- Main container: display: flex และ position: relative Display: flex ให้ tabs วางติดกันในแถว Relative position เป็น boundary/fence contain tab content
ตอนนี้เห็น 4 blocks ของ text พร้อม radio button และ content ต้องการแสดง checked block ซ่อนอีก blocks
- บน .tab container จัด style label:
- 1px solid border สีไหนก็ได้
- Padding: 5px, 10px – เพิ่ม space รอบ label text
- Border-radius 10px, 10px, 0px, 0px – ทำให้ label ดูเหมือน tab แท้
ตอนนี้ labels มี circular radio buttons ด้านซ้าย ดูเหมือน tab แท้ แต่ต้องซ่อน circular portion ของ radio button เพื่อรักษา checked attribute
- Select button ด้วย .tab [type='radio'] ตั้ง display: none ซ่อนมัน
ต่อมา จัดการ content ให้แสดงแค่หนึ่ง tab:
- Select content div ตั้ง position: absolute absolute position ให้ div วางได้ไหนก็ได้ใน relative parent ใช้ top, right, left, bottom กำหนดตำแหน่ง กรณีนี้ left และ right = 0 สร้าง border และ background color non-transparent
- z-index ของ selected tab ให้ tab panel อยู่บนสุด Select checked button และ content ด้วย [type='radio']:checked ~ label ~ .content "~" ใน CSS บอกว่า content class ที่อยู่หลัง label ที่อยู่หลัง checked radio button
- แสดง active tab ตั้ง [type='radio']:checked ~ label background color ต่างกัน
ตอนนี้ user คลิก tabs แต่ละอัน สลับได้สำเร็จโดยไม่เห็น content อื่นนี่คือ minimum สำหรับ tabbed navigation ลองปรับ CSS เปลี่ยน styling! Working implementation ด้านล่าง:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Tabs</title> <style> * { box-sizing: border-box; } body { font-family: 'Roboto'; } .tabs { max-width: 700px; min-height: 100px; margin: 25px 0; width: 100%; display: flex; /* allows for tabs to be next to each other */ position: relative; /* relative here contains the width of the content */ } .tab label { padding: 5px 10px; border: 1px solid #ccc; cursor: pointer; border-radius: 10px 10px 0 0; } .tab [type='radio'] { display: none; /* this makes the radio buttons disappear - we are only keeping track if they are checked or not */ } h3 { margin: 10px 40px; } ul { list-style-type: none; } .content { padding: 10px; border-radius: 0px 10px 10px 10px; position: absolute; left: 0; right: 0; background: white; border: 1px solid #ccc; /* the left and right at 0 help the tabs to overlap each other */ } /* This allows the selected tab to be on top */ [type='radio']:checked ~ label ~ .content { z-index: 1; } [type="radio"]:checked ~ label { background: lightgrey; } /* color scheme for tabs */ [type='radio']:checked ~ #gryffindor { background: #ec9086; color: #241806; } [type='radio']:checked ~ #ravenclaw { background: #3054ca; color: #241806; } [type='radio']:checked ~ #slytherin { background: #089714; color: #252525; } [type='radio']:checked ~ #hufflepuff { background: #f0d695; color: #372e29; } [type='radio'] ~ #slytherin { background: #033807; color: #aaaaaa; } [type='radio'] ~ #hufflepuff { background: #f0c75e; color: #372e29; } [type='radio'] ~ #gryffindor { background: #9c1203; color: #e3a000; } [type='radio'] ~ #ravenclaw { background: #0e1a40; color: #946b2d; } .gryffindor { background: #9c1203; color: #e3a000; } .slytherin { background: #033807; color: #aaaaaa; } .hufflepuff { background: #f0c75e; color: #372e29; } .ravenclaw { background: #0e1a40; color: #946b2d; } </style> </head> <body> <div class="tabs"> <div class="tab"> <input type="radio" id="tab-1" name="tab-group-1" checked/> <label id="gryffindor" for="tab-1">Gryffindor</label> <div class="content gryffindor"> <h3>HP Chars in Gryffindor</h3> <ul class="gryffindor-students"> <li>Harry Potter</li> <li>Hermione Grainger</li> <li>Ron Weasley</li> <li>Albus Dumbledore</li> <li>Katie Bell</li> <li>Neville Longbottom</li> </ul> </div> </div> <div class="tab"> <input type="radio" id="tab-2" name="tab-group-1"/> <label id="slytherin" for="tab-2">Slytherin</label> <div class="content slytherin"> <h3>HP Chars in Slytherin</h3> <ul class="slytherin-students"> <li>Draco Malfoy</li> <li>Narcissa Black</li> <li>Lucius Malfoy</li> <li>Severus Snape</li> <li>Tom Riddle</li> <li>Dolores Umbridge</li> </ul> </div> </div> <div class="tab"> <input type="radio" id="tab-3" name="tab-group-1"/> <label for="tab-3" id="ravenclaw">Ravenclaw</label> <div class="content ravenclaw"> <h3>HP Chars in Ravenclaw</h3> <ul class="ravenclaw-students"> <li>Lisa Turpin</li> <li>Luna Lovegood</li> <li>Gilderoy Lockhart</li> <li>Garrick Ollivander</li> <li>Padma Patil</li> <li>Sybil Trelawney</li> </ul> </div> </div> <div class="tab"> <input type="radio" id="tab-4" name="tab-group-1"> <label for="tab-4" id="hufflepuff">Hufflepuff</label> <div class="content hufflepuff"> <h3>HP Chars in Hufflepuff</h3> <ul class="hufflepuff-students"> <li>Cedric Diggory</li> <li>Newton Scamander</li> <li>Nymphadora Tonks</li> <li>Pomona Sprout</li> <li>Susan Bones</li> <li>Teddy Lupin</li> </ul> </div> </div> </div> </body> </html>