prefers-reduced-motion cho biết người dùng đã bật thiết lập giảm chuyển động ở cấp hệ điều hành. Đây không phải sở thích thẩm mỹ: chuyển động lớn gây chóng mặt, buồn nôn thật với người có rối loạn tiền đình.
Cách viết được khuyến nghị — mặc định là không animate, chỉ thêm khi người dùng không phản đối:
.card { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
.card { animation: fade-up 0.28s ease-out both; }
}Cách này an toàn hơn kiểu "animate mặc định rồi tắt sau", vì nếu quên một chỗ thì chỗ đó không có animation thay vì animate mất kiểm soát.
Khi phải áp lên codebase đã có sẵn animation, giảm thay vì xoá:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}Đặt 0.01ms thay vì none để sự kiện animationend/transitionend vẫn bắn — nhiều logic JS phụ thuộc vào chúng.
Trong JS:
const reduce = matchMedia('(prefers-reduced-motion: reduce)').matchesChốt: thứ cần bỏ là chuyển động lớn (trượt ngang, phóng to, parallax).
Đổi màu hay mờ dần nhẹ thường vẫn giữ được — mục tiêu là bớt gây khó chịu, không phải làm giao diện đứng yên hoàn toàn.