Cơ bản về CSS Preprocessor - Tại sao bạn nên sử dụng CSS Preprocessor

cover

LESS và SASS là 2 CSS Preprocessor (tiền xử lý CSS) nổi bật nhất hiện nay (mình cũng chỉ biết có 2 cái này). Nếu bạn là 1 front-end developer, hoặc ít nhất, bạn là người yêu thích CSS - và, bạn chưa sử dụng CSS Preprocessor thì có lẽ sau bài viết này, bạn nên làm quen với nó.

Trong bài viết này, mình chủ yếu nói về SASS (mặc định là SASS luôn). Cú pháp của SASS và LESS tương tự nhau, cho nên biết 1 cái bạn cũng gần như là biết cái còn lại.

Tất nhiên yêu cầu là bạn phải biết CSS nhen.

cài đặt

Cài đặt trình biên dịch cho SASS. Bạn có thể dùng trình biên dịch online hoặc js biên dịch. Nhưng để thuận tiện khi làm việc thì tốt hơn hết là cài đặt nó.

SASS - Syntax Awesome Stylesheet

Một vài chú ý:

Cần phân biệt giữa S-C-SS và S-A-SS
  • SASS là bộ tiền xử lý CSS (CSS Preprocessor).
  • SCSS là phần mở rộng của 1 tập tin SASS. Ví dụ: styles.scss
  • Có 2 cú pháp viết SASS, đó là SASS (*.sass) và SCSS (*.scss). Cú pháp của SCSS gần giống với CSS, còn SASS thì bỏ các dấu ';', '{', '}'.... Bản thân mình thấy cú pháp SASS khá khó đọc, chủ yếu là do mình quen với CSS rồi. Tốt nhất là cứ sử dụng cú pháp SCSS.

biên dịch

Biên dịch là chuyển từ 1 file *.scss thành *.css. Mình sẽ nói đến cách biên dịch bằng trình biên đã cài đặt ở trên.

Bước 1: Tạo 1 file style.scss. Mở bằng 1 text editor bất kỳ và gõ 1 đoạn css đơn giản

scss demo

Bước 2: Mở cmd ngay tại thư mục chứa (giữ shift + chuột phải > Open command window here) và gõ lệnh build

build scss

Ý nghĩa: build file input style.scss thành file output style.css. Bạn có thể đặt tên file output bất kỳ, ví dụ như my-output-style.css.

Và kết quả sau khi build xong

scss build result

Bạn không thể cứ mỗi lần thay đổi scss là mở cmd và build lại. Thay vào đó, bạn chỉ cần ra lệnh cho trình biên dịch, mỗi khi có sự thay đổi ở file input, hãy tự động build cho ta. Đơn giản là bạn chỉ cần thêm tham số --watch vào lệnh biên dịch.

scss --watch style.css:style.css

Và bắt đầu, phần hấp dẫn nhất...

SCSS cũng là CSS, do đó, mọi cú pháp hợp lệ của CSS cũng hợp lệ cho SCSS.

Biến (Variables)

Biến, 1 phần làm nên điều tuyệt vời của scss (CSS Preprocessor nói chung). Hãy xem 1 ví dụ của biến sau đây:

Và bạn thử đoán xem kết quả sẽ ra sao? Tất cả những nơi có sử dụng biến sẽ được thay thế bằng giá trị biến đã khai báo lúc đầu:

Thật tuyệt vời phải không?! Bạn không cần phải ghi nhớ giá trị của màu xanh nữa, và mỗi lần thay đổi, bạn chỉ cần đổi 1 chỗ, tất cả những chỗ khác sẽ tự động đổi theo.

Vậy, giá trị của biến có thể là những gì? Yeah, nó có thể là bất cứ giá trị nào của 1 thuộc tính css, từ số, px, chuỗi...

@mixin

Lại là một điều tuyệt vời nữa của scss (vì nội dung bài viết đề cập tới scss nhen, chứ những CSS Preprocessor khác vẫn có như thường). Bạn có thể hình dung mixin như là 1 function, khai báo 1 lần và sử dụng nhiều lần. Tất nhiên, bạn có thể truyền tham số cho mixin y hệt 1 function vậy

Ví dụ 1: mixin không có tham số đầu vào. Cú pháp của mixin đơn giản

    @mixin name-of-mixin { /* styles */ }

Và sử dụng mixin cũng đơn giản không kém

    @include name-of-mixin;

Tất nhiên là chả ai lại viết cái mixin pull-left như ví dụ, vì nó chả có gì để mà phải chia ra dài dòng phức tạp vậy. Bạn chỉ nên viết mixin khi nào bạn muốn dùng đi dùng lại nhiều lần, nhưng tham số khác nhau. Đó là cách để bạn viết DRY (Don't Repeat Yourself) css. Ví dụ thứ 2 là 1 trường hợp sử dụng mixin hợp lý

Trong VD2, khai báo 1 mixin dùng để tạo border cho thẻ. Bạn có thể tùy chọn màu sắc và kích thước cho border, do đó mình truyền 2 tham số màu và độ dày cho mixin. Mình cũng sử dụng giá trị mặc định cho nó, khi đó nếu không truyền giá trị cho mixin, giá trị mặc định sẽ được sử dụng (đơn giản mà phải không :] )

Và đây là kết quả sau khi build, có đúng như dự đoán của bạn không? :))

Bạn cũng chú ý rằng, có 2 cách comment trong scss. Cách comment của css /**/ sẽ được build ra kết quả, cách comment của js // (gọi cho dễ hình dung) sẽ được lược bỏ. Từ đó bạn có thể lựa chọn cách comment để có thể ghi chú tốt nhất.

Extend

Tương tự như như lập trình, extend là kế thừa 1 đoạn css đã được định nghĩa trước đó. Dùng extend để có thể mở rộng css 1 cách đơn giản mà không phải lặp lại. Có thể nói đây mới diễn tả chính xác hơn về định nghĩa DRY css.

Định nghĩa 1 class .box. Bạn muốn 1 .box đỏ, chỉ cần sử dụng lại .box và thêm background cho box đỏ, tương tự với box xanh/đen/vàng...

Vậy quan hệ extend sau khi build sẽ ra sao?

SCSS sẽ build selector cha (selector được extend) và selector con (selector dùng extend) vào cùng 1 nhóm -> giúp output tránh lặp đi lặp lại cùng 1 nội dung. Những nội dung thêm mới sẽ được viết riêng ra của selector thêm mới đó.

Vậy bạn muốn chỉnh sửa 1 thuộc tính của selector cha thì sao (1 cách nói). Đơn giản, ví dụ bạn muốn box đỏ có width = 120px?

Với kết quả như thế này, theo quy luật của css, những style viết sau sẽ override lên style viết trước. Và dĩ nhiên, kết quả sẽ như mong đợi.

@mixin và extend

Có thể bạn sẽ hơi bối rối giữa 2 cái này, khi nào thì dùng mixin, khi nào thì dùng extend. Một vài ý kiến sau đây sẽ giúp bạn:

  • mixin sẽ không được build ra, extend thì có (thực chất là lớp được extend - .box - cũng chỉ là 1 class bình thường nên tất nhiên là được build rồi.) => Sử dụng extend nếu bạn muốn "mở rộng - extend" 1 selector bằng các thuộc tính mới.
  • Sử dụng mixin nếu bạn muốn chỉnh sửa 1 vài giá trị của thuộc tính, hoặc không cần chỉnh sửa mà chỉ sử dụng nhiều lần.

nested selector

Selector lồng nhau, đây là tính năng làm cho css của bạn dễ bảo trì và sửa chữa hơn bao giờ hết. Đối chiếu 2 cách viết sau:

Đây là cách viết cha-ông-ta-để-lại (ví dụ thôi nhé, mình chả viết style 1 hàng đâu). Ban đầu thì có vẻ đẹp đấy, nhìn gọn đấy. Nhưng nếu như nó dài loằng ngoằng ra thì sao? hoặc nếu như bạn muốn chen giữa các selector đó thì sao? Bạn phải sửa từng cái 1, rất mất thời gian và công sức.

Còn đây là cách viết lồng nhau của scss. Bạn thấy sao? Có thể bạn chưa quen và nó rất khó nhìn, nhưng hãy cố gắng đi, và hãy xem:

  • Nếu bạn muốn thêm class .menu cho ul, bạn chỉ cần thêm 1 chỗ duy nhất. Sau này bạn muốn đổi tên class là .nav, bạn cũng chỉ cần đổi 1 chỗ duy nhất.
  • Nếu bạn muốn biết ul chứa những gì? Rất dễ nhìn có phải không?!
  • Và nếu bạn muốn xen giữa li và a 1 selector khác thì sao? Cũng chả có gì phức tạp.

Tất nhiên là kết quả build ra cũng sẽ giống như trên thôi, nhưng mấu chốt là, css của bạn sẽ dễ dàng quản lý hơn rất nhiều nếu như viết lồng nhau.

Một vài chú ý đối với selector lồng - selector '&'

  • '&' tham chiếu tới selector cha gần nhất của selector hiện tại.
  • ul li là quan hệ tổ tiên - con cháu. Nếu muốn viết ul > li thì trong selector lồng bạn phải dùng '&

Với cách viết như trên, kết quả sẽ là

Bạn có hình dung ra được không?

  • Với cách viết '& > .child' sẽ build ra '.parent > .child'
  • Với cách viết '&.parent-ex' sẽ build ra '.parent.parent-ex'
  • Với cách viết '&:hover' sẽ build ra '.parent:hover'

Tóm lại, & sẽ tham chiếu tới thằng cha. Nếu có khoảng trắng và selector nối (+, ~, > ...) thì sẽ là cha trực tiếp, con liền kề...y hệt css

Nếu không có khoảng trắng thì sẽ là 2 selector trong cùng 1 phần tử

Trong less thì & chỉ đơn giản có thế. Nhưng trong scss thì & có nhiều sức mạnh hơn. Tuy nhiên, chỉ cần biết 'sơ sơ' đến nhiêu đây là đủ. Biết nhiều nguy hiểm :)) - hoặc vào trang chủ của sass mà coi chi tiết.

Đi ngủ, mai viết tiếp ^^

Comments

  1. Cho em hỏi, giao diện Blogspot này anh thiết kệ ạ :D

    ReplyDelete
    Replies
    1. :v yep, và chuẩn bị ra mắt 1 version mới nữa

      Delete

Post a Comment

Popular posts from this blog

Căn giữa thẻ div trong thẻ div

Gỡ bộ Visual Studio ra khỏi máy tính