CSS Architecture: First steps
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 selectors để 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 họ. Chúng dễ dàng để nắm bắt và bắt đầu á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 ...
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 selectors để 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 họ. Chúng dễ dàng để nắm bắt và bắt đầu á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 đề.
Ví dụ với tính năng cascading, cho phép các thuộc tính được ghi đè bởi các selectors khác theo thứ tự nó được viết trong file hoặc bởi selector specificity. Cũng như những eletement thừa hưởng các thuộc tính từ cha mẹ của họ trên DOM. Nếu không có sự tổ chức thích hợp, có thể dẫn đến việc không kiểm soát được và gây sự lộn xộn. => Đây là lúc chúng ta cần một kiến trúc.
Kiến trúc của một CSS là gì?
Một kiến trúc CSS mang lại lý do để sáng tác ra CSS. Hãy tưởng tượng nó như là một tập hợp các hướng dẫn và phương pháp tốt nhất để giúp các developers viết code, mà nó có thể maintainable, flexible, linh hoạt và có thể tái sử dụng được. Chúng tôi đạt được điều đó bằng cách áp dụng modular, thúc đẩy tổ chức, và sử dụng các quy ước vào codebase. Chúng ta sẽ xem xét làm thế nào để áp dụng những nguyên tắc này với 3 bước cơ bản.
Modularity là một khái niệm cốt lõi. Không chỉ là trên code level mà là còn trên mặt design => Page-based CSS sẽ không còn phù hợp với nhu cầu xây dựng các sản phẩm linh hoạt và có khả năng mở rộng. Làm việc với các reusable components là một con đường để đi.
Trên một kiến trúc CSS, modularity có thể áp dụng trên nhiều cấp độ khác nhau. Ba bước cơ bản để bắt đầu cấu trúc lại CSS của bạn theo các cách đó là:
- Chia nhỏ code và tách chúng bằng cách scope
- Code các components một cách độc lập và dễ dàng đóng gói
- Đặt tên cho các CSS selectors theo mục đích và liên hệ chúng với nhau
Chúng ta sẽ cùng nhau bắt đầu
1. Tách và phân loại mã code của bạnĐể giữ lại kiến trúc của modular, điều quan trọng là cần chia nhỏ code của bạn ra thành những phần nhỏ. Chia nhỏ thành nhiều files làm cho code của bạn dễ đọc, dễ theo dõi hơn. Để làm điều đó, một tiền xử lý css như Sass, LESS hoặc Stylus là một con đường để đi. Preprocessors tăng cường sự hiểu biết về CSS, giới thiệu các tính năng mới như variables, mixins và nhiều hơn thế nữa. Để làm việc với các file riêng biệt, code của bạn sẽ sẽ được chia thành các partials và improted vào một tập tin như là main.scss, nó sẽ compile mọi thứ ra một file css duy nhất. Dưới đây là ví dụ về một file css.
Bây giờ là thời gian để phân loại từng mã code theo phạm vi của nó trong project. Một trong những phương pháp đầu tiên để phân loại là SMACSS(Scalable and Modular Architecture for CSS). Các layers được đề xuất bởi SMACSS là Base, Layout, MOdule, State và Theme. ITCSS (Scalable and Maintainable CSS Architecture) là một mở rộng của chủ đề này, nó giới thiệu các layers khác như là Settings, Trunps. MVCSS(Modular View CSS) có một cách tiếp cận tương tự nhưng mà với các quy ước đặt tên khác nhau. Bạn không cần làm theo các phương pháp một cách nghiêm ngặt. Hãy học chúng thông qua các ví dụ và tìm những gì phù hợp nhất đối với dự án của bạn. Theo quan điểm của tôi, tách kiến trúc của bạn vào Settings, Base, Layout và Components là một khởi đầu tốt. Settings là nơi chứa các tập tin configuration, như các variables (colors, sizing, các định nghĩa về font ...) và các helpers (functions. mixins....) sẽ được lưu trữ. Base layer sẽ chứa các thiết lập lại và nguyên tắc unclassed HTML. Layout lưu trữ cấu trúc của các classes mà nó giữ các components ở trong page - girds và containers. Và cuối cùng, Components: là core của kiến trúc và design team.
2. Định nghĩa Components của bạnTôi đã cân nhắc components thành core của một kiến trúc CSS là bởi vì đó là nơi mà hầu hết các mã code sẽ sống. Đó là những mô hình tái sử dụng mà cấu thành nên giao diện người dùng như là các buttons, accordions hoặc modals.
Mỗi components được đóng gói vào file riêng của mình. Vì những lý do liên quan đến tính thống nhất, đó là một best practice để sử dụng cùng tên cho file và main selector. Ví dụ:
Đôi khi, khi bạn định nghĩ một components, bạn sẽ tự hỏi chính mình rằng nó nên là một components độc lập hay là một phần của một block lớn. Để trả lời câu hỏi đó, hãy search trong product hoặc website của bạn về việc lặp lại partent đó. Nếu nó được sử dụng ở những bối cảnh khác nhau thì hãy đưa nó ra thành component riêng.
3. Áp dụng các quy ước về việc đặt tênHãy nhớ rằng: Chúng tôi muốn kiến trúc của chúng tôi truyền đạt được ý nghĩa và theo một tổ chức. Sử dụng một quy ước đặt tên sẽ giúp chúng tôi đạt được điều đó. Một pattern như là BEM (Block, Element, Modifier) sẽ làm sáng tỏ ý định và mối quan hệ giữa một component (the Block) và các elements của chính nó cũng như tăng cường khả năng dự đoán khi so sánh với các thành phần khác. Ý tưởng của BEM là tên follow theo cấu trúc:
- Block: các component của chính nó
- Elements: các bộ phận bên trong của components
- Modifiers: các biến thể của block hoặc element
Hãy xem các ví dụ sau:
- Block:
.blog-post { … }
Bao gồm cả blog post đó
- Element
.blog-post__excerpt { … }
Một đoạn trích (excerpt) trong blog. Để biểu thị mối quan hệ giữa Element và Block, BEM đã sử dụng 2 dấu gạch dưới.
- Modifier
.blog-post--small { … }
Một biến thể trong block sẽ làm cho nó nhỏ hơn. Để biểu thị mối quan hệ giữa Modifier và Block, BEM sử dụng 2 dấu gạch ngang.
Trên phương diện về organizational level thì phương pháp này thúc đẩy tính thống nhất và khả năng dự đoán trên Component layer. Trên phương diện technical level, nó giúp giảm selector chuyên biệt và tăng khả năng phân tách CSS từ cấu trúc DOM (thúc đẩy việc tái sử dụng). Hãy cùng xem ví dụ dưới:
section.container div.grid div p { … }
Trong hoàn cảnh này, trình duyệt phải check tất cả các điều kiện để áp dụng vào selector:
Is there a <p> inside a <div> inside another <div> with a class of .grid inside a <section> with a class of .container? If so, style this.
Các phương pháp tiếp cận dựa theo BEM class-based là chính xác và ý nghĩa hơn. Trình duyệt chỉ cần check cho class blog-post__excerpt trên DOM => sẽ có hiệu quả về performent hơn. Nó có thể được tái sử dụng và các developers có thể giả định rằng nó là một phần của component .blog-post.
Kết luận
Những lời khuyên này chỉ là thời điểm bắt đầu, là basic cơ bản và bước đầu cho các dự án về structuring CSS. Để tìm hiểu thêm về đề tài này tôi khuyên bạn nên xem những danh sách bài này. Và có rất nhiều tài liệu trên mạng khác mà các bạn có thể tham khảo.