Quy tắc BEM trong CSS – Bạn không cần phải đau đầu với cách đặt tên class nữa

238

Highlight: BEM là viết tắt của Block Element Modifiers – một quy tắc giúp bạn đặt tên các selector của CSS.

Chào các bạn,

Bạn có bao giờ code CSS mà không biết phải đặt tên class như thế nào không? Mình thì có đấy. Nhất là khi maintain dự án, mất bao nhiêu công mới nghĩ ra được cái tên hay thì lại bị người người trước dùng mất rồi. Tự nghĩ Code CSS thì nên tập trung vào việc căn chỉnh các thuộc tính, chứ không nên mất nhiều thời gian vào cách đặt tên, nên mình đã đi tìm hiểu xem có cái quy tắc nào trong cách đặt tên không, để rồi cứ theo quy tắc là làm, đỡ phải nghĩ nhiều.

Sau một hồi lục sục trên mạng, mình thấy có cái quy tắc BEM này khá hay nên viết bài để chia sẻ tới mọi người.

I. Quy tắc BEM là gì?

BEM là viết tắt của Block Element Modifiers – một quy tắc giúp bạn đặt tên các selector của CSS.

Block Element Modifiers nghĩa là “Khối – Phần tử – Biến thể”, dịch ra Tiếng Việt nghe không được sát nghĩa và có vẻ không “chuyên nghiệp”, nên thôi mình cứ để Tiếng Anh nhé.

Với quy tắc BEM, nó sẽ chia các class css ra làm 3 loại:

  • class định nghĩa cho một block
  • class định nghĩa cho các element trong block
  • class định nghĩa các “biến thể” cho block hoặc cho element trong block.

Rắc rối nhỉ, thôi thì xem cái ví dụ này để dễ hiểu hơn bạn nhé.

CSS viết theo quy tắc BEM

/* class định nghĩa một block */
.product {  }

/* class định nghĩa element của block */
.product__title {  }
.product__description {  }
.product__image {  }

/* class định nghĩa các "biến thể" của block */
.product--style-1 {  }
.product--big {  }
.product--small {  }
.product__title--style-1 {  }

HTML sử dụng CSS viết theo quy tắc BEM

<div class="product product--small">
    <div class="product__image">
        <img src="..." alt="">
    </div>
    <div class="product__title product__title--style-1">Iphone 11 Pro</div>
    <div class="product__description">Siêu đắt</div>
</div>

Từ hai đoạn code trên bạn có thể thấy:

  • product là một block, style của nó được định nghĩa thông qua class .product
  • .product__title, .product__image, .product__description lần lượt là các class element.
  • .product--style-1, .product--big, .product--small, .product__title--style-1 là các class “biến thể”.

Tổng quát lại, chúng ta có thể thấy một class viết theo quy tắc BEM sẽ có cấu trúc như sau

Block__Element--Modifier

Với cách đặt tên kiểu này, các css selector sẽ khó mà trùng nhau được.

II. Lợi ích khi sử dụng BEM

Lợi ích mà ai cũng thấy được ngay đó là BEM giúp chúng ta giảm khả năng 2 css selector bị trùng nhau – giống như ngay từ đầu mình đề cập. Nhưng ngoài ra, BEM còn có một số lợi ích khác:

  • Giúp bạn hình dung ra được cấu trúc của một block HTML sẽ sử dụng các class này.
  • Dễ dàng nắm bắt được các thành phần phụ thuộc lẫn nhau.
  • Với BEM, nó làm “phẳng” các class, không có sự lồng cấp kiểu .a .b .c, giúp bạn không cần phải để ý tới độ ưu tiên (specificity) khi code css.
  • Giảm công sức của developer trong việc phải cố nghĩ ra một cái tên vừa hay vừa chưa tồn tại.

Ngoài các lợi ích kể trên, BEM còn phù hợp để triển khai với SCSS

Ví dụ: Vẫn là đoạn CSS ở ví dụ trên, nhưng giờ mình viết theo SCSS.

.product {
    &__title {
        &--style-1 { }
    }

    &__description { }
    &__image { }

    &--style-1 { }
    &--big { }
    &--small { }
}

III. Một số ý kiến không đồng tình với quy tắc BEM

Dù có nhiều lợi ích, nhưng có nhiều người không thích dùng quy tắc này vì

Nó dài và xấu

Mình công nhận điều này, nếu không cận thận bạn sẽ có .Mot-cai-class__dai--ngoang-ngoang-the-nay.

Nhưng dài mà mang đủ ý nghĩa, đảm bảo không bị trùng thì cũng không sao. Còn xấu thì… nhìn nhiều khắc quen.

Nó có vẻ không cần thiết

Quay trở lại với ví dụ ở phần đầu, mình có thể viết CSS không tuân theo quy tắc BEM và vẫn đáp ứng được một số lợi ích của BEM như sau:

.product {  }

.product .title {  }
.product .description {  }
.product .image {  }

.product.style-1 {  }
.product.big {  }
.product.small {  }
.product .title.style-1 {  }

Nhìn còn có vẻ gọn ngàng hơn đấy chứ, nhưng khi dự án phát triển tới một “cảnh giới” nhất định thì liệu bạn có chắc chắn các class sẽ không bị đặt tên chồng chéo không? Giả sử ở đâu đó trong project đã có ai đó định nghĩa các class .title, .image, .description rồi thì sao?

// Ai đó đã định nghĩa trước các selector thế này
.title {  }
.description {  }
.image {  }

Không biết bạn có cảm thấy không hài lòng với BEM ở chỗ nào không?

IV. Tổng kết

Tổng kết lại thì:

  • BEM là quy tắc đặt tên class cho CSS, mang lại nhiều lợi ích nhưng quan trọng vẫn là giúp developer bớt phải nghĩ ra cái tên vừa hay vừa chưa được sử dụng.
  • BEM sẽ tuyệt vời hơn khi sử dụng với SCSS
  • Có nhiều người không thích BEM vì nó làm tên class dài và xấu, hoặc họ tự có phương pháp khác thay thế BEM.

Còn bạn thế nào, bạn có thấy BEM cần thiết trong dự án của mình không? Hãy để lại comment cho mình biết với.