Xlera8

Efek Melayang Mewah Untuk Avatar Anda

Tahukah Anda efek seperti itu di mana kepala seseorang menyembul melalui lingkaran atau lubang? Animasi Porky Pig yang terkenal di mana dia melambaikan tangan sambil keluar dari serangkaian cincin merah adalah contoh sempurna, dan Kilian Valkhof sebenarnya membuatnya kembali di CSS-Tricks beberapa waktu lalu.

Saya memiliki ide serupa tetapi ditangani dengan cara yang berbeda dan dengan taburan animasi. Saya pikir ini cukup praktis dan menghasilkan efek hover yang rapi yang dapat Anda gunakan pada sesuatu seperti avatar Anda sendiri.

Lihat itu? Kita akan membuat animasi penskalaan di mana avatar tampak keluar dari lingkaran tempatnya berada. Keren, kan? Jangan lihat kodenya dan mari buat animasi ini bersama langkah demi langkah.

HTML: Hanya satu elemen

Jika Anda belum memeriksa kode demo dan bertanya-tanya berapa banyak divIni akan memakan waktu, lalu berhenti di situ, karena markup kita hanyalah satu elemen gambar:

<img src="" alt="">

Ya, satu elemen! Bagian yang menantang dari latihan ini adalah menggunakan jumlah kode sekecil mungkin. Jika Anda telah mengikutiku untuk sementara, Anda harus terbiasa dengan ini. Saya berusaha keras untuk menemukan solusi CSS yang dapat dicapai dengan kode sekecil mungkin yang dapat dipelihara.

Saya menulis serangkaian artikel di sini di CSS-Trik di mana saya mengeksplorasi berbagai efek hover menggunakan markup HTML yang sama yang berisi satu elemen. Saya membahas detail tentang gradien, masking, kliping, garis besar, dan bahkan teknik tata letak. Saya sangat merekomendasikan untuk memeriksanya karena saya akan menggunakan kembali banyak trik di posting ini.

File gambar persegi dengan latar belakang transparan akan bekerja paling baik untuk apa yang kita lakukan. Inilah yang saya gunakan jika Anda ingin memulai dengan itu.

Dirancang oleh cang

Saya berharap dapat melihat banyak contoh tentang hal ini menggunakan gambar nyata — jadi silakan bagikan hasil akhir Anda di komentar setelah Anda selesai sehingga kami dapat membuat koleksi!

Sebelum terjun ke CSS, mari kita bedah dulu efeknya. Gambar menjadi lebih besar saat diarahkan, jadi kami pasti akan menggunakannya transform: scale() di sana. Ada lingkaran di belakang avatar, dan gradien radial sudah cukup. Terakhir, kita memerlukan cara untuk membuat batas di bagian bawah lingkaran yang menciptakan tampilan avatar di belakang lingkaran.

Ayo mulai bekerja!

Efek skala

Mari kita mulai dengan menambahkan transformasi:

img { width: 280px; aspect-ratio: 1; cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

Belum ada yang rumit, kan? Ayo lanjutkan.

Lingkaran

Kami mengatakan bahwa latar belakang akan menjadi gradien radial. Itu sempurna karena kita bisa membuat perhentian keras di antara warna gradien radial, yang membuatnya terlihat seperti sedang menggambar lingkaran dengan garis padat.

img { --b: 5px; /* border width */ width: 280px; aspect-ratio: 1; background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, #0000 ); cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

Perhatikan variabel CSS, --b, saya gunakan di sana. Ini mewakili ketebalan "perbatasan" yang sebenarnya hanya digunakan untuk menentukan penghentian warna keras untuk bagian merah dari gradien radial.

Langkah selanjutnya adalah bermain dengan ukuran gradien pada hover. Lingkaran perlu mempertahankan ukurannya saat gambar tumbuh. Karena kami menerapkan a scale() transformasi, kita benar-benar perlu mengurangi ukuran lingkaran karena sebaliknya akan meningkat dengan avatar. Jadi, saat gambar diperbesar, kita memerlukan gradien untuk memperkecil.

Mari kita mulai dengan mendefinisikan variabel CSS, --f, yang mendefinisikan "faktor skala", dan menggunakannya untuk mengatur ukuran lingkaran. saya menggunakan 1 sebagai nilai default, seperti itulah skala awal untuk gambar dan lingkaran yang kita ubah.

Berikut adalah demo untuk mengilustrasikan triknya. Arahkan kursor untuk melihat apa yang terjadi di balik layar:

Saya menambahkan warna ketiga ke radial-gradient untuk lebih mengidentifikasi area gradien saat melayang:

radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, lightblue
);

Sekarang kita harus memposisikan latar belakang kita di tengah lingkaran dan memastikannya memenuhi ketinggian penuh. Saya suka mendeklarasikan semuanya secara langsung di background properti steno, sehingga kita dapat menambahkan pemosisian latar belakang dan memastikannya tidak berulang dengan menempelkan nilai tersebut tepat setelah radial-gradient():

background: radial-gradient() 50% / calc(100% / var(--f)) 100% no-repeat;

Latar belakang ditempatkan di tengah (50%), memiliki lebar sama dengan calc(100%/var(--f)), dan memiliki tinggi sama dengan 100%.

Tidak ada skala kapan --f adalah sama dengan 1 - sekali lagi, skala awal kami. Sementara itu, gradien menempati seluruh lebar wadah. Saat kita meningkat --f, ukuran elemen bertambah — berkat scale() transform — dan ukuran gradien berkurang.

Inilah yang kami dapatkan ketika kami menerapkan semua ini ke demo kami:

Kami semakin dekat! Kita memiliki efek luapan di bagian atas, tetapi kita masih perlu menyembunyikan bagian bawah gambar, sehingga terlihat seperti keluar dari lingkaran daripada duduk di depannya. Itulah bagian rumit dari semua ini dan itulah yang akan kita lakukan selanjutnya.

Batas bawah

Saya pertama kali mencoba mengatasi ini dengan border-bottom properti, tetapi saya tidak dapat menemukan cara untuk mencocokkan ukuran batas dengan ukuran lingkaran. Ini yang terbaik yang bisa saya dapatkan dan Anda bisa langsung melihat kesalahannya:

Solusi sebenarnya adalah dengan menggunakan outline Properti. Ya, outline, tidak border. di artikel sebelumnya, saya tunjukkan caranya outline sangat kuat dan memungkinkan kita membuat efek hover yang keren. Dikombinasikan dengan outline-offset, kami memiliki apa yang kami butuhkan untuk efek kami.

Idenya adalah untuk mengatur sebuah outline pada gambar dan sesuaikan offsetnya untuk membuat batas bawah. Offset akan tergantung pada faktor penskalaan dengan cara yang sama seperti ukuran gradien.

Sekarang kita memiliki "perbatasan" bawah kita (sebenarnya sebuah outline) digabungkan dengan "perbatasan" yang dibuat oleh gradien untuk membuat lingkaran penuh. Kita masih perlu menyembunyikan sebagian dari outline (dari atas dan samping), yang akan kita bahas sebentar lagi.

Inilah kode kita sejauh ini, termasuk beberapa variabel CSS lainnya yang dapat Anda gunakan untuk mengonfigurasi ukuran gambar (--s) dan warna "batas" (--c):

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50% / calc(100% / var(--f)) 100% no-repeat; transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

Karena kita membutuhkan batas bawah melingkar, kita menambahkan a border-radius di sisi bawah, memungkinkan outline untuk mencocokkan kelengkungan gradien.

Perhitungan yang digunakan pada outline-offset jauh lebih mudah daripada yang terlihat. Secara default, outline ditarik di luar dari kotak elemen. Dan dalam kasus kami, kami membutuhkannya tumpang tindih elemen. Lebih tepatnya, kita membutuhkannya untuk mengikuti lingkaran yang dibuat oleh gradien.

Diagram transisi latar belakang.

Saat kita menskalakan elemen, kita melihat ruang antara lingkaran dan tepi. Jangan lupa bahwa idenya adalah untuk menjaga lingkaran pada ukuran yang sama setelah transformasi skala berjalan, yang memberi kita ruang yang akan kita gunakan untuk menentukan offset garis luar seperti yang diilustrasikan pada gambar di atas.

Jangan lupa bahwa elemen kedua diskalakan, jadi hasil kita juga diskalakan… artinya kita perlu membagi hasilnya dengan f untuk mendapatkan nilai offset sebenarnya:

Offset = ((f - 1) * S/2) / f = (1 - 1/f) * S/2

Kami menambahkan tanda negatif karena kami membutuhkan garis besar dari luar ke dalam:

Offset = (1/f - 1) * S/2

Berikut adalah demo singkat yang menunjukkan bagaimana garis besar mengikuti gradien:

Anda mungkin sudah melihatnya, tapi kita masih membutuhkan garis tepi bawah untuk menindih lingkaran daripada membiarkannya menembusnya. Kita bisa melakukannya dengan menghapus ukuran perbatasan dari offset:

outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2) - var(--b));

Sekarang kita perlu menemukan cara menghapus bagian atas dari garis besar. Dengan kata lain, kita hanya menginginkan bagian bawah gambar outline.

Pertama, mari tambahkan ruang di bagian atas dengan padding untuk membantu menghindari tumpang tindih di bagian atas:

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; padding-block-start: calc(var(--s)/5); /* etc. */
}
img:hover { --f: 1.35; /* hover scale */
}

Tidak ada logika khusus untuk bantalan atas itu. Idenya adalah untuk memastikan garis besar tidak menyentuh kepala avatar. Saya menggunakan ukuran elemen untuk menentukan ruang agar selalu memiliki proporsi yang sama.

Perhatikan bahwa saya telah menambahkan content-box nilai ke background:

background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50%/calc(100%/var(--f)) 100% no-repeat content-box;

Kami membutuhkan ini karena kami menambahkan bantalan dan kami hanya ingin latar belakang disetel ke kotak konten, jadi kami harus secara eksplisit memberi tahu latar belakang untuk berhenti di situ.

Menambahkan topeng CSS ke dalam campuran

Kami mencapai bagian terakhir! Yang perlu kita lakukan hanyalah menyembunyikan beberapa bagian, dan kita selesai. Untuk ini, kami akan mengandalkan mask properti dan, tentu saja, gradien.

Berikut adalah gambar untuk mengilustrasikan apa yang perlu kita sembunyikan atau apa yang perlu kita tunjukkan agar lebih akurat

Menunjukkan bagaimana topeng diterapkan ke bagian bawah lingkaran.

Gambar kiri adalah yang kita miliki saat ini, dan gambar kanan adalah yang kita inginkan. Bagian hijau mengilustrasikan topeng yang harus kita terapkan pada gambar asli untuk mendapatkan hasil akhir.

Kami dapat mengidentifikasi dua bagian dari topeng kami:

  • Bagian melingkar di bagian bawah yang memiliki dimensi dan kelengkungan yang sama dengan gradien radial yang kita gunakan untuk membuat lingkaran di belakang avatar
  • Persegi panjang di bagian atas yang menutupi area di dalam garis tepi. Perhatikan bagaimana garis luar berada di luar area hijau di bagian atas — itu adalah bagian yang paling penting, karena memungkinkan garis dipotong sehingga hanya bagian bawah yang terlihat.

Inilah CSS terakhir kita:

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; --_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); width: var(--s); aspect-ratio: 1; padding-top: calc(var(--s)/5); cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: var(--_o); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000) var(--_g); mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g); transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

Mari kita uraikan itu mask Properti. Sebagai permulaan, perhatikan bahwa serupa radial-gradient() dari background properti ada di sana. Saya membuat variabel baru, --_g, untuk bagian umum agar tidak terlalu berantakan.

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

Selanjutnya, ada linear-gradient() di sana juga:

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

Ini menciptakan bagian persegi panjang dari topeng. Lebarnya sama dengan lebar gradien radial dikurangi dua kali ketebalan batas:

calc(100% / var(--f) - 2 * var(--b))

Tinggi persegi panjang sama dengan setengah, 50%, dari ukuran elemen.

Kami juga membutuhkan gradien linier yang ditempatkan di pusat horizontal (50%) dan offset dari atas dengan nilai yang sama dengan offset garis luar. Saya membuat variabel CSS lain, --_o, untuk offset yang telah kita tentukan sebelumnya:

--_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));

Salah satu hal yang membingungkan di sini adalah kita membutuhkan a negatif offset untuk garis besar (untuk memindahkannya dari luar ke dalam) tetapi a positif offset untuk gradien (untuk berpindah dari atas ke bawah). Jadi, jika Anda bertanya-tanya mengapa kami menggandakan offset, --_o, Dengan -1, nah, sekarang kamu tahu!

Berikut adalah demo untuk mengilustrasikan konfigurasi gradien topeng:

Arahkan kursor ke atas dan lihat bagaimana semuanya bergerak bersama. Kotak tengah mengilustrasikan lapisan topeng yang terdiri dari dua gradien. Bayangkan sebagai bagian yang terlihat dari gambar kiri, dan Anda mendapatkan hasil akhir di sebelah kanan!

Membungkus

Oof, kita sudah selesai! Dan kami tidak hanya berakhir dengan animasi hover yang apik, tetapi kami melakukan semuanya dengan satu HTML <img> elemen. Hanya itu dan tipuan CSS kurang dari 20 baris!

Tentu, kami mengandalkan beberapa trik kecil dan rumus matematika untuk mencapai efek yang begitu rumit. Tapi kami tahu persis apa yang harus dilakukan karena kami mengidentifikasi bagian yang kami butuhkan di muka.

Bisakah kita menyederhanakan CSS jika kita mengizinkan lebih banyak HTML? Sangat. Tapi kami di sini untuk mempelajari trik CSS baru! Ini adalah latihan yang bagus untuk menjelajahi gradien CSS, masking, dan outline perilaku properti, transformasi, dan banyak lagi. Jika Anda merasa tersesat kapan saja, maka periksalah seri saya yang menggunakan konsep umum yang sama. Kadang-kadang membantu untuk melihat lebih banyak contoh dan kasus penggunaan untuk mengarahkan poin ke rumah.

Saya akan meninggalkan Anda dengan satu demo terakhir yang menggunakan foto-foto pengembang CSS populer. Jangan lupa tunjukkan demo dengan gambar Anda sendiri agar saya bisa menambahkannya ke koleksi!

Hubungi kami

Hai, yang di sana! Apa yang bisa saya bantu?