Gradient CSS chỉ là một dòng mã, và phần lớn thời gian nó trông đúng như bạn nghĩ. Các ngoại lệ thì có thể đoán trước: đường chéo không chạm góc, một màu xám đục ở giữa hai màu tươi, những dải màu phẳng trên nền tối rộng. Mỗi hiện tượng đều có nguyên nhân trong cách trình duyệt tính gradient, và đều có cách sửa đơn giản. Bài này đi qua từng trường hợp với số liệu do phần mã hình học của công cụ tạo gradient CSS tính ra.
Gradient tuyến tính: góc và đường gradient
background: linear-gradient(135deg, #ff512f 0%, #f09819 100%);135deg được đo theo chiều kim đồng hồ từ hướng "lên", nên 0deg chỉ lên trên, 90deg sang phải và 135deg về phía dưới bên phải. Trình duyệt vẽ một đường gradient qua tâm hộp theo góc đó, với độ dài được chọn sao cho màu 0% và 100% rơi đúng vào các góc. Với góc a trong hộp w nhân h, độ dài là |w sin a| + |h cos a|.
Trong banner 1200 × 600, đường gradient 90deg dài 1200 px, bằng chiều rộng hộp. Ở 135deg nó dài 848,5 + 424,3 = 1272,8 px. Các điểm dừng tính theo phần trăm là phần trăm của đường này, nên cùng 50% là 600 px tính từ đầu trong trường hợp này và 636 px trong trường hợp kia.
135deg không phải "to bottom right"
to bottom right không phải một góc cố định. Đặc tả định nghĩa nó sao cho màu ở giữa chạy đúng qua hai góc còn lại, nên với hộp không vuông góc sẽ khác. Trong hình vuông nó là 135deg. Trong banner 1200 × 600 nó là 180 − atan(600 ÷ 1200) = 153,4deg. Nếu thiết kế dùng to bottom right cho ảnh bìa và 135deg cho thẻ, hai đường chéo sẽ không khớp nhau. Hãy dùng một dạng nhất quán: góc khi độ dốc quan trọng, từ khoá khi gradient phải chạm góc bất kể hình dạng.
Điểm dừng màu và cạnh sắc
Mỗi điểm dừng là một màu và một vị trí. Giữa các điểm dừng, màu được nội suy; trước điểm đầu và sau điểm cuối, màu được giữ nguyên. Khi hai điểm dừng trùng vị trí, không còn chỗ để hoà trộn, và bạn có một cạnh sắc:
linear-gradient(90deg, #ff0000 50%, #0000ff 50%)Đó là một hộp nửa đỏ nửa xanh, không cần ảnh. Lặp lại mẫu là có sọc:
repeating-linear-gradient(45deg, #222222 0%, #222222 5%, #ffcc00 5%, #ffcc00 10%)Mẫu từ 0% tới 10% lặp dọc theo đường, tạo ra sọc vàng đen cảnh báo quen thuộc. Công cụ của chúng tôi vẽ gradient lặp theo cùng cách trên canvas khi tải PNG, vì gradient của canvas không tự lặp.
Toả tròn và hình nón
Gradient toả tròn lan ra từ một tâm. Kích thước mặc định là farthest-corner: điểm dừng 100% rơi vào góc xa tâm nhất. Với tâm ở 600, 300 trong hộp 800 × 400, đó là hình tròn bán kính √(600² + 300²) ≈ 670,8 px; nếu là hình elip đặt giữa cùng hộp thì hai bán kính là 565,7 và 282,8 px. closest-side khiến gradient kết thúc ở cạnh gần nhất, đúng thứ bạn cần cho một vệt sáng không được tràn ra:
radial-gradient(circle closest-side at 30% 40%, #ffffff 0%, #000000 100%)Gradient hình nón thì xoay quanh tâm. Điểm dừng cứng biến nó thành biểu đồ tròn mà không cần thư viện nào:
conic-gradient(#e63946 0%, #e63946 40%, #457b9d 40%, #457b9d 75%, #2a9d8f 75%, #2a9d8f 100%)Đó là ba lát 40%, 35% và 25%, bắt đầu từ trên cùng và chạy theo chiều kim đồng hồ. Biểu đồ dựng theo cách này chỉ là hình ảnh với công nghệ hỗ trợ người khuyết tật, nên hãy ghi các con số bằng chữ nữa.
Vùng xám ở giữa
Mặc định, CSS hoà màu trong không gian sRGB, từng kênh một. Xanh lam #0000ff và vàng #ffff00 đối nghịch ở mọi kênh, nên ở giữa trình duyệt tính ra (127,5; 127,5; 127,5): một màu xám trung tính, phẳng lì. Hai màu gần bổ sung nào cũng bị như vậy ở mức độ nhẹ hơn, đó là lý do gradient tím sang xanh lá làm vội trông bẩn ở giữa.
Hai cách sửa:
- Thêm một điểm dừng ở giữa với màu do bạn chọn, ví dụ xanh nhạt hoặc xanh lá giữa xanh lam và vàng. Cách này chạy trên mọi trình duyệt.
- Nội suy trong không gian màu khác. CSS Color 4 cho phép viết
linear-gradient(in oklab, #0000ff, #ffff00), được các trình duyệt lớn hỗ trợ ở phiên bản hiện tại. Trong OKLab, điểm giữa đó tính ra khoảng#6cabc7, một màu xanh da trời dịu thay vì xám. Công cụ của chúng tôi viết gradient sRGB thông thường, nên nếu muốn hãy tự thêm phầnin oklab, và giữ phiên bản không có nó làm dự phòng cho trình duyệt cũ.
Mờ dần sang trong suốt
Làm một màu mờ dần sang transparent từng tạo ra vệt tối, vì transparent là màu đen có độ đục bằng 0 và một số trình duyệt cũ trộn luôn cả màu đen vào. CSS hiện nay nội suy theo màu nhân trước (premultiplied): màu được nhân với độ đục trước khi trộn. Ở giữa đường từ đỏ đục sang transparent, kết quả là đỏ với độ đục 50%, (255, 0, 0, 0,5), chứ không phải đỏ sẫm (127,5, 0, 0, 0,5). Ảnh PNG của công cụ cũng theo đúng quy tắc này, nên khớp với CSS.
Vệt sọc (banding)
Mỗi kênh của một điểm ảnh thường có 256 mức. Gradient từ #1e1e1e tới #2a2a2a chỉ trải qua 12 bước, nên trên ảnh bìa rộng 1200 px chỉ có 13 sắc xám khác nhau, mỗi sắc là một dải rộng khoảng 92 px. Trên màn hình tốt, những dải đó hiện rõ thành sọc. Gradient tối và tinh tế là trường hợp tệ nhất, và nén ảnh chụp màn hình của nó sang JPEG còn làm tệ hơn.
Cách sửa: mở rộng khoảng màu, rút ngắn khoảng cách, phủ thêm một lớp nhiễu mờ, hoặc chấp nhận dùng màu phẳng. Một số trình duyệt và GPU có làm nhiễu (dither) gradient, nhưng không thể trông cậy vào điều đó.
Những lỗi thường gặp
- Trộn
to bottom rightvới135degvà chờ đợi cùng một đường chéo. - Hoà hai màu bổ sung mà không có điểm dừng giữa, rồi thắc mắc màu xám từ đâu ra.
- Đặt chữ lên gradient mà không kiểm tra độ tương phản ở cả hai đầu. Hãy kiểm tra điểm sáng nhất và tối nhất bằng công cụ kiểm tra tương phản màu; bài giải thích tỉ lệ tương phản WCAG nói về các ngưỡng.
- Gradient tối, tương phản thấp, trải dài trên màn hình lớn, dễ bị vệt sọc.
- Quên đặt
background-colordự phòng cho trường hợp hiếm gradient không phân tích được, nhưin oklabtrên trình duyệt chưa hỗ trợ.
Hãy dựng gradient trong công cụ tạo gradient CSS, sao chép CSS, hoặc tải ảnh PNG đúng kích thước bạn cần. Bản xem trước dùng chính đoạn CSS bạn sao chép.