box-shadow là thuộc tính CSS thêm bóng đổ, hiệu ứng phát sáng và vùng lõm bên trong cho bất kỳ phần tử nào. Đây là công cụ mạnh nhất để tạo cảm giác *độ cao* cho một thiết kế phẳng: thẻ nổi lên khỏi trang, hộp thoại lơ lửng trên nội dung, nút bấm trông như có thể nhấn xuống.
Bí quyết là một bóng *đẹp* hiếm khi chỉ có một lớp. Bóng ngoài đời thực mềm hơn và có ánh sáng phản xạ xung quanh: phần lớn design system (Material, iOS, Tailwind) xếp 2 hoặc 3 khai báo box-shadow với offset và độ mờ khác nhau. Viết tay những dòng đó khá mất công; một công cụ tạo bóng giúp bạn chỉnh từng lớp bằng mắt và xem ngay kết quả kết hợp.
Công cụ của Coddy hỗ trợ số lớp không giới hạn, cả bóng *bên ngoài* lẫn *inset*, màu và độ mờ riêng cho từng lớp, cùng các mẫu có sẵn cho những kiểu phổ biến nhất: thẻ nhẹ nhàng, bóng sắc nét, phát sáng màu thương hiệu, vùng lõm inset và bề mặt neumorphic. Sao chép CSS và dán thẳng vào stylesheet: không cần tải lên, không cần tài khoản, không có watermark.
Những điều cần biết về CSS box-shadow
Cú pháp là box-shadow: [inset] <x> <y> <blur> <spread> <color>. inset đặt bóng *bên trong* phần tử; không có nó thì bóng nằm bên ngoài.
*Blur* làm mềm cạnh bóng: giá trị càng lớn thì bóng càng lan tỏa. *Spread* phóng to hoặc thu nhỏ bóng trước khi áp dụng blur (giá trị âm kéo bóng vào trong, hữu ích để tạo hiệu ứng nổi nhẹ).
Nhiều bóng được phân tách bằng dấu phẩy và xếp từ sau ra trước theo thứ tự viết: bóng khai báo đầu tiên nằm *bên dưới* các bóng sau trong kết quả cuối cùng.
Dùng rgba() (hoặc hsla()) cho màu để chỉnh độ mờ riêng từng lớp. Màu đen thuần với độ mờ thấp trông như bóng xám mềm; màu đen thuần với độ mờ tối đa trông như một mảng cắt cứng.
box-shadow được GPU kết hợp và là một trong những cách nâng cấp giao diện rẻ nhất. Nó không ảnh hưởng đến bố cục: phần tử giữ nguyên kích thước và vị trí ban đầu.
Cách thiết kế một box-shadow
1
Bắt đầu từ một mẫu có sẵn
Chọn mẫu hợp với cảm giác bạn muốn: thẻ nhẹ nhàng, nổi mềm, bóng sắc nét, phát sáng màu thương hiệu, vùng lõm inset hoặc neumorphic. Các mẫu là điểm khởi đầu tốt để bạn tinh chỉnh.
2
Chỉnh lớp đang chọn
Kéo thanh trượt cho offset X/Y, blur, spread, màu và độ mờ. Bản xem trước bên trái cập nhật ngay lập tức. Độ mờ thấp hơn và blur cao hơn cho bóng *mềm* hơn.
3
Xếp thêm lớp
Nhấn *Thêm lớp* để xếp thêm một bóng thứ hai. Chiều sâu chân thực hầu như luôn dùng hai lớp: một lớp ngắn và gọn (bóng tiếp xúc) và một lớp dài và mềm (bóng môi trường).
4
Bật inset cho vùng lõm
Bật *Inset* để vẽ bóng bên trong phần tử thay vì xung quanh. Kết hợp với một bóng ngoài nhẹ để có hiệu ứng nút đang được nhấn.
5
Sao chép CSS
Khi bản xem trước đã đúng thiết kế, nhấn *Sao chép CSS*. Dán kết quả vào stylesheet: quy tắc được tạo bao gồm mọi lớp đang bật.
Tra cứu nhanh box-shadow
Từng giá trị trong box-shadow: x y blur spread color và vai trò của nó.
Giá trị
Tác dụng
Khoảng thường dùng
Offset X
Dịch bóng theo chiều ngang; dương = sang phải
Từ −40px đến 40px
Offset Y
Dịch bóng theo chiều dọc; dương = xuống dưới
Từ 0px đến 40px cho ánh sáng tự nhiên
Blur
Làm mềm cạnh của bóng
Từ 0px đến 80px
Spread
Phóng to hoặc thu nhỏ trước khi áp dụng blur
Từ −30px đến 30px
Màu
Bất kỳ màu CSS nào, nhưng rgba() cho phép chỉnh độ mờ từng lớp
Độ mờ alpha từ 0.05 đến 0.3 trong rgba(0,0,0,a) cho bóng tự nhiên
Một bóng gọn với blur thấp xác định điểm tiếp xúc, còn một bóng dài và mềm hơn tạo cảm giác ánh sáng môi trường. Đây là kiểu mà phần lớn design system hiện đại đang dùng.
Phát sáng màu thương hiệu
Phát sáng màu mềm
box-shadow:0024px4pxrgba(108,140,255,0.45);
Đặt X và Y bằng 0 để ánh sáng tỏa đều. Một spread dương nhỏ làm vầng sáng dày hơn trước khi blur làm mềm nó. Dùng tiết chế: vầng sáng màu thu hút rất nhiều sự chú ý.
Bóng inset được vẽ bên trong phần tử. Một bóng mềm tạo cảm giác vùng lõm xuống; một đường inset mảnh thêm viền trong tinh tế cho rõ nét.
Lỗi thường gặp với box-shadow
Dùng màu đen thuần với độ mờ cao. Kết quả trông như mảng cắt cứng, không phải bóng. Hạ độ mờ xuống khoảng 0.06 đến 0.18 để có độ nổi tự nhiên.
Quên offset Y. Bóng có X=0 và Y=0 nằm đều *phía sau* phần tử: hợp với hiệu ứng phát sáng, nhưng sai với một thẻ cần trông như đang lơ lửng.
Xếp quá nhiều lớp. Ba lớp thường là đủ; mười lớp tạo ra một mảng nhòe lem nhem và tốn đáng kể chi phí vẽ.
Dùng filter: drop-shadow() và box-shadow thay thế cho nhau. drop-shadow() đi theo mặt nạ alpha của SVG hoặc ảnh, hữu ích cho hình dạng bất thường, nhưng box-shadow nhanh hơn và gọn hơn cho phần tử hình chữ nhật.
Quên rằng box-shadow bỏ qua overflow: hidden trên chính phần tử đó. Nếu phần tử cha có overflow: hidden, bóng sẽ bị cắt.
Câu hỏi thường gặp về CSS box-shadow
Từng giá trị của box-shadow có ý nghĩa gì?
box-shadow: x y blur spread color. Hai giá trị đầu là offset; *blur* làm mềm cạnh; *spread* đổi kích thước trước khi blur; màu là bất kỳ màu CSS nào (dùng rgba() để kiểm soát độ mờ). Thêm inset ở đầu để đặt bóng bên trong phần tử.
Làm sao để xếp nhiều bóng trong một quy tắc?
Phân tách từng bóng bằng dấu phẩy. Chúng được vẽ từ sau ra trước theo thứ tự viết, nên bóng khai báo đầu tiên nằm *bên dưới* các bóng sau. Dùng cách này để kết hợp một bóng tiếp xúc gọn với một bóng môi trường mềm.
box-shadow và filter: drop-shadow() khác nhau thế nào?
box-shadow đi theo hình chữ nhật bao của phần tử và vẽ rất nhanh. drop-shadow() đi theo kênh alpha của thứ nó được áp dụng (rất hợp với SVG và PNG trong suốt) nhưng tốn chi phí hiển thị hơn. Dùng box-shadow cho thẻ và nút; dùng drop-shadow() cho hình dạng bất thường.
Vì sao bóng của tôi trông bị vỡ hạt?
Có thể blur quá nhỏ (blur 0px vốn tạo bóng sắc nét) hoặc phần tử đang bị phóng to thu nhỏ. Tăng giá trị blur hoặc kiểm tra xem có transform: scale() nào ở các phần tử cha không.
box-shadow có ảnh hưởng đến bố cục không?
Không. Bóng được vẽ bên ngoài hộp của phần tử nhưng không đẩy nội dung bên cạnh. Nếu cần phần tử cha chừa chỗ cho bóng, hãy thêm padding cho phần tử cha hoặc đặt overflow: visible.