Share vì hữu ích

4 phút đọc

Nếu bạn là một Frontend Developer, việc phải xây dựng các layout trên một website sẽ cần tới việc đặt tên các class và sử dụng element một cách hợp lý.

BEM là một thỏa thuận, theo như cách nói của những ai thường nghĩ tới việc teamwork, cho việc xây dựng tiêu chuẩn cơ bản về đặt tên trong CSS.

BEM rất phù hợp với các site production, tức hoạt động phục vụ end-client thay vì các template để sửa.

Tại sao lại vậy? BEM đưa ra những quan điểm mang tính phân loại thuộc tính CSS cao và tính chất dùng lại thấp hơn nhiều so với việc sử dụng reuse class như các framework thông thường. Điều này sẽ được lý giải sau khi chúng ta nghiên cứu cách sử dụng BEM trong bài viết này.

Block trong BEM

Như bất kỳ phương thức tạo ra element nào đó trong HTML, BEM cũng định nghĩa Block.

Block ở đây thông thường có thể hiểu như các thành phần header, body, content, footer, cũng có thể là left-side hay right-side hay column nằm trong grid. Về cơ bản, tức là 1 Block thì cần chứa tối thiểu 1 Element ở trong.

Như vậy, với quy tắc của BEM, ta có thể xây dựng một số ví dụ mẫu sau:

Section Hero có thể là tập hợp các block:

  • .hero__container làm nhiệm vụ cân max width và padding left right
  • .hero__inner làm nhiệm vụ cân padding top bottom và điểm bám cho các element absolute (như button chẳng hạn).
  • .hero__header chứa Sub-title.
  • .hero__content chứa Headline và Description, và ảnh minh họa cho section
  • .hero__footer chứa button CTA

Bạn có thể thấy prefix của tất cả class đều là hero. Điều này giúp chúng ta nhận diện section này rất dễ dàng khi update mục tương ứng trong CSS.

Element trong BEM

Tiếp đến trong Block ta thường có các element, những đối tượng chịu tác động nhiều về typography hơn là layout.

Ở ví dụ là section Hero, có thể có các element như sau:

  • .hero__headline là Text cỡ lớn. Thường là H1 hoặc H2.
  • .hero__intro, .hero__description làm mô tả content.
  • .hero__image chứa ảnh minh họa
  • .hero__button với style riêng cho buttom trong section này

Bạn có thể thấy, các element này cũng có prefix hero đúng không nào?

Nhưng hãy lưu ý những điểm quan trọng sau đây:

  • Các element được gọi ở trên có thể mang các thuộc tính class khác. Ta có thể gán class="button hero__button", nhưng class hero__button phải nằm cuối cùng.
  • Ta có thể gọi 1 element thông qua Block. Ví dụ button nhưng nằm ở footer của section: .hero__footer-button
  • Trường hợp phổ biến là khi ta vận dụng linh hoạt cả hai trường hợp trên để đáp ứng mục đích sử dụng tốt nhất.

Modifier trong BEM

Quá trình xây dựng layout và các element không thể tránh khỏi việc trùng các class của lớp Element. Lớp Block thì tỷ lệ đụng mặt nhau ít hơn.

Modifier giúp xử lý nó triệt để hơn. Không vội nói tới BEM, ngay như trong Bootstrap bạn cũng có thể thấy button có nhiều kiểu thông qua sử dụng class như .btn-primary , .btn-danger chẳng hạn.

Với Modifier, thay vì một dấu gạch, chúng ta cần hai dấu gạch để phân định extend (style mở rộng).

Tức là .hero__button có thể có kiểu khác như .hero__button--outline, .hero__button--alert

Điểm lưu ý quan trọng trong Modifier là tính kế thừa. Modifier không sử dụng độc lập mà đi sau class gốc.

Như thế, class="hero__button hero__button--outline" mới là hợp lý.

Các tình huống cần nắm rõ trong BEM CSS

Đầu tiên, là việc nhiều element cùng mang 1 class.

Chẳng hạn, bạn có 3 button nằm lần lượt ở hero__header, hero__content và hero__footer. Tất nhiên, ban đầu cả 3 button này đều có thể mang class .hero__button.

Nhưng trong trường hợp 3 button này cần 3 màu khác nhau, bạn sẽ làm như thế nào?

<còn tiếp>

Kết luận

Vậy bạn đã hiểu rõ BEM và tự tin xây dựng layout theo đúng BEM chưa?

Share vì hữu ích

Tác giả: Khôi 'Pro' Nguyễn

Technical Lead tại Solis Lab. Quản lý ngôn ngữ tại vi.wordpress.org.

2 Trả lời “Toàn tập về BEM CSS

    1. Cứ giả sử em có 1 class .item, class .item này nếu được sử dụng trong .list, .blocks, .header chẳng hạn, thì sẽ tới lúc em thấy 1 .item chịu sự chi phối override của nhiều class cha. Điều này dẫn tới việc không biết thằng nào ghi đè lên thằng nào, hoặc sẽ có dạng css như .list.blocks > .item thì mới xử lý được.

Trả lời