GODRICH
#css-animation#button#loader#transition#scroll#ui#xu-huong-thiet-ke

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

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 thấy gì

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.

Gradient chuyển động
Mở trong tab mới

01 · Gradient chuyển động — Diện tích đo được 99.739% · khung hình chuyển động 20/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

background-position220% 220%$ease-out

Dùng ở đâu

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

Chuyện gì diễn ra trên màn hình

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ơ.

Mesh gradient trôi
Mở trong tab mới

02 · Mesh gradient trôi — Diện tích đo được 52.819% · khung hình chuyển động 15/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

radial-gradient 레이어transform: translate비동기 주기

Chỗ dùng

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ờ

Chuyển động thế nào

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.

Aurora mờ
Mở trong tab mới

03 · Aurora mờ — Diện tích đo được 41.671% · khung hình chuyển động 23/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

filter: blur반투명 레이어transform 회전

Dùng khi nào

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

Bạn thấy gì

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.

Lưới kẻ trôi
Mở trong tab mới

04 · Lưới kẻ trôi — Diện tích đo được 99.682% · khung hình chuyển động 23/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

linear-gradient 2겹background-position대각선 이동

Dùng ở đâu

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

Chuyện gì diễn ra trên mà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 biến hình
Mở trong tab mới

05 · Blob biến hình — Diện tích đo được 36.54% · khung hình chuyển động 22/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

레이어 크로스페이드transform: scale·rotateopacity

Chỗ dùng

.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

Chuyển động thế nào

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ũ.

Hạt nhiễu noise
Mở trong tab mới

06 · Hạt nhiễu noise — Diện tích đo được 99.705% · khung hình chuyển động 21/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

repeating-conic-gradientsteps()background-position

Dùng khi nào

Đâ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

Bạn thấy gì

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.

Chấm bi trôi
Mở trong tab mới

07 · Chấm bi trôi — Diện tích đo được 24.738% · khung hình chuyển động 23/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

radial-gradient 도트background-size 타일대각선 흐름

Dùng ở đâu

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

Chuyện gì diễn ra trên màn hình

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.

Sọc chéo di chuyển
Mở trong tab mới

08 · Sọc chéo di chuyển — Diện tích đo được 99.674% · khung hình chuyển động 23/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

repeating-linear-gradient45degbackground-position

Chỗ dùng

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ỏ

Chuyển động thế nào

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.

Đèn chiếu theo con trỏ
Mở trong tab mới

09 · Đèn chiếu theo con trỏ — Diện tích đo được 34.851% · khung hình chuyển động 13/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · Xem mật khẩu

radial-gradient 스포트라이트transform: translatepointermove 대응

Dùng khi nào

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

background-position transform và opacity

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

Điểm dừng của từng nền khi giảm chuyển động

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.

Nhập mật khẩu file nén

Mật khẩu nằm ngay trong bài viết này. Đọc tới đó bạn sẽ thấy.