Hướng dẫn sử dụng BEM để đặt tên Class cho CSS
Trong CSS, việc đặt tên Class là một vấn đề mà rất nhiều Front-End Developer đau đầu. Kể cả với những học viên của tôi.
Việc đặt tên Class không có quy tắc, dẫn đến việc khó bảo trì và không thể kế thừa, làm việc nhóm với nhau được.
Trong bài viết này, tôi sẽ hướng dẫn các bạn sử dụng BEM để đặt tên Class cho CSS.
BEM là gì?
BEM viết tắt của Blocks, Elements, Modifiers, là một phương pháp đặt tên class cho HTML và CSS. Được phát triển tại Yandex giúp lập trình viên hiểu rõ hơn mối quan hệ giữa HTML và CSS trong dự án front end.
Ví dụ sau đây sẽ minh hoạ cách sử dụng ký pháp BEM:
/* Một Block (khối) độc lập */ .button {} /* Element (phần tử) con, phụ thuộc vào Block ở trên */ .button__price {} /* Modifier (bộ điều chỉnh) thay đổi trạng thái của Block */ .button--orange {} .button--red {}
Với cách đặt tên class này, ta có Block sẽ đại diện cho một component, và trong ví dụ ở đây, là một button .button
. Block cũng sẽ đóng vai trò là một parent mà trong nó sẽ có một hoặc nhiều hơn Element con liên quan. Tên class cho Element và mối quan hệ của nó với Block sẽ được diễn tả bằng tên của Block, tiếp theo là hai gạch dưới, và cuối cùng là tên của Element .button__price
. Thành phần thứ ba của BEM là các Modifier mà chúng sẽ giúp điều chỉnh các trạng thái hoặc phái sinh khác của Block / Element. Tên của Modifier sẽ được nối với tên Block / Element phía trước bởi 02 gạch ngang .button--orange
.
Trong HTML, BEM sẽ được dùng như sau:
<a class="button button--big button--orange" href="http://int3ractive.com"> <span class="button__price">$9.99</span> <span class="button__text">Subscribe</span> </a>
Tại sao phải sử dụng BEM?
Trước tiên, BEM giúp người mới tham gia dự án dễ dàng phát hiện ra các trạng thái và các đối tượng con của một component đã được viết sẵn. Điều này giúp tránh cho họ phải viết lại những kiểu CSS đã có sẵn và hạn chế việc viết thừa code hoặc trùng kiểu CSS, điều mà rất hay xảy ra trong dự án lớn có nhiều người tham gia.
Thứ hai, chỉ cần đọc HTML, bạn vẫn có thể nhanh chóng nắm được các thành phần phụ thuộc lẫn nhau. Trong ví dụ trên, bạn dễ dàng nhìn thấy .button__price
phụ thuộc vào .button
mặc dù bạn chưa biết vai trò cụ thể của nó ngay lập tức.
Thứ ba, với BEM, mọi định nghĩa chỉ có một cấp class và không lồng cấp. Điều này giúp cho độ ưu tiên (specificity) chung của hệ thống CSS thấp. Đây là một lợi thế vì sau này bạn không phải “chiến đấu” với specificity của những thuộc tính đã có sẵn (VD: siêu lồng cấp .a .b .c .d .e {...}
) cũng như vận dụng những kỹ thuật không hay để thay thế được style (chẳng hạn !important
hay inline CSS).
Quy luật thác nước cascading của CSS là con dao hai lưỡi: nó giúp dễ dàng định nghĩa những thuộc tính và kiểu chung trên những selector tổng quát mà không cần phải khai báo lặp lại trên từng phần tử, nhưng nếu không nắm được tầm ảnh hưởng, lập trình viên CSS rất dễ gây ra những tác động phụ đến các đối tượng không liên quan khi chỉnh sửa trên những class có sẵn hoặc thậm chí viết mới. Với BEM, lập trình viên sẽ tự tin hơn khi bắt tay chỉnh sửa hoặc viết thêm style vì đã biết rõ tầm ảnh hưởng của selector mà mình đang viết ra.
Tóm lại, BEM, nếu áp dụng triệt để, sẽ giúp cải thiện sự phối hợp giữa các thành viên trong nhóm. Ngoài ra, nó buộc người viết CSS phải đầu tư suy nghĩ về việc xây dựng những component độc lập và tái sử dụng được (phù hợp với tiêu chí của OOCSS).
Sử dụng BEM với SASS
Với phiên bản SASS mới nhất hiện nay, việc viết theo ký pháp BEM trong SCSS dễ dàng và thuận tiện hơn bao giờ hết.
Bạn vẫn sẽ sử dụng cách viết lồng để cô lập khối component và kết hợp với biểu tượng parent &
của SASS để đặt tên cho Element và Modifier mà không phải đánh lại tên của Block.
.block { &__element {} &--mod {} }
Mặc dù viết lồng cấp, khi được biên dịch thành CSS, chúng vẫn được trải phẳng thành một cấp class theo đúng tinh thần của BEM:
.block {} .block__element {} .block--mod {}
Nếu bạn sử dụng LibSass (nhanh hơn rất nhiều lần bản gốc Ruby) để biên dịch SASS, thì hãy đảm bảo các công cụ wrapper được cập nhật các phiên bản tương đương hoặc mới hơn như sau: node-sass 3.4.0, gulp-sass 2.1.0 (nếu sử dụng GulpJS) và grunt-sass 1.1.0 (nếu sử dụng GruntJS)
Thế còn LESS? Vì tôi không sử dụng LESS nên sẽ không đề cập ở đây. Bạn có thể giúp bổ sung hướng dẫn cho LESS nếu nó có cú pháp trợ giúp tương đương.
Kết luận
Trên đây, tôi đã chia sẻ kỹ thuật sử dụng BEM để đặt tên class cho CSS. Tuy nhiên, với phương pháp này có nhiều ý kiến trái chiều: tên class xấu, dài dòng, phức tạp,…
Tuy nhiên, về góc độ bảo trì, làm việc nhóm thì cách đặt tên Class theo quy tắc thực sự cần thiết.
Nếu có bất kỳ câu hỏi nào, hãy comment phía dưới bài viết này.
Cảm ơn ad. Bài hữu ích quá!
Class chấp nhận cả gạch trên và gạch dưới sao?
Đúng rồi nhé. Chỉ có biến không chấp nhận gạch ngang thôi. class CSS vẫn nhận bình thường.
[…] đây, tôi có viết bài sử dụng BEM để đặt tên Class cho CSS. Đặt tên Class, Function, Variable, Property có những chuẩn đặt tên nào? Và nên […]