Liquid Glass được hiện thực bằng CSS
(atlaspuplabs.com)- Cách tái tạo các hiệu ứng cốt lõi của ngôn ngữ thiết kế Liquid Glass mà Apple công bố tại WWDC25 bằng cách kết hợp CSS và bộ lọc SVG
- Triển khai từng bước bằng CSS/SVG nhiều lớp khác nhau để mô phỏng chất liệu kính thật như Specular Highlights, Blur, Color Filter, Refraction, Edge/Ripple Distortion, Chromatic Aberration
- Việc hiện thực các hiệu ứng chính sử dụng các kỹ thuật CSS·SVG nâng cao như backdrop-filter, box-shadow, SVG DisplacementMap, Turbulence, ColorMatrix, Offset, Blend
- Khả năng tương thích trình duyệt chủ yếu xoay quanh Chrome; trên Safari/Firefox, bộ lọc SVG không hoạt động nên chỉ áp dụng Blur·Shadow
- Với các hiệu ứng càng phức tạp thì mức sử dụng GPU càng lớn, và nếu lạm dụng trên toàn bộ UI có thể làm giảm hiệu năng, nên chỉ nên dùng ở các vùng trọng tâm
Liquid Glass là gì?
- Đây là ngôn ngữ thiết kế mới nhất của Apple, hướng tới các hiệu ứng đồ họa cao cấp mô phỏng phản xạ/khúc xạ ánh sáng, biến đổi màu sắc, chiều sâu như kính thật
- Nó được dùng để tăng cảm giác chiều sâu và độ sống động cho các thành phần UI, với đặc trưng là hình ảnh mượt mà và gợi cảm giác chạm mang tính vật lý
Các lớp hiệu ứng chính và cách triển khai
1. Specular Highlights (ánh phản chiếu trên kính)
- Thêm highlight ở viền kính để nhấn mạnh chiều sâu và cảm giác khối
- Chồng nhiều inset box-shadow của CSS để thể hiện cảm giác ánh sáng phản xạ theo từng góc
box-shadow: inset 10px 10px 20px rgba(153, 192, 255, 0.1), inset 2px 2px 5px rgba(195, 218, 255, 0.2), inset -10px -10px 20px rgba(229, 253, 190, 0.1), inset -2px -2px 30px rgba(247, 255, 226, 0.2); - Tham khảo [Fresnel Effect] để điều chỉnh cường độ phản xạ ánh sáng một cách tự nhiên
2. Blur (làm mờ nền)
- Dùng backdrop-filter: blur(20px); để chỉ áp dụng blur cho nội dung phía sau kính
- Hiệu ứng chỉ áp dụng lên nội dung nền, không phải chính bản thân phần tử
3. Color Filter (nhấn màu)
- Áp dụng thêm các backdrop-filter như contrast(80%) saturate(120%) để tạo màu sắc rõ nét thông qua tăng độ bão hòa, giảm độ tương phản của nội dung phía sau kính
backdrop-filter: blur(20px) contrast(80%) saturate(120%);
4. Mô phỏng khúc xạ (Refraction)
-
Hiệu ứng khúc xạ khiến nền phía sau bị bẻ cong theo bề mặt cong của kính khó có thể triển khai chỉ bằng CSS, nên được hiện thực bằng cách kết hợp với bộ lọc SVG
-
Displacement Map: sử dụng gradient của SVG để tạo distortion map (Identity Map) trong đó pixel bị nén ở mép và giãn ra ở phần trung tâm
- Gradient đỏ/xanh trong ví dụ SVG xác định lượng dịch chuyển pixel theo trục X/Y
- Điều chỉnh ramp của gradient để thiết kế mẫu nén ở viền và giãn ở trung tâm
- Chuyển SVG thành Data URL để tải bằng feImage, rồi dùng cho biến đổi tọa độ trong feDisplacementMap
-
Ripple Distortion: kết hợp feTurbulence (texture nhiễu) và feDisplacementMap bổ sung để mô tả cả những gợn sóng nhỏ trên bề mặt kính
-
Chromatic Aberration (quang sai sắc): kết hợp feColorMatrix, feOffset, feBlend để tách và dịch từng kênh RGB rồi trộn lại, mô phỏng hiện tượng tán sắc ánh sáng quan sát được ở kính thật
Cách áp dụng hiệu ứng CSS/SVG
- Sau khi định nghĩa SVG filter, áp dụng nó vào phần tử DOM bằng filter: url(#filterId);
- Chuỗi filter kết hợp tất cả hiệu ứng có thể tái tạo đồng thời chất cảm của tấm kính thật, độ méo ánh sáng và biến đổi màu sắc
Lưu ý về tương thích và hiệu năng
- SVG displacement filter chỉ được hỗ trợ đầy đủ trên Chrome. Trên Safari, Firefox... hiệu ứng sẽ bị giới hạn (chỉ còn Blur/Shadow)
- Khi có nhiều thành phần kính hoặc áp dụng animation, tải GPU sẽ lớn và hiệu năng render giảm
- Trên thực tế, phù hợp nhất là chỉ dùng cho một số UI cần nhấn mạnh như Hero/Feature area
Tham khảo và ghi công
- Cách triển khai này dựa trên bài viết của Smashing Magazine, "A Deep Dive Into The Wonderful World Of SVG Displacement Filtering" và tài liệu chính thức về Apple Liquid Glass
- Điểm cốt lõi là tận dụng kết hợp các công nghệ web hiện đại như SVG displacement, CSS backdrop-filter, box-shadow
3 bình luận
Phần người này triển khai có vẻ tự nhiên hơn đấy
https://v0.dev/chat/dynamic-frame-layout-1VUCCecq7Uy
Cái này có vẻ không áp dụng được trên Safari.
Triển khai trên web vẫn còn hơi gượng gạo nhỉ haha