Các mixin trong SASS
Bài viết này giải thích về mixin trong SASS.
Chúng tôi sẽ giải thích mixin trong SASS bằng các ví dụ thực tế.
YouTube Video
Các mixin trong SASS
Tổng quan – Mixin là gì?
Mixin là một cơ chế cho phép bạn định nghĩa các tập hợp thuộc tính kiểu dáng thường dùng thành các hàm có thể tái sử dụng, bạn có thể gọi chúng ở bất cứ đâu khi cần thiết. Chúng rất hữu ích để giữ cho các class CSS và nhiều thuộc tính của bạn tuân thủ nguyên tắc DRY (Không Lặp Lại Chính Mình).
Ví dụ: Mixin đơn giản nhất
Dưới đây là ví dụ đơn giản về một mixin tái sử dụng border-radius và box-shadow cùng nhau. Bằng cách gọi mixin này, bạn có thể áp dụng cùng một kiểu dáng cho nhiều phần tử.
1// Simple mixin that applies border-radius and box-shadow
2@mixin card-style {
3 border-radius: 8px;
4 box-shadow: 0 4px 10px rgba(0, 0, 0, 0.12);
5 background: #fff;
6}
7
8.card {
9 @include card-style;
10 padding: 1rem;
11}- Với mixin này, bạn không còn cần phải lặp lại style trực tiếp nữa.
- Gọi nó chỉ cần một dòng:
@include card-style;.
Mixins với các đối số (tham số)
Mixins có thể nhận các đối số, giống như các hàm. Điều này cho phép bạn thay đổi giao diện với cùng một logic. Tiếp theo là ví dụ nơi màu sắc được lấy làm đối số.
1// Mixin with parameters: accepts a color and optional radius
2@mixin colored-box($bg-color, $radius: 4px) {
3 background-color: $bg-color;
4 border-radius: $radius;
5 padding: 0.75rem;
6}
7
8.box-primary {
9 @include colored-box(#007acc);
10}
11
12.box-custom {
13 @include colored-box(#ffcc00, 12px);
14}- Bằng cách cung cấp giá trị mặc định, bạn có thể kiểm soát hành vi khi không truyền đối số.
- Trong ví dụ này, bán kính mặc định được sử dụng và chỉ màu nền bị ghi đè.
Trường hợp sử dụng đối số biến (...)
Khi bạn muốn nhận nhiều giá trị, bạn có thể dùng đối số biến ($args...). Điều này hữu ích cho việc tạo ra các class tiện ích hoặc truyền danh sách fallback.
Nó hữu ích khi bạn cần truyền nhiều kiểu font hoặc nhiều giá trị shadow.
1// Mixin that accepts variable arguments and forwards them to box-shadow
2@mixin multi-shadow($shadows...) {
3 box-shadow: $shadows;
4}
5
6.panel {
7 @include multi-shadow(0 2px 4px rgba(0,0,0,0.08), 0 8px 16px rgba(0,0,0,0.06));
8}- Ở phía gọi mixin, bạn có thể truyền nhiều shadow cách nhau bằng dấu phẩy.
- Bằng cách này, bạn có thể dùng cùng một mixin cho cả shadow đơn giản và phức tạp.
Mixins với @content — Nhận một block
Với @content, một mixin có thể nhận một block style từ phía gọi. Điều này cho phép mixin cung cấp một khung bao chung, trong khi phía gọi xác định chi tiết bên trong.
1// Mixin that sets up a responsive container and yields to caller via @content
2@mixin responsive-container($max-width: 1200px) {
3 margin-left: auto;
4 margin-right: auto;
5 padding-left: 1rem;
6 padding-right: 1rem;
7 max-width: $max-width;
8
9 @content; // place where caller's styles are inserted
10}
11
12.header {
13 @include responsive-container(1000px) {
14 display: flex;
15 align-items: center;
16 justify-content: space-between;
17 }
18}- Ở phía gọi, bạn có thể thêm một block vào
@includeđể chèn style bên trong. - Mẫu này hữu ích cho các khung bố cục như lưới, thẻ và biểu mẫu.
Mixins nâng cao sử dụng điều kiện và vòng lặp
Cấu trúc điều khiển như @if và @for có thể được sử dụng trong mixins. Bạn có thể dùng chúng để tự động tạo các tiện ích và nhóm các thiết lập responsive.
Dưới đây là ví dụ về việc tự động tạo các class tiện ích về chiều rộng.
1@use 'sass:math';
2
3// Mixin that generates width utility classes from a list of fractions
4@mixin generate-widths($fractions) {
5 @each $name, $fraction in $fractions {
6 .w-#{$name} {
7 width: math.percentage($fraction);
8 }
9 }
10}
11
12$widths: (
13 '1-4': 0.25,
14 '1-3': 0.3333,
15 '1-2': 0.5,
16 '3-4': 0.75
17);
18
19@include generate-widths($widths);- Bằng cách truyền vào một bản đồ các phân số mà bạn muốn tạo ở phía gọi, bạn có thể tự động tạo tất cả các lớp tiện ích tương ứng một cách đồng loạt.
- Sử dụng cách tiếp cận này giúp giảm thiểu việc phải định nghĩa kiểu thủ công mà vẫn đảm bảo tính nhất quán cho thiết kế của bạn.
Mixins so với Placeholders (%placeholder)
Trong khi mixin chèn trực tiếp một tập hợp thuộc tính, placeholder được sử dụng với @extend khi kế thừa các kiểu dáng. Mixin có thể tạo ra CSS trùng lặp trong một số trường hợp, nhưng @extend có thể giúp tạo CSS gọn nhẹ hơn trong những tình huống nhất định.
Bằng cách hiểu mục đích và sự khác biệt trong CSS được sinh ra bởi từng phương pháp, bạn sẽ có thể chọn ra cách tiếp cận tối ưu nhất.
1// Placeholder example (for comparison)
2%btn-base {
3 display: inline-block;
4 padding: 0.5rem 1rem;
5 border-radius: 4px;
6}
7
8.btn-primary {
9 @extend %btn-base;
10 background: #007acc;
11 color: #fff;
12}
13
14.btn-secondary {
15 @extend %btn-base;
16 background: #e0e0e0;
17}- Khi bạn sử dụng
@extendcho một placeholder, nhiều selector có thể được gộp lại thành một quy tắc duy nhất, từ đó sinh ra CSS gọn nhẹ hơn. - Ngược lại, vì mixin chèn thuộc tính trực tiếp tại nơi cần thiết, chúng mang lại tính linh hoạt và giúp tránh việc gộp selector ngoài ý muốn.
Các mẫu thực tế thường gặp (Responsive, Tiền tố trình duyệt, v.v.)
Trong thực tế, nên đưa các xử lý thường dùng như tiền tố trình duyệt và responsive vào mixin. Dưới đây là ví dụ kết hợp transform và các thuộc tính tiền tố. Bạn có thể tập trung mã để đảm bảo tương thích trình duyệt, giúp bảo trì dễ dàng hơn.
1// Mixin for transform with vendor prefixes
2@mixin transform($value) {
3 -webkit-transform: $value;
4 -ms-transform: $value;
5 transform: $value;
6}
7
8.icon-rotate {
9 @include transform(rotate(45deg));
10}- Cách sử dụng rất đơn giản và bạn có thể dùng ở bất kỳ đâu, chẳng hạn như
@include transform(rotate(10deg));. - Ngay cả khi tiền tố không còn cần thiết về sau, việc bảo trì cũng trở nên dễ dàng hơn vì chỉ cần cập nhật mixin là có thể áp dụng thay đổi cho toàn bộ mã nguồn.
Ví dụ thực tế: Kết hợp Card và Button
Dưới đây là một ví dụ về cách các kiểu nút được sử dụng trong thẻ được hợp nhất bằng mixin, cho phép chúng thay đổi theo màu của chủ đề.
Cách này tổ chức mẫu 'card + button' thường dùng bằng mixins.
1// Simple mixin that applies border-radius and box-shadow
2@mixin card-style {
3 border-radius: 8px;
4 box-shadow: 0 4px 10px rgba(0, 0, 0, 0.12);
5 background: #fff;
6}
7
8// Mixin for transform with vendor prefixes
9@mixin transform($value) {
10 -webkit-transform: $value;
11 -ms-transform: $value;
12 transform: $value;
13}
14
15// Button mixin with theme and size parameters
16@mixin btn($bg, $color: #fff, $padding: 0.5rem 1rem) {
17 display: inline-block;
18 padding: $padding;
19 background: $bg;
20 color: $color;
21 border-radius: 6px;
22 text-decoration: none;
23 cursor: pointer;
24 @include transform(translateY(0)); // reuse earlier transform mixin
25}
26
27// Card mixin that accepts inner button styling via @content
28@mixin card($gap: 1rem) {
29 @include card-style; // reuse earlier card-style mixin
30 padding: $gap;
31 @content;
32}
33
34.card-feature {
35 @include card {
36 .title { font-size: 1.125rem; margin-bottom: 0.5rem; }
37 .cta {
38 @include btn(#007acc);
39 }
40 }
41}
42
43.card-warning {
44 @include card {
45 .title { font-weight: bold; }
46 .cta {
47 @include btn(#ff6600);
48 }
49 }
50}- Nhờ sử dụng các mixin này, bạn có thể viết các component một cách ngắn gọn.
Chú ý đến hiệu suất và CSS được sinh ra
Vì mixins thêm thuộc tính mỗi lần được gọi, sử dụng nhiều @include cho cùng một quy tắc sẽ làm tệp CSS cuối cùng lớn hơn. Bạn có thể tối ưu bằng cách kết hợp với placeholders và thiết kế component khi cần.
Hơn nữa, các biện pháp sau đây cũng rất hiệu quả.
- Các kiểu thường xuyên sử dụng nên được tạo thành các lớp để tái sử dụng.
- Các mẫu phổ biến nên được nhóm lại bằng cách sử dụng
@content. - Việc tạo các tiện ích phức tạp chỉ nên được thực hiện khi xây dựng.
Mẹo để debug dễ dàng hơn
Khi sử dụng mixin, cũng rất quan trọng để nghĩ ra các phương pháp nhằm cải thiện việc kiểm tra lỗi và bảo trì. Bằng cách sử dụng tên biến rõ ràng và thêm ghi chú trong mixin, bạn sẽ dễ dàng hiểu hơn khi kiểm tra lại mã sau này. Ngoài ra, nếu chức năng trở nên phức tạp, chia nhỏ mixin thành các đơn vị nhỏ hơn sẽ giúp kiểm thử dễ dàng hơn và cải thiện khả năng bảo trì.
Bên cạnh đó, việc bật source map giúp bạn dễ dàng theo dõi mixin nào đã tạo ra CSS nào, từ đó dễ dàng khoanh vùng sự cố.
Dưới đây là ví dụ về một mixin dễ hiểu với các chú thích tài liệu.
1// Example: readable mixin with clear param names and comments
2/// Adds a subtle focus ring for accessibility
3/// $color - ring color
4/// $size - thickness of the ring
5@mixin focus-ring($color: #007acc, $size: 2px) {
6 outline: none;
7 box-shadow: 0 0 0 $size rgba(blue($color), 0.15);
8}- Việc có các chú thích tài liệu được tổ chức như vậy giúp việc chia sẻ và hiểu biết trong nhóm trở nên dễ dàng hơn.
- Vì các chú thích tài liệu SASS có thể được trích xuất tự động bằng các công cụ tương thích, nên chúng cũng rất hữu ích trong việc tạo ra các tài liệu như hướng dẫn về phong cách (style guide).
Tóm tắt
Vì mixins cho phép bạn đóng gói các style thường dùng để tái sử dụng, chúng giúp giảm trùng lặp mã và tăng khả năng bảo trì. Ngoài ra, khi nhiều bộ chọn dùng chung một quy tắc, hãy cân nhắc sử dụng cả mixin lẫn @extend (placeholder). Ngoài ra, dù @content cho phép tách biệt layout và nội dung linh hoạt, nhưng lạm dụng @include có thể làm tệp CSS trở nên cồng kềnh, nên hãy chú ý. Điều quan trọng là tận dụng các đối số, giá trị mặc định và đối số biến để thiết kế mixin tổng quát, dễ mở rộng.
Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.