Trang chủTác giảLiên hệ

CSS Architecture - Ways to write better CSS

By Phạm Ngọc Hoàng
Published in CSS
June 09, 2021
6 min read

Hello mọi người, lại là mình, Hoàng đây - dù chẳng mấy ai biết mình là ai :)

Hôm nay chúng ta cùng đi tìm hiểu một số vấn đề của css và cách để cải thiện chúng tốt hơn nhé. Như thường lệ, chúng ta có cấu trúc như sau

  1. Mở đầu
  2. BEM - Block__Element—Modifier
  3. Atomic CSS - Vì một thế giới hoà bình
  4. Kết luận

Mở đầu

CSS được thiết kế để trở thành một ngôn ngữ đơn giản và trực quan. Mục đích cơ bản của nó là để xác định selector để nhắm mực tiêu vào các phần tử HTML và áp dụng các thuộc tính cho nó. Chúng dễ dàng để nắm bắt và áp dụng. Khi làm việc trên những project lớn hoặc phức tạp, thì một số tính năng CSS có thể sẽ phức tạp hơn khi gặp vấn đề.

Những vấn đề với cách viết CSS hiện tại

  • Bạn còn nhớ lần đầu bạn viết CSS như thế nào chứ? Có thể là khai báo style cho một thẻ HTML nào đó.

Sau đó bạn biết thêm về idclass

Và bạn học được cách xử lý các pseudo selector, hoặc khai báo cho các phần tử anh, chị, em, họ hàng, con cháu…

Rồi khi đã quen tay với CSS và bạn bắt tay vào dự án thực tế, bạn bắt đầu nhận ra kẻ thù không ở đâu xa, đang lởn vởn quanh ta ý mà. Bạn bước vào cuộc chiến specificity war, đánh nhau tơi bời khói lửa với các chiến hữu trong team. Một trận đấu kinh hoàng khi ai cũng muốn override code của người đi trước. Người nắm giữ !important, người lại dùng kế hiểm inline style + !important. Tình nghĩa anh em có chắc bền lâu, chiến hữu quay đầu không nhìn mặt nhau. Thật ức chế!!!

Specificity là gì?

Specificity là một trọng số được trình duyệt sử dụng để quyết định CSS style nào sẽ được áp dụng cho các element. Specificity được tính toán dựa vào phân loại selector và số lượng selector áp dụng lên một element. Bạn có thể đọc thêm về chủ đề này trên trang MDN minh hoạ khá cụ thể cách tính specificity.

Tính tái sử dụng và kích thước tập tin CSS

Tính chất “cascading” của CSS vốn được sinh ra để hỗ trợ tái sử dụng code lại là một con dao 2 lưỡi. Cascading cùng với specificity làm cho CSS trở nên khó đoán và lời khuyên là hạn chế cascading được bao nhiêu thì hay bấy nhiêu. Điều này dẫn đến tập tin CSS chứa nhiều khai báo bị trùng lặp.

=> Đây là lúc chúng ta cần một kiến trúc.

BEM - Block__Element—Modifier

1. BEM là gì?

  • BEM là một quy ước đặt tên giúp bạn xây dựng các class theo từng block, mỗi block lại có element con, và các element này có thể sẽ có giao diện khác nhau tuỳ thuộc vào modifier của nó.
  • BEM được viết tắt bởi Block, Element, Modifier.

2. Quy ước đặt tên

.block: Thành phần cấp to nhất của abstraction hoặc component.
.block__element: Thành phần con bên trong của block.
.block—modifier: Là 1 phiên bản khác của block. Hay những thay đổi style khác so với style ban đầu (font-size, background, color, padding,…)

3. Tại sao lại dùng BEM?

  • BEM là một phương pháp hiệu quả để chia nhỏ trang thành từng component.
  • Giúp bạn tránh được conflict với class khác bằng cách chỉ sử dụng cách đặt tên theo BEM.
  • Khi 1 component không còn được sử dụng nữa thì có thể xoá đi class mà không sợ ảnh hưởng đến các component khác.

4. Biến thể của BEM

  • Khi thay đổi về style modifier chúng ta sẽ thêm thuộc tính khác chèn lên thuộc tính cũ. Nhưng nếu với nhiều thay đổi, code của chúng ta sẽ trở nên như thế này:
    <button class=”btn btn--primary btn--large btn--font-20 ….”>Submit</button>
  • BEM cung cấp biến thể để đơn giản việc viết class
    <button class=”btn --primary --large --font-20 ….”>Submit</button>

Hoàn toàn không sai, BEM là một phương pháp hiệu quả để chi nhỏ trang thành từng component và bạn hoàn toàn có thể tránh được những vấn đề xung đột ở phía trên bằng cách chỉ sửu dụng class được đặt tên theo BEM. Ngoài ra, khi một component không còn dùng nữa, bạn có thể xoá đi class mà không lo sợ ảnh hưởng đến các component khác.

Tuy nhiên, BEM cũng mang lại những vấn đề khó chịu mà bạn có thể xem thêm ở bài viết Battling BEM CSS: 10 Common Problems And How To Avoid Them. Có thể kể đến một số vấn đề sau:

  • Khi 1 component lớn, việc đặt tên cho các element cháu, chắt trở nên khó khăn (bởi tính chất đặt tên theo thành phần), đặt tên sao cho đúng ngữ nghĩa (semantic). Đừng coi thường nhé, một trong những công việc khó nhai nhất của khoa học máy tính đó là việc đặt tên.
  • Cân nhắc nên “tiếp tục Modifier?” hay “tạo ra component mới?”.
  • Quản lý các trạng thái của component (hover, active, focus, ….)

Vậy atomic CSS giải quyết được những vấn đề trên à?

Có thể, nhưng trước hết hãy xem atomic CSS là gì đã nhé.

Atomic CSS - Vì một thế giới hoà bình

1. Atomic CSS là gì?

Atomic CSS (thường được gọi là Funtional CSS hay Utility-first CSS) là cách khai báo các class sao cho mỗi class chỉ mô tả một tính năng duy nhất. Để xây dựng compponent lớn hơn, chúng ta sẽ kết hợp các class nguyên tử này lại với nhau. Chẳng hạn như:

Trong ví dụ trên, class .white chỉ làm duy nhất một việc là thay đổi màu chữ sang màu trắng, .bg-green sẽ thiết lập màu nền sang màu xanh, trong khi .px-20 điều chỉnh padding trục x thành 20px. Một component được viết theo atomic CSS sẽ giống như thế này: <button class=" text-white bg-green px-20 ">Submit</button>

2. Atomic CSS có gì hay?

  • Tránh cảnh binh đao: Lợi ích đầu tiên cũng giống như BEM, atomic CSS chỉ cho phép khai báo các class nên chúng không xảy ra tranh chấp specificity. Đồng thời, mỗi class chỉ mô tả một tính năng duy nhất, việc các thuộc tính giẫm chân lên nhau được hạn chế ở mức thấp nhất.
  • Tập tin CSS nhẹ hơn: Bằng cách xây dựng component bằng những class nguyên tử, bạn không cần phải lặp đi lặp lại những khai báo đã có. Khi nhận được thiết kế cho component mới, bạn chỉ cần kết hợp các class sẵn có với nhau hoặc viết thêm atomic classes. Những class mới xuất hiện sẽ tiếp tục được tái sử dụng nên số lượng các class bạn thêm vào sẽ ngày càng giảm dần đi khi tuổi thọ của dự án dài ra.
  • Không phải suy nghĩ chuyện đặt tên class: Vì các atomic classes được đặt tên gần với thuộc tính của chúng, bạn không cần phải suy nghĩ nên đặt tên gì. Một lợi ích nữa là nhìn vào HTML bạn có thể tương đối biết được style của một element. Lấy ví dụ:
  • Xây dựng prototype nhanh hơn Prototyping, hay là chuyện làm những giao diện giả để kiểm tra UI/UX, không còn lạ với dân làm frontend nữa. Một trong những lý do bạn chọn Bootstrap, Foundation, hay Bulma… cho dự án vì đơn giản chúng cung cấp những component được xây dựng sẵn, cùng với hệ thống grid và các class hỗ trợ. Nhưng rồi bạn sẽ lâm vào cảnh đánh nhau với các class của framework để tuỳ biến cho phù hợp với chuẩn thiết kế. Kết quả ra sao thì bạn biết rồi.

Các framework được thiết kế theo hướng atomic không có nhiều component, nhưng bù lại chúng không đặt quá nhiều ý kiến riêng và ép buộc bạn phải làm theo. Hầu hết đều cho phép bạn tuỳ chỉnh màu sắc, kích thước theo ý, từ đó bạn có thể xây dựng lên những component cần thiết.

3. Hạn chế

  • Bùng nổ class -> chỉ nên xây dựng class khi thực sự cần thiết

  • Tìm và thay đổi class theo yêu cầu khó khăn.

    Ví dụ:

    • Đối với BEM: tìm tên class “btn--update" -> replace tất cả thuộc tính trong đó
    • Đối với atomic CSS:
      • sửa đổi 1 class: tìm kiếm -> xoá class và đổi theo yêu cầu.
      • sửa đổi nhiều class: “bg-green red font-24” -> tương tự cách trên, nhưng chẳng may nó bị chèn thêm 1 class vào giữa “bg-green red fw-bold font-24” và thế là….
  • “Nếu viết hàng loạt class trong cùng 1 element vậy thì khác nào viết inline style đâu… tại sao không viết css inline cho nhanh?”

    Nhìn sơ qua thì đúng là giống như inline style vậy, và ai cũng biết inline style là bad practice. Nhưng atomic classes khác hoàn toàn và mạnh mẽ hơn inline style nhiều. Atomic classes cho phép bạn viết media queries, @support, pseudo selectors hay sử dụng animation, những điều mà inline style không làm được. Và vì atomic CSS được lưu trong tập tin CSS, trình duyệt có thể lưu vào bộ nhớ đệm, không giống như inline style.

Kết luận

  • Nếu dự án của bạn đang dùng BEM hay các phương pháp phát triển CSS khác và bạn hài lòng với chúng, bạn có thể không cần atomic CSS.
  • Atomic CSS không phải sinh ra là để triệt tiêu BEM, mà bổ sung và giúp bạn làm việc với CSS một cách hiệu quả hơn.
  • Mọi ý kiến thắc mắc gì hãy comment hoặc inbox trực tiếp cho mình nhé. Rất mong sư góp ý của các bạn để cải thiện trọng các bài viết lần sau

@hoangpn - Better every day!


Phạm Ngọc Hoàng

Related Posts

CSS
Seri CSS cơ bản - [CSS Basic 2] Making layout
June 09, 2021
7 min
© 2021, All Rights Reserved.

Quick Links

Liên hệ quảng cáoThông tinLiên hệ

Social Media