การเขียน CSS ของแต่ละคนมีเทคนิค มีสไตล์การเขียนแตกต่างกันไป ทำให้เวลามีคนเขียน CSS หลายคนในโปรเจคเดียวกัน หรือนำโค้ดของคนอื่นมาแก้ การจะอ่าน CSS ของคนอื่นให้เข้าใจจึงเป็นเรื่องลำบากมาก เพราะฉะนั้นจึงมีกลุ่มคนที่พยายามสร้างมาตรฐานในการเขียน CSS เพื่อให้โค้ดเป็นระเบียบ ทำงานกับคนอื่นง่าย และยังทำให้เวลาเรากลับมาเขียนหลังจากผ่านไปหลายเดือน ก็สามารถอ่านโค้ดเก่าตัวเองแล้วเข้าใจการทำงานได้ทันที
BEM หรือ “Block Element Modifier” คือวิธีการตั้งชื่อ class อย่างเป็นระบบ เพื่อที่จะทำให้เราสามารถไล่โค้ดได้ง่าย และลดความซ้ำซ้อนของโค้ด โดยการตั้งชื่อ class ด้วยวิธี BEM นั้น จะดูจากหน้าที่ของ html element นั้นๆ ซึ่งแบ่งออกเป็น 3 แบบ ด้วยกัน ดังนี้
Block - กล่องอะไรก็ตามที่อยู่ได้โดยอิสระ (เช่น กล่อง search, กล่อง log in, เมนูหลัก เป็นต้น)
Element - องค์ประกอบต่างๆ ของ Block (หาก Block เป็นคน Element ก็หมายถึงแขนขาของคนนั่นเอง)
Modifier - ใส่ให้กับ Block หรือ Element ที่มีสไตล์เฉพาะตัว (Modifier ของ Block ก็เช่น คนที่เป็นผู้หญิง ส่วน Modifier ของ Element ก็เช่น แขนข้างซ้าย เป็นต้น)
กฏข้อแรกที่ต้องจำไว้ คือ BEM CSS เขียน Selector ด้วย .class ทั้งหมด เราจะไม่ใช้ #ID เพื่อให้ Selector ที่เราเขียนมีความยืดหยุ่น สามารถใช้ได้หลายครั้งนั่นเองครับ ทีนี้มาดูกันว่า Block, Element, และ Modifier ซึ่งเป็นหัวใจหลักของ BEM CSS มันคืออะไรกันบ้าง
Block คือ HTML Element ที่ครอบ Element ย่อยอื่น ๆ เช่น Header, Sidebar, Content, Footer เป็นต้น
Element คือ HTML Element ย่อย ๆ ที่อยู่ใน Block
Logo กับ Ads โฆษณา คือ Element ที่อยู่ใน Block ชื่อ Header นั่นเอง
ในการเขียนแบบ BEM CSS เราจะใช้ __ (underscore 2 ตัว) คั่นระหว่าง Block กับ Element แบบนี้:
.block__element { }
เพราะฉะนั้น ถ้าเป็นกรณีของ Header ในเว็บไซต์ Designil ซึ่งมี Logo กับ Ads เราก็จะเขียน CSS แบบนี้
สังเกตว่าพอเขียนแบบนี้ เวลาเราอ่าน CSS จะเข้าใจได้ทันทีว่า Selector ไหนที่แก้แล้วจะไปเปลี่ยน Element ตัวไหน โดยที่ไม่ต้องดูไฟล์ HTML หรือใช้ฟังก์ชัน Inspect Element ใน Browser ด้วยซ้ำ
ในบางกรณี Block หรือ Element ของเราก็มีร่างแยกหลายรูปแบบ
การเขียน Modifier คือใส่ — (ขีดกลาง 2 ตัว) แล้วตามด้วยชื่อ Modifier เช่น
ถ้าเป็นกรณีแบบในรูปด้านบน ซึ่งมี Menu ใน Header 2 จุด เราก็อาจจะเขียนแบบนี้
ซึ่งการเลือกใช้คำว่า menu, top, main นี่แล้วแต่ความชอบของแต่ละคนเลยครับ อาจใช้คำว่า navigation แทน menu หรือ primary / secondary แทน main / top ก็ได้ เลือกคำที่คิดว่าเราและคนในทีมมาอ่านแล้วเข้าใจได้ก็พอ
ถ้าเขียน CSS แบบ BEM ก็จะออกมาเป็นแบบนี้
เวลาเขียนใน HTML ก็จะออกมาเป็นแบบนี้
การเขียน class=”alert alert–success” แบบด้านบนไม่ค่อยดีตรงที่ทำให้ HTML ยาวและอ่านยาก เราควรจะเขียนแค่ class=”alert–success” ก็พอ แต่ถ้าเขียน BEM CSS แบบนี้จะทำยังไง เพราะ CSS บางส่วนอยู่ใน Selector .alert { } ด้วย
หรือวิธีแก้ง่าย ๆ คือ เอา CSS ใน .alert { } ทั้งหมดมาโยนใส่ทั้ง .alert--success { }, .alert--warning { }, .alert--error { } หมดเลย แต่วิธีนี้ไม่ดีเพราะจะมีโค้ดซ้ำ ๆ หลายที่ (ฝรั่งจะเรียกว่า DRY – Don’t Repeat Yourself) ทั้งที่จริงเขียนแค่ทีเดียวแล้วเรียกใช้ดีกว่า ตอนแก้ไขจะได้แก้แค่ที่เดียวด้วย
วิธีแก้ปัญหานี้ที่ดีกว่าวิธีข้างบน คือ ใช้ SASS เข้ามาช่วย
ถ้าใช้ SASS เราสามารถทำให้ HTML เหลือแค่ class=”alert–success” โดยที่ไม่มีโค้ดซ้ำ เพราะ SASS มีฟีเจอร์ @extend ที่สามารถดึง CSS จาก Selector อื่นมาใส่ตัวมันเองได้ ทำให้เราไม่ต้องเขียน CSS เดิมซ้ำ ๆ
พอเขียน BEM ด้วย SASS โค้ดจะกลายเป็นแบบนี้
เท่านี้ HTML เราก็จะเหลือแค่
ลองเอาการเขียน BEM CSS ไปใช้งานกันดู แรก ๆ อาจจะรู้สึกแปลก ๆ เพราะ CSS Selector หน้าตาไม่ค่อยคุ้น หรือดูแปลก แต่พอเขียนไปเรื่อย ๆ และได้อ่านโค้ดคนอื่นไปเรื่อย ๆ จะพบว่ามีคนใช้ BEM CSS อยู่เยอะมาก และเราอ่านโค้ดเค้าได้ง่ายกว่าเดิมหลายเท่า