เขียน CSS ให้ดีขึ้นได้ง่าย ๆ ด้วยเทคนิค BEM !!

designil

การเขียน CSS ของแต่ละคนมีเทคนิค มีสไตล์การเขียนแตกต่างกันไปครับ ทำให้เวลามีคนเขียน CSS หลายคนในโปรเจคเดียวกัน หรือนำโค้ดของคนอื่นมาแก้ต่อ (โดยเฉพาะตอนซื้อ HTML Template หรือ Theme จาก Themeforest มาแล้วต้องแก้ไข) การจะอ่าน CSS ของคนอื่นให้เข้าใจจึงเป็นเรื่องลำบากมาก

เพราะฉะนั้นจึงมีกลุ่มคนที่พยายามสร้างมาตรฐานในการเขียน CSS เพื่อให้โค้ดเป็นระเบียบ ทำงานกับคนอื่นง่าย และยังทำให้เวลาเรากลับมาเขียนหลังจากผ่านไปหลายเดือน ก็สามารถอ่านโค้ดเก่าตัวเองแล้วเข้าใจการทำงานได้ทันที

บทความที่เกี่ยวข้อง: CSS Guideline – เปิดตำราสอนเทคนิคเขียน CSS อย่างมืออาชีพ !!

วันนี้เราจะมาพูดถึง การเขียน CSS แบบ BEM ซึ่งเป็นหนึ่งในมาตรฐานที่ได้รับความนิยมมากที่สุด ท่านที่สนใจมาตรฐานอื่น ๆ เดี๋ยวจะเอามาเขียนเล่าให้ฟังในโอกาสหน้าครับ ซึ่งมี OOCSS (Object Oriented CSS) กับ SMACSS (Scalable and Modular Architecture for CSS ชื่อยาวมาก)

BEM CSS คืออะไร

BEM ย่อมาจาก Block Element Modifier ซึ่งเป็นการแบ่งส่วนต่าง ๆ บนหน้าเว็บไซต์ออกเป็น Block, Element, และ Modifier นั่นเอง ตัวอย่างของการเขียน BEM CSS ก็คือ Selector แบบนี้ครับ บางท่านอาจจะเคยแกะโค้ดคนอื่นเจอมาแล้ว

[css].badge__text {}
.badge–article {}
.badge–review {}[/css]

ซึ่งจะสังเกตได้ว่าการเขียน CSS แบบ BEM คือการใช้ (ขีดกลาง 2 ตัว) กับ __ (underscore 2 ตัว) ในการเขียน Selector ครับ

กฏข้อแรกที่ต้องจำไว้ คือ BEM CSS เขียน Selector ด้วย .class ทั้งหมด เราจะไม่ใช้ #ID เพื่อให้ Selector ที่เราเขียนมีความยืดหยุ่น สามารถใช้ได้หลายครั้งนั่นเองครับ ทีนี้มาดูกันว่า Block, Element, และ Modifier ซึ่งเป็นหัวใจหลักของ BEM CSS มันคืออะไรกันบ้าง

Block ใน BEM CSS คืออะไร

Block คือ HTML Element ที่ครอบ Element ย่อยอื่น ๆ เช่น Header, Sidebar, Content, Footer เป็นต้น ลองดูตัวอย่าง Layout ด้านล่างนี้ครับ:

ตัวอย่าง BEM CSS Blocks
ตัวอย่าง BEM CSS Blocks – รูปประกอบจาก WebDesignTuts

HTML Element กล่องสีเขียวแต่ละอันคือ Block นั่นเองครับ

Element ใน BEM CSS คืออะไร

Element คือ HTML Element ย่อย ๆ ที่อยู่ใน Block ตัวอย่างเช่น ใน Header ของธีมใหม่เว็บไซต์ Designil.com ก็มี Logo กับ Ads โฆษณา

Header Element ของ BEM CSS

Logo กับ Ads โฆษณา คือ Element ที่อยู่ใน Block ชื่อ Header นั่นเองครับ

ในการเขียนแบบ BEM CSS เราจะใช้ __ (underscore 2 ตัว) คั่นระหว่าง Block กับ Element แบบนี้:

[css].block__element { } [/css]

เพราะฉะนั้น ถ้าเป็นกรณีของ Header ในเว็บไซต์ Designil ซึ่งมี Logo กับ Ads เราก็จะเขียน CSS แบบนี้ครับ

[css].header { }
.header__logo { }
.header__ads { }[/css]

สังเกตว่าพอเขียนแบบนี้ เวลาเราอ่าน CSS จะเข้าใจได้ทันทีว่า Selector ไหนที่แก้แล้วจะไปเปลี่ยน Element ตัวไหน โดยที่ไม่ต้องดูไฟล์ HTML หรือใช้ฟังก์ชั่น Inspect Element ใน Browser ด้วยซ้ำ

Modifier ใน BEM CSS คืออะไร

ในบางกรณี Block หรือ Element ของเราก็มีร่างแยกหลายรูปแบบครับ เช่น ใน Header ของเว็บไซต์ Designil.com มี Menu อยู่ 2 จุด ด้านบนโลโก้ กับ ด้านล่างโลโก้

Dsignil Header BEM CSSMenu ด้านบนกับด้านล่างมีหน้าที่เหมือนกัน หน้าตาคล้าย ๆ กัน แตกต่างกันที่ Menu ด้านบนตัวหนังสือเล็กกว่า และไม่มีแถบสีส้มเวลาชี้เม้าส์เหมือน Menu ด้านล่าง ซึ่งในกรณีแบบนี้ การเขียน BEM CSS จะเรียกเมนูแต่ละจุดว่าเป็น Modifier ครับ

การเขียน Modifier คือใส่ — (ขีดกลาง 2 ตัว) แล้วตามด้วยชื่อ Modifier เช่น

[css].block–modifier { }
.block–modifier__element { }
.block__element–modifier { }[/css]

ถ้าเป็นกรณีแบบในรูปด้านบน ซึ่งมี Menu ใน Header 2 จุด เราก็อาจจะเขียนแบบนี้ครับ

[css].header__menu–top { }
.header__menu–main { }[/css]

ซึ่งการเลือกใช้คำว่า menu, top, main นี่แล้วแต่ความชอบของแต่ละคนเลยครับ อาจใช้คำว่า navigation แทน menu หรือ primary / secondary แทน main / top ก็ได้ เลือกคำที่คิดว่าเราและคนในทีมมาอ่านแล้วเข้าใจได้ก็พอครับ

อีกหนึ่งตัวอย่างการเขียน BEM ลองมาดูกล่อง Alert ที่จะแสดงใน Form บนหน้าเว็บไซต์ครับ

UI Alert Box BEM CSS
Alert Box Design โดย Ali Asghar

ถ้าเขียน CSS แบบ BEM ก็จะออกมาเป็นแบบนี้

[css].alert { } // CSS ที่ใช้ร่วมกันทุกกล่อง
.alert–success { } // CSS กล่องเขียว
.alert–warning { } // CSS กล่องเหลือง
.alert–error { } // CSS กล่องแดง[/css]

เวลาเขียนใน HTML ก็จะออกมาเป็นแบบนี้

[html]<div class=”alert  alert–success”>Success!</div>
<div class=”alert  alert–warning”>Warning!</div>
<div class=”alert  alert–error”>Error!</div>[/html]

เดี๋ยวก่อน! มาดูวิธีใช้ SASS ช่วยให้เขียน BEM ได้สะดวก

การเขียน 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 คืออะไร? เทคนิคช่วยให้การเขียน CSS เป็นเรื่องง่าย ๆ ใช้กันทั่วโลก !!

ถ้าใช้ SASS เราสามารถทำให้ HTML เหลือแค่ class=”alert–success” โดยที่ไม่มีโค้ดซ้ำ เพราะ SASS มีฟีเจอร์ @extend ที่สามารถดึง CSS จาก Selector อื่นมาใส่ตัวมันเองได้ ทำให้เราไม่ต้องเขียน CSS เดิมซ้ำ ๆ

พอเขียน BEM ด้วย SASS โค้ดจะกลายเป็นแบบนี้

.alert { } // CSS ที่ใช้กับทุกกล่อง
.alert--success {
  @extend .alert;
  // CSS กล่องเขียว}

เท่านี้ HTML เราก็จะเหลือแค่

<div class="alert--success"></div>

สรุปการใช้งาน BEM CSS

ลองเอาการเขียน BEM CSS ไปใช้งานกันดูครับ แรก ๆ อาจจะรู้สึกแปลก ๆ เพราะ CSS Selector หน้าตาไม่ค่อยคุ้น หรือดูแปลก แต่พอเขียนไปเรื่อย ๆ และได้อ่านโค้ดคนอื่นไปเรื่อย ๆ จะพบว่ามีคนใช้ BEM CSS อยู่เยอะมาก และเราอ่านโค้ดเค้าได้ง่ายกว่าเดิมหลายเท่าครับ

ตอนแรกผมก็รู้สึกว่า Selector อันนี้มันแปลก ๆ ครับ แต่ล่าสุดได้อ่านโค้ดของ WordPress Theme ที่ขายใน Themeforest ซึ่งอ่านแล้วเข้าใจได้ง่ายมากว่า Block ไหนมี Element อะไรบ้าง และ Element ไหนมี Modifier อะไรบ้าง ขอยกตัวอย่างให้ดูง่าย ๆ นะครับ

.article--grid { }
.article--list { }
.article--masonry { }

จากการอ่าน CSS ผมก็รู้ได้ทันทีว่า Theme นี้มีการแสดงผลบทความ 3 แบบ นั่นคือ Grid, List, และ Masonry ครับ โดยไม่ต้องไปตามหา HTML เลย เพราะ WordPress Theme มีไฟล์เยอะมาก จะไปหา HTML ส่วนหนึ่งให้เจอไม่ใช่เรื่องง่ายครับ

ท่านผู้อ่านมีความคิดเห็นอย่างไรเกี่ยวกับการเขียน CSS แบบ BEM มาบอกกันด้านล่างได้เลยครับ! คอมเม้นท์ไหนถูกใจแอดมินอาจมีของขวัญเล็ก ๆ น้อย ๆ ให้ด้วยครับ :D

designil

designil

Data engineer & WordPress Developer ทำงานที่บริษัทแคนว่า ซิดนีย์ออสเตรเลีย ปัจจุบันเป็นเจ้าของเว็บไซต์ Designil, DataTH ชอบอ่านบทความใหม่ๆ ตลอดเวลา และชอบสรุปเรื่องราวเกี่ยวกับเทคโนโลยีให้ภาษาที่เข้าใจง่าย ยินดีที่ได้รู้จักทุกคนนะครับ
บทความทั้งหมด