9 hiệu ứng css background animation dán là chạy
Css background animation là cách khiến nền sau nội dung — gradient, lưới, chấm, nhiễu — tự chuyển động mà không cần ảnh hay JS.
Tự chạy · bấm ô để tới mục đó · cả 9 trong một zip
- 01 Gradient chuyển động
- 02 Mesh gradient trôi
- 03 Aurora mờ
- 04 Lưới kẻ trôi
- 05 Blob biến hình
- 06 Hạt nhiễu noise
- 07 Chấm bi trôi
- 08 Sọc chéo di chuyển
- 09 Đèn chiếu theo con trỏ
Chín hiệu ứng không xếp theo độ hoành tráng mà theo vai trò trên sân khấu: 01 đến 03 để chính màu sắc làm chủ thể, 04 vẽ ra một cấu trúc, 05 liên tục đổi hình, 06 và 07 thêm chất liệu bề mặt, 08 tạo cảm giác hướng đi, còn 09 phản hồi thao tác của bạn. Gần như tất cả chỉ động vào background-position, transform hoặc opacity, không đụng đến width hay border-radius mỗi khung hình. Mỗi mục dưới đây chỉ trích đoạn cốt lõi, bản đầy đủ nằm trong file zip.
01Gradient chuyển động
Bạn vẽ nền to gấp đôi khung hình rồi chỉ cho background-position trượt qua lại, khiến một gradient đứng yên bỗng trông như đang chảy. Không có phần tử phụ nào cả — chính nền sân khấu là nhân vật chính.
.stage::before {
content: "";
position: absolute;
inset: 0;
background-image: linear-gradient(120deg, $stage-ink, $color, $subject-cream, $stage-ink);
background-size: 220% 220%;
animation: flow $duration $easing infinite;
}
@keyframes flow {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
02Mesh gradient trôi
Ba vệt radial-gradient màu khác nhau chồng lên nhau, mỗi vệt tự dịch bằng transform: translate với độ trễ khởi động riêng, nên chúng trôi qua nhau và hoà thành một mesh gradient hữu cơ. Bạn sẽ gặp kiểu nền này rất nhiều ở landing SaaS gần đây.
.blob { position: absolute; width: 42%; aspect-ratio: 1; border-radius: 50%; filter: blur(12px); opacity: .9; }
.b1 { background: radial-gradient($color, transparent 65%); animation: drift1 $duration $easing infinite; }
.b2 { background: radial-gradient($subject-cream, transparent 65%); animation: drift2 $duration $easing infinite; animation-delay: -.6s; }
.b3 { background: radial-gradient($stage-ink, transparent 65%); opacity: .65; animation: drift3 $duration $easing infinite; animation-delay: -1.2s; }
@keyframes drift1 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(48px, 32px); } }
@keyframes drift2 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-42px, -26px); } }
@keyframes drift3 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(24px, -38px); } }
03Aurora mờ
Hai ba khối màu được filter: blur làm nhoè, xếp chồng bán trong suốt và chỉ xoay bằng transform (dịch chuyển kèm rotate), tạo cảm giác như dải aurora đang cuộn qua nhau. Bạn hay thấy nó làm ánh sáng nền cho hero chế độ tối.
.aurora { position: absolute; width: 38%; aspect-ratio: 1; border-radius: 50%; filter: blur(3px); }
.a1 { background: radial-gradient($subject-cream 0%, $subject-cream 25%, transparent 55%);
animation: spin1 $duration linear infinite; }
@keyframes spin1 {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(56px, 38px) rotate(180deg); }
100% { transform: translate(0, 0) rotate(360deg); }
}
04Lưới kẻ trôi
Hai lớp repeating-linear-gradient vẽ đường kẻ ngang và dọc chồng lên nhau, rồi background-position đẩy cả cặp trục x·y cùng lúc theo đường chéo, khiến lưới trông như cuộn mãi không dứt. Bạn có thể dùng nó làm nền cho tài liệu kỹ thuật hoặc dashboard rỗng.
.stage::before {
content: "";
position: absolute;
inset: 0;
background-image:
linear-gradient(to right, rgba($color, .35) 1px, transparent 1px),
linear-gradient(to bottom, rgba($color, .35) 1px, transparent 1px);
background-size: 32px 32px, 32px 32px;
animation: gridmove $duration linear infinite;
}
@keyframes gridmove {
from { background-position: 0 0, 0 0; }
to { background-position: 32px 32px, 32px 32px; }
}
05Blob biến hình
Ba lớp blob có border-radius cố định khác nhau chồng lên nhau, chỉ opacity và transform (scale, rotate) thay phiên xuất hiện, nên khối trông như liên tục đổi hình mà trình duyệt không phải tính lại border-radius ở từng khung hình.
.blob { position: absolute; width: 52%; aspect-ratio: 1; background: $color; }
.m1 { border-radius: 42% 58% 63% 37% / 41% 44% 56% 59%; animation: morph1 $duration $easing infinite; }
.m2 { border-radius: 63% 37% 41% 59% / 55% 48% 52% 45%; opacity: 0; animation: morph2 $duration $easing infinite; }
@keyframes morph1 {
0% { opacity: 1; transform: scale(1) rotate(0deg); }
38% { opacity: 0; transform: scale(.94) rotate(8deg); }
100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
06Hạt nhiễu noise
Một ô repeating-conic-gradient chỉ 3px được lát dày đặc, rồi background-position nhảy cóc từng khung hình bằng steps(40) thay vì trượt mượt, nên bề mặt tạo cảm giác nhiễu hạt như phim cũ. Đây là lớp phủ chất liệu quen thuộc trên thẻ cao cấp.
.stage::before {
content: "";
position: absolute;
inset: 0;
background-image: repeating-conic-gradient(from 0deg, rgba($color, .55) 0deg 90deg, transparent 90deg 180deg);
background-size: 3px 3px;
opacity: .35;
animation: grain $duration steps(40) infinite;
}
@keyframes grain {
from { background-position: 0 0; }
to { background-position: 117px 69px; }
}
07Chấm bi trôi
Một mẫu chấm nhỏ vẽ bằng radial-gradient được lát kín thành lưới 20px, rồi background-position trôi chậm theo đường chéo để các chấm chảy liền mạch, không lộ mối nối giữa các tile. Hợp để làm nền slide hoặc phía sau một lưới thẻ.
.stage::before {
content: "";
position: absolute;
inset: 0;
background-image: radial-gradient(circle, rgba($color, .6) 1.5px, transparent 1.5px);
background-size: 20px 20px;
animation: dotdrift $duration linear infinite;
}
@keyframes dotdrift {
from { background-position: 0 0; }
to { background-position: 20px 20px; }
}
08Sọc chéo di chuyển
Sọc dọc vẽ bằng repeating-linear-gradient được cả lớp xoay 45 độ bằng transform: rotate, còn background-position chỉ trượt theo trục ngang của toạ độ gốc trước khi xoay — nhờ vậy sọc trông như đang diễu hành chéo qua bề mặt. Thường gặp trên banner khuyến mãi hoặc trạng thái đang xử lý.
.stage::before {
content: "";
position: absolute;
inset: -150% -150%;
transform: rotate(45deg);
background-image: repeating-linear-gradient(90deg, rgba($color, .18) 0 18px, transparent 18px 36px);
animation: stripemove $duration linear infinite;
}
@keyframes stripemove {
from { background-position: 0 0; }
to { background-position: 36px 0; }
}
09Đèn chiếu theo con trỏ
Một vòng tròn radial-gradient nhỏ đã làm mờ đóng vai đèn spotlight, di chuyển theo quỹ đạo elip chỉ bằng transform: translate. Trong lưới demo nó tự quay vì không có chuột thật, còn trên trang của bạn, cùng toạ độ ấy sẽ được lấy từ sự kiện pointermove để bám theo con trỏ.
.spot {
position: absolute;
top: 50%;
left: 50%;
width: 120px;
height: 120px;
margin: -60px 0 0 -60px;
border-radius: 50%;
background: radial-gradient(circle, rgba($color, .55), transparent 70%);
filter: blur(6px);
}
.spot.is-demo { animation: orbit $duration $easing infinite; }
@keyframes orbit {
0% { transform: translate(-90px, -40px); }
25% { transform: translate(90px, -50px); }
50% { transform: translate(70px, 60px); }
75% { transform: translate(-80px, 55px); }
100% { transform: translate(-90px, -40px); }
}
Chỗ dễ hỏng ở đâu? — cái bẫy
Tám trong chín mục chỉ động vào background-position, transform hoặc opacity vì đây là những thuộc tính trình duyệt xử lý ở bước hợp thành, đúng như tài liệu hiệu năng animation của MDN khuyến nghị — nền vốn phủ một diện tích lớn nên đổi width hay tính lại border-radius mỗi khung hình sẽ bắt trình duyệt vẽ lại toàn bộ vùng đó. Cái bẫy nằm ở mục 08. Bạn có thể nghĩ chỉ cần xoay sọc 45 độ rồi cho background-position chạy theo đúng đường chéo đó là xong, nhưng làm vậy màn hình không đổi một pixel nào cả — hướng dịch chuyển trùng khít với hướng sọc nên mắt không phân biệt được điểm đầu và điểm cuối của phép dịch. Cách đúng là vẽ sọc dọc trước rồi xoay nguyên lớp đó 45 độ bằng transform, còn background-position vẫn trượt ngang trong toạ độ gốc chưa xoay. Nếu bạn muốn xem file gốc kèm phần bình luận đã ghi lại đúng chỗ dễ nhầm này, mật khẩu của zip là bc82wnvk.
Khả năng tiếp cận
Khi bạn bật "giảm chuyển động" trong hệ điều hành, cả chín nền phản hồi prefers-reduced-motion: reduce nhưng không đơn giản là tắt hết — mỗi mục dừng ở một khung hình còn giữ được ý nghĩa thị giác. Mục 05 giữ nguyên lớp blob đầu tiên và ẩn hai lớp còn lại thay vì để trống, còn mục 09 đứng yên tại điểm bắt đầu quỹ đạo thay vì biến mất khỏi màn hình. Mức hỗ trợ của media query này theo từng trình duyệt được ghi trong tài liệu prefers-reduced-motion của MDN.
@media (prefers-reduced-motion: reduce) {
.stage::before,
.blob,
.aurora,
.spot.is-demo { animation: none; }
}
Nếu bạn muốn xem thêm hiệu ứng CSS khác ngoài phần nền, chuyên mục CSS gom hết các bài cùng dạng, còn trang giới thiệu nói rõ site này chọn demo theo tiêu chí nào.
FAQ
Css background animation có làm chậm trang không?
Không, miễn là bạn chỉ động vào background-position, transform hoặc opacity như chín mục ở đây, vì trình duyệt xử lý chúng ở bước hợp thành mà không phải vẽ lại layout. Riêng mục 02 và 03 dùng filter: blur, nên hai mục đó chỉ blur vài khối nhỏ thay vì toàn bộ sân khấu để giữ chi phí thấp.
Vì sao mục 09 tự quay trong lưới demo thay vì theo chuột?
Vì lưới demo cần chuyển động chạy sẵn để bạn xem mà không phải rê chuột vào từng ô, nên class .is-demo ép một quỹ đạo elip cố định. Khi bạn mở file thật từ zip và gắn vào trang của mình, đoạn pointermove sẽ thay thế quỹ đạo đó bằng toạ độ con trỏ thật.
Có ghép được nhiều hiệu ứng nền trên cùng một trang không?
Về mặt kỹ thuật thì được, nhưng bạn nên chỉ dùng một nền động cho mỗi màn hình. Hai nền cùng chuyển động sẽ khiến mắt không biết nên nhìn theo cái nào, và chữ đặt lên trên cũng khó đọc hơn hẳn. Bạn có thể tránh việc đó bằng cách chọn một mục làm chủ thể chính rồi giữ các phần còn lại của trang đứng yên.