Nếu bạn từng bị giới hạn bởi việc resort vào tiền xử lý như Sass hoặc chèn thêm các hàm trong JavaScript để xử lý các kiểu CSS phức tạp.
Thì giờ đây có một hướng tiếp cận mới: sử dụng phần mở rộng của CSS thuần để đưa logic động vào stylesheet — đúng vậy, chỉ với CSS.
Trong bài viết này, chúng ta sẽ cùng tìm hiểu:
- Tại sao logic động trở nên cần thiết trong styling.
- Làm thế nào phần mới của CSS – ví dụ giả định là
@function– có thể thay thế các đoạn mã Sass/JS trước đó. - Các ví dụ ứng dụng thực tế: chuyển đổi đơn vị (
rem), kiểu chữ linh hoạt, màu & độ tương phản. - Những lưu ý và giới hạn hiện tại cho giải pháp này.
Tại sao chúng ta muốn logic trong CSS?
Khi phát triển giao diện web, có rất nhiều tình huống mà bạn phải lặp lại logic trong Sass hoặc JavaScript để đạt được styling linh hoạt như:
- Chuyển đơn vị từ px sang rem/h để hỗ trợ kích thước chữ linh hoạt.
- Thiết lập động màu sắc dựa trên trạng thái (được kích hoạt, hover, chế độ tối/sáng).
- Điều chỉnh tỉ lệ dòng (line-height), khoảng cách margin/padding phụ thuộc vào font-size hoặc viewport.
- Viết lại các mixin hoặc hàm trong Sass chỉ để tái sử dụng cùng logic – khiến stylesheet trở nên nặng và khó bảo trì.
Cho tới nay, giải pháp phổ biến là: viết hàm trong Sass, hoặc dùng JS để tính toán và gán biến CSS. Ví dụ: dùng Sass @function convertRem($px) hoặc JS window.getComputedStyle(...).setProperty(...). Nhưng cả hai cách đều có nhược điểm: phụ thuộc vào build-time, hoặc runtime (JS) — dẫn tới chuyện giữ synchronisation và phức tạp hơn trong bảo trì.
Nếu CSS có thể tự mình hỗ trợ một số logic như “nếu giá trị > x thì …”, “chuyển đổi đơn vị”, “chọn màu tương phản” mà không cần Sass hay JS — đó sẽ là bước tiến thú vị.
Giới thiệu function trong CSS
Giả sử rằng CSS chuẩn trong tương lai hoặc bằng bản mở rộng có thêm chỉ thị như:
@function convertRem(px) {
return px / 16 * 1rem;
}
h1 {
font-size: convertRem(24);
}
Tức là, một hàm CSS gốc (native) có thể nhận tham số, thực hiện tính toán, và trả về giá trị CSS hợp lệ. Nhờ đó bạn giảm phụ thuộc vào Sass mixin hoặc JS setup.
Những điểm nổi bật:
- Không cần đặt logic vào Sass/JS riêng — bạn viết trực tiếp trong CSS.
- Giảm độ phức tạp build-system.
- CSS trở nên có khả năng “phép toán” nhẹ nhàng, linh hoạt hơn — tốt hơn cho maintainability.
- Có khả năng tái sử dụng cao khi bạn viết các hàm/logic chung trong CSS.
Tuy nhiên — còn có nhiều điều cần lưu ý: việc hỗ trợ trình duyệt, khả năng thay thế hoàn toàn các mixin/JS hiện tại, và hiệu năng.
Một vài ví dụ ứng dụng CSS function
Chuyển đổi đơn vị linh hoạt
Thay vì viết trong Sass:
@function rem($px) {
@return $px / 16 * 1rem;
}
h2 { font-size: rem(32); }
Với @function CSS bạn có thể:
@function toRem(px) {
return px / 16 * 1rem;
}
h2 {
font-size: toRem(32);
}
Khi giá cơ sở thay đổi (ví dụ root font-size = 18px), bạn chỉ cần điều chỉnh logic trong hàm CSS là xong, mà không phải chỉnh nhiều chỗ.
Kiểu chữ linh hoạt (fluid typography)
Khi bạn muốn font-size tăng/giảm theo viewport, thay vì dùng JS hoặc Sass media queries, bạn có thể viết:
@function fluid(minSize, maxSize, minScreen, maxScreen) {
return calc(
minSize + (maxSize - minSize) *
((100vw - minScreen) / (maxScreen - minScreen))
);
}
h3 {
font-size: fluid(1.2rem, 2rem, 320px, 1200px);
}
Điều này cho phép h3 thay đổi từ 1.2rem ở màn hình nhỏ tới 2rem ở màn hình cực lớn — tất cả chỉ trong CSS.
Định màu & độ tương phản động
Bạn có thể viết hàm trong CSS để chọn màu sáng/tối dựa trên màu nền:
@function contrastColor(bgColor) {
// giả định logic: nếu bgColor quá tối thì trả màu trắng, ngược lại trả màu đen
@if (lightness(bgColor) < 50%) {
return white;
} else {
return black;
}
}
.button {
background: #1a1a1a;
color: contrastColor(#1a1a1a);
}
Như vậy bạn không cần JS để tính toán “màu chữ nên là mấy” dựa vào nền.
Lưu ý và giới hạn
- Hỗ trợ trình duyệt: Nếu đó là một tính năng mới/đang thử nghiệm, nhiều trình duyệt có thể chưa hỗ trợ đầy đủ => cần kiểm tra fallback.
- Khi logic quá phức tạp hoặc phụ thuộc vào trạng thái runtime (ví dụ: user setting, thời gian thực) — vẫn cần JS.
- Nếu có nhiều hàm/phép tính phức tạp, stylesheet có thể trở nên khó đọc hơn — nên có tài liệu hoặc đặt tại file riêng.
- Hệ sinh thái hiện tại (với Sass, PostCSS, build tools) đã rất phong phú — việc chuyển sang CSS-native logic cần cân nhắc lợi/hại.
- Tính năng mới có thể chưa được tiêu chuẩn hóa — nên xác định rõ “beta” hay “experimental”.
Kết luận
Việc đưa logic động vào CSS mà không phụ thuộc Sass hay JavaScript mở ra một hướng đi rất thú vị cho frontend: stylesheet thông minh hơn, ít phụ thuộc hơn vào công cụ bên ngoài, và khả năng tái sử dụng cao hơn.
