Ảnh động đường viền CSS

Xem xét một số cách tạo ảnh động cho đường viền trong CSS

Có một số phương pháp để đặt đường viền cho một phần tử: border, outlinebox-shadow. Như đã trình bày chi tiết trong bài viết 3 phương thức CSS để thêm đường viền phần tử của Stephanie Eckles, mỗi phương pháp đều có ưu và nhược điểm riêng, đặc biệt là khi tạo ảnh động cho đường viền. Lý do chính khiến bạn không sử dụng border CSS thích hợp là cho mục đích tạo ảnh động.

Ảnh động đường viền sử dụng outline-offset của Kevin J. Powell

Một bài viết thu hút sự chú ý gần đây là Ảnh động đường viền CSS tuyệt đẹp, trong đó tác giả Coco khám phá thêm nhiều lựa chọn. Bằng cách chèn nội dung được tạo bằng ::before::after, chúng sẽ tạo ra một đường viền giả sau đó được tạo hiệu ứng động.

Điều nổi bật nhất đối với tôi là các hình ảnh động hỗ trợ được sử dụng trong bài viết. Các chú thích này thực sự giúp giải thích chính xác những gì đang được thực hiện để đạt được hiệu ứng mong muốn.

Ảnh động đường viền sử dụng nội dung do Coco tạo ra

Cả lớp màu trắng và các đường có màu đều là nội dung được tạo. Bằng cách làm mờ và làm rõ lớp màu trắng, bạn có thể thấy rõ cách các lớp xếp chồng lên nhau và cách hoạt động của ảnh động.

Giữ lại mô hình hộp

Một nhược điểm của việc sử dụng Nội dung được tạo để mô phỏng đường viền là bạn sẽ có một mô hình hộp bị hỏng: nội dung hiện có thể che khuất đường viền giả vì "đường viền" đó được vẽ bên dưới. Để giảm thiểu, bạn phải áp dụng border-width mong muốn làm padding.

Để có đường viền thực sự – và do đó giữ lại hoạt động của mô hình hộp – bạn có thể sử dụng nhiều nền, sau đó kéo giãn ra khu vực đường viền.

Khái niệm cơ bản

Hãy bắt đầu bằng cách tạo đường viền chấm rồi thêm nhiều nền.

/* Size of the border */
--border-size: 0.5rem;

/* Create a dotted border */
border: var(--border-size) dotted lime;

/* Create two background layers:
   1. A white semi-transparent
   2. A layer with the colored boxes
 */
background-image:
  linear-gradient(to right, rgb(255 255 255 / 0.5), rgb(255 255 255 / 0.5)),

  conic-gradient(
    from 45deg,
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  )
;

Định kích thước nền bằng background-origin

Như bạn có thể thấy, có điều gì đó thú vị đang xảy ra với nền ở đây: chúng được vẽ vào đường viền, nhưng conic-gradient có vẻ như không đúng. Đây thực sự là hành vi dự kiến: theo mặc định, hình nền không vẽ vào đường viền vì nguồn gốc của hình nền là padding-box của phần tử. Để tạo đường viền sau cùng, các hình nền đã đặt được lặp lại trong chính đường viền đó, tạo ra hiệu ứng hình ảnh kỳ lạ.

Để giải quyết vấn đề này, bạn cần kéo giãn nền để nền cũng chiếm kích thước của đường viền. Bạn có thể thực hiện việc này theo cách thủ công bằng cách kéo giãn và đặt lại vị trí nền, nhưng tốt nhất là sử dụng thuộc tính background-origin để định kích thước nền dựa trên border-box.

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 4.
  • Safari: 3.

Nguồn

Không nên
/* Manually add or offset the size of the border where needed */
background-position: calc(var(--border-size) * -1) calc(var(--border-size) * -1);
background-size: calc(var(--border-size) * 2 + 100%) calc(var(--border-size) * 2 + 100%);
Nên
background-origin: border-box;

Chỉ cần thêm một phần này vào là mọi thứ trông sẽ đẹp hơn nhiều:

Thu nhỏ lớp nền trắng bằng background-clip

Giờ đây, nền đã chiếm hết không gian, nên lớp bán trong suốt cần được thu nhỏ lại. Thay vì thực hiện lại background-size, có một cách dễ dàng hơn để thực hiện việc này: sử dụng background-clip và đặt thành padding-box. Bằng cách đó, nền sẽ không còn được vẽ bên dưới khu vực đường viền.

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 4.
  • Safari: 5.

Nguồn

background-clip:
  padding-box, /* Clip white semi-transparent to the padding-box */
  border-box /* Clip colored boxes to the border-box (default) */
;

Cuối cùng, hãy tạo đường viền transparent để có hiệu ứng đầy đủ.

border: 0.3rem dotted transparent;

Hoạt ảnh

Để khôi phục ảnh động của đường viền, bạn có thể thao tác với góc bắt đầu của conic-gradient.

--angle: 0deg;
conic-gradient(
  from var(--angle),
  #d53e33 0deg 90deg,
  #fbb300 90deg 180deg,
  #377af5 180deg 270deg,
  #399953 270deg 360deg
);

Nhờ @property, việc này trở nên dễ dàng trong các trình duyệt hỗ trợ thuộc tính này:

Hỗ trợ trình duyệt

  • Chrome: 85.
  • Edge: 85.
  • Firefox: 128.
  • Safari: 16.4.

Nguồn

@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes rotate {
  to {
    --angle: 360deg;
  }
}

Khi kết hợp tất cả, mã sẽ trở thành:

Nội dung thưởng: border-image

Một phương pháp đã đề cập trước đây để vẽ đường viền chuyển màu là sử dụng CSS border-image.

Hỗ trợ trình duyệt

  • Chrome: 16.
  • Edge: 12.
  • Firefox: 15.
  • Safari: 6.

Nguồn

Điều này cho phép mã đơn giản hơn vì bạn không cần xử lý các nền chồng chéo. Bạn có thể áp dụng ảnh động theo cách tương tự như trước.

/* Create a border */
border: 0.5rem solid transparent;

/* Paint an image in the border */
border-image:
  conic-gradient(
    from var(--angle),
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  ) 1
;

Tuy nhiên, bạn sẽ nhận thấy một số tính năng không còn hoạt động với phương pháp này:

  • border-image không tuân theo border-radius; nó sẽ luôn giữ nguyên hình chữ nhật.
  • Khi đặt border-image-slice thành fill (điền), border-image không được vẽ bên dưới tập hợp background mà ở trên cùng. Điều này có thể gây phiền toái nếu bạn muốn nền có độ trong suốt bán phần.

Kết luận

Có rất nhiều cách để tạo hiệu ứng động cho đường viền trong CSS. Tuỳ thuộc vào trường hợp sử dụng, bạn có thể dùng một trong hai cách này.