Animasi batas CSS

Melihat beberapa cara untuk menganimasikan batas di CSS

Ada beberapa metode yang tersedia untuk menetapkan batas pada elemen: border, outline, dan box-shadow. Seperti yang dijelaskan dalam 3 Metode CSS untuk Menambahkan Batas Elemen oleh Stephanie Eckles, setiap pendekatan memiliki kelebihan dan kekurangannya sendiri, terutama dalam hal menganimasikan batas. Alasan utama untuk tidak menggunakan border CSS yang tepat adalah untuk tujuan animasi.

Animasi Batas menggunakan outline-offset oleh Kevin J. Powell

Artikel yang baru-baru ini menarik perhatian saya adalah Fantastic CSS border animation, yang ditulis oleh Coco yang mengeksplorasi lebih banyak opsi. Dengan memasukkan konten yang dihasilkan menggunakan ::before dan ::after, keduanya akan membuat batas palsu yang kemudian dianimasikan.

Yang paling menarik bagi saya adalah visualisasi animasi pendukung yang digunakan dalam artikel. Diagram ini sangat membantu menjelaskan apa yang sebenarnya dilakukan untuk mencapai efek yang diinginkan.

Animasi Batas menggunakan konten yang dibuat oleh Coco

Lapisan putih dan garis berwarna adalah konten yang dihasilkan. Dengan memudarkan lapisan putih secara perlahan, Anda dapat melihat dengan jelas cara lapisan tersebut ditumpuk dan cara kerja animasi.

Mempertahankan model kotak

Kekurangan menggunakan Konten yang Dibuat untuk meniru batas adalah Anda akan mendapatkan model kotak yang rusak: konten kini dapat mengaburkan batas palsu karena “batas” tersebut digambar di bawahnya. Untuk menguranginya, Anda harus menerapkan border-width yang diinginkan sebagai padding.

Untuk memiliki batas yang sebenarnya–sehingga mempertahankan cara kerja model kotak–Anda dapat menggunakan beberapa latar belakang yang kemudian Anda rentangkan ke area batas.

Dasar-dasar

Mari kita mulai dengan membuat batas putus-putus dan menambahkan beberapa latar belakang.

/* 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
 
)
;

Mengubah ukuran latar belakang dengan background-origin

Seperti yang dapat Anda lihat, ada sesuatu yang aneh dengan latar belakang di sini: latar belakang dicat ke dalam batas, tetapi conic-gradient tampaknya salah. Ini sebenarnya adalah perilaku yang diinginkan: secara default, gambar latar tidak digambar ke dalam batas karena asalnya adalah padding-box elemen. Untuk membuat batas, gambar latar yang ditetapkan akan diulang di batas itu sendiri, sehingga menghasilkan efek visual yang aneh.

Untuk mengatasi masalah ini, Anda perlu meregangkan latar belakang sehingga juga menempati ukuran batas. Anda dapat melakukannya secara manual dengan meregangkan dan memosisikan ulang latar belakang, tetapi sebaiknya gunakan properti background-origin untuk menyesuaikan ukuran latar belakang dengan border-box.

Dukungan Browser

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

Sumber

Larangan
/* 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%);
Anjuran
background-origin: border-box;

Penambahan ini membuat semuanya terlihat jauh lebih baik:

Memperkecil lapisan latar belakang putih dengan background-clip

Dengan latar belakang yang sekarang memenuhi semua ruang, lapisan semi-transparan perlu diciutkan lagi. Daripada harus mengutak-atik background-size lagi, ada cara yang lebih mudah untuk melakukannya: gunakan background-clip dan tetapkan ke padding-box. Dengan begitu, latar belakang tidak lagi digambar di bawah area batas.

Dukungan Browser

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

Sumber

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

Terakhir, buat batas transparent agar memiliki efek penuh.

border: 0.3rem dotted transparent;

Animasi

Untuk memulihkan animasi batas, Anda dapat memanipulasi sudut awal conic-gradient.

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

Berkat @property, hal ini menjadi mudah di browser yang mendukungnya:

Dukungan Browser

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

Sumber

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

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

Jika digabungkan, kodenya menjadi seperti ini:

Konten Bonus: border-image

Pendekatan yang telah dibahas sebelumnya untuk menggambar batas gradien adalah menggunakan CSS border-image.

Dukungan Browser

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

Sumber

Hal ini memungkinkan kode yang lebih sederhana karena Anda tidak perlu menangani latar belakang yang tumpang-tindih. Animasi dapat diterapkan dengan cara yang sama seperti sebelumnya.

/* 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
;

Namun, Anda akan melihat beberapa hal yang tidak lagi berfungsi dengan pendekatan ini:

  • border-image tidak mengikuti border-radius; border-image akan selalu tetap persegi panjang.
  • Saat menetapkan border-image-slice untuk mengisi, border-image tidak digambar di bawah background yang ditetapkan, tetapi di atasnya. Hal ini dapat merepotkan jika Anda ingin latar belakang menjadi semi-transparan.

Sebagai penutup

Ada banyak kemungkinan untuk menganimasikan batas di CSS. Bergantung pada kasus penggunaan, Anda mungkin lebih memilih salah satunya.