Anda pasti pernah mendengar tentang CSS Anchor Positioning yang baru, bukan? Ini adalah fitur yang memungkinkan Anda menghubungkan elemen apa pun dari halaman ke halaman lainnya, yaitu jangkar. Ini berguna untuk semua hal tooltip, tetapi juga dapat membuat banyak efek bagus lainnya.
Pada artikel ini, kita akan mempelajari navigasi menu di mana saya mengandalkan posisi jangkar untuk menciptakan efek hover yang bagus pada tautan.
Keren, bukan? Kami memiliki efek geser di mana persegi panjang biru menyesuaikan agar pas dengan konten teks melalui transisi yang bagus. Jika Anda baru dalam penentuan posisi jangkar, contoh ini sangat cocok untuk Anda karena sederhana dan memungkinkan Anda menemukan dasar-dasar fitur baru ini. Kita juga akan mempelajari contoh lainnya, jadi tunggu sampai akhir!
Perhatikan bahwa hanya browser berbasis Chromium yang sepenuhnya mendukung penentuan posisi jangkar pada saat saya menulis ini. Anda sebaiknya melihat demo di browser seperti Chrome atau Edge hingga fitur tersebut didukung lebih luas di browser lain.
Konfigurasi awal
Mari kita mulai dengan struktur HTML yang tidak lain adalah a nav
elemen yang berisi daftar tautan tidak berurutan:
Kami tidak akan menghabiskan terlalu banyak waktu untuk menjelaskan struktur ini karena bisa berbeda jika kasus penggunaan Anda berbeda. Cukup pastikan semantiknya relevan dengan apa yang Anda coba lakukan. Sedangkan untuk bagian CSS, kita akan mulai dengan beberapa gaya dasar untuk membuat navigasi menu horizontal.
ul {
padding: 0;
margin: 0;
list-style: none;
display: flex;
gap: .5rem;
font-size: 2.2rem;
}
ul li a {
color: #000;
text-decoration: none;
font-weight: 900;
line-height: 1.5;
padding-inline: .2em;
display: block;
}
Sejauh ini tidak ada yang mewah. Kami menghapus beberapa gaya default dan menggunakan Flexbox untuk menyelaraskan elemen secara horizontal.
Efek geser
Pertama, mari kita pahami cara kerja efeknya. Pada pandangan pertama, sepertinya kita memiliki satu persegi panjang yang menyusut hingga ketinggian kecil, berpindah ke elemen yang melayang, dan kemudian tumbuh hingga ketinggian penuh. Itulah efek visualnya, namun kenyataannya, lebih dari satu elemen terlibat!
Ini adalah demo pertama di mana saya menggunakan warna berbeda untuk melihat lebih baik apa yang terjadi.
Setiap item menu memiliki “elemen” sendiri yang menyusut atau bertambah. Kemudian kita memiliki “elemen” umum (yang berwarna merah) yang meluncur di antara item menu yang berbeda. Efek pertama dilakukan dengan menggunakan animasi latar belakang dan yang kedua adalah dimana posisi jangkar ikut berperan!
Animasi latar belakang
Kami akan menganimasikan tinggi gradien CSS untuk bagian pertama ini:
/* 1 */
ul li {
background:
conic-gradient(lightblue 0 0)
bottom/100% 0% no-repeat;
transition: .2s;
}
/* 2 */
ul li:is(:hover,.active) {
background-size: 100% 100%;
transition: .2s .2s;
}
/* 3 */
ul:has(li:hover) li.active:not(:hover) {
background-size: 100% 0%;
transition: .2s;
}
Kami telah mendefinisikan gradien dengan a 100%
lebar dan 0%
tinggi, ditempatkan di bagian bawah. Sintaks gradien mungkin terlihat aneh, tetapi ini adalah sintaksis terpendek yang memungkinkan saya memiliki gradien satu warna.
Terkait: “Cara mendefinisikan gradien satu warna dengan benar”
Lalu, jika item menu diarahkan atau memiliki .active
kelas, kita buat tingginya sama dengan 100%
. Perhatikan penggunaan penundaan di sini untuk memastikan pertumbuhan terjadi setelah penyusutan.
Terakhir, kita perlu menangani kasus khusus dengan .active
barang. Jika kita mengarahkan item apa pun (yaitu bukan yang aktif), lalu .active
item mendapat efek melalaikan (ketinggian gradien sama dengan 0%
). Itulah tujuan dari pemilih ketiga dalam kode.
Animasi pertama kita selesai! Perhatikan bagaimana pertumbuhan dimulai setelah penyusutan selesai karena penundaan yang kita tentukan di pemilih kedua.
Animasi penentuan posisi jangkar
Animasi pertama cukup mudah karena setiap item memiliki animasi latar belakangnya sendiri, artinya kita tidak perlu peduli dengan konten teks karena latar belakang secara otomatis memenuhi seluruh ruang.
Kami akan menggunakan satu elemen untuk animasi kedua yang meluncur di antara semua item menu sambil menyesuaikan lebarnya agar sesuai dengan teks setiap item. Di sinilah posisi jangkar dapat membantu kita.
Mari kita mulai dengan kode berikut:
ul:before {
content:"";
position: absolute;
position-anchor: --li;
background: red;
transition: .2s;
}
ul li:is(:hover, .active) {
anchor-name: --li;
}
ul:has(li:hover) li.active:not(:hover) {
anchor-name: none;
}
Untuk menghindari penambahan elemen tambahan, saya lebih suka menggunakan elemen semu di ul
. Itu harus diposisikan secara mutlak dan kita akan mengandalkan dua properti untuk mengaktifkan posisi jangkar.
Kami mendefinisikan jangkar dengan anchor-name
milik. Saat item menu diarahkan atau memiliki .active
kelas, itu menjadi elemen jangkar. Kita juga harus melepas jangkar dari .active
item jika item lain dalam keadaan melayang (karenanya, pemilih terakhir dalam kode). Dengan kata lain, hanya satu jangkar yang ditentukan dalam satu waktu.
Kemudian kita menggunakan position-anchor
properti untuk menghubungkan elemen semu ke jangkar. Perhatikan bagaimana keduanya menggunakan notasi yang sama --li
. Ini mirip dengan bagaimana, misalnya, kita mendefinisikannya @keyframes
dengan nama tertentu dan kemudian menggunakannya di dalam sebuah animation
milik. Ingatlah bahwa Anda harus menggunakan itu
sintaksisartinya nama harus selalu diawali dengan dua tanda hubung (--
).
Elemen semu ditempatkan dengan benar tetapi tidak ada yang terlihat karena kami tidak menentukan dimensi apa pun! Mari tambahkan kode berikut:
ul:before {
bottom: anchor(bottom);
left: anchor(left);
right: anchor(right);
height: .2em;
}
Itu height
properti itu sepele tapi anchor()
adalah pendatang baru. Begini cara Juan Diego menggambarkannya di Almanak:
CSSnya
anchor()
fungsi mengambil sisi elemen jangkar dan memutuskan kedi mana posisinya. Ini hanya dapat digunakan di properti inset (mis
top
,bottom
,bottom
,left
,right
dll.), biasanya untuk menempatkan elemen dengan posisi absolut relatif terhadap jangkar.
Mari kita periksa halaman MDN demikian juga:
Itu
anchor()
CSS fungsi dapat digunakan dalam elemen yang diposisikan jangkar sisipkan properti nilai, mengembalikan nilai panjang relatif terhadap posisi tepi elemen jangkar terkait.
Biasanya kami menggunakan left: 0
untuk menempatkan elemen absolut di tepi kiri blok yang memuatnya (yaitu, leluhur terdekat yang memiliki position: relative
). Itu left: anchor(left)
akan melakukan hal yang sama tetapi alih-alih blok yang memuatnya, ia akan mempertimbangkan elemen jangkar terkait.
Itu saja — kita sudah selesai! Arahkan item menu pada demo di bawah ini dan lihat bagaimana elemen semu meluncur di antara item tersebut.
Setiap kali Anda mengarahkan kursor ke item menu, item tersebut menjadi jangkar baru untuk elemen semu (the ul:before
). Ini juga berarti bahwa anchor(...)
nilai akan berubah menciptakan efek geser! Jangan lupakan penggunaan transisi yang penting, jika tidak, kita akan mengalami perubahan mendadak.
Kita juga dapat menulis kode secara berbeda seperti ini:
ul:before {
content:"";
position: absolute;
inset: auto anchor(right, --li) anchor(bottom, --li) anchor(left, --li);
height: .2em;
background: red;
transition: .2s;
}
Dengan kata lain, kita dapat mengandalkan inset
singkatan daripada menggunakan sifat fisik seperti left
, right
Dan bottom
dan bukannya mendefinisikan position-anchor
kita dapat memasukkan nama jangkar di dalamnya anchor()
fungsi. Kami mengulangi nama yang sama tiga kali yang mungkin tidak optimal di sini tetapi dalam beberapa situasi, Anda mungkin ingin elemen Anda mempertimbangkan beberapa jangkar, dan dalam kasus seperti itu, sintaksis ini akan masuk akal.
Menggabungkan kedua efek tersebut
Sekarang, kami menggabungkan kedua efek dan, Kemudianilusi itu sempurna!
Perhatikan nilai transisi dimana penundaan penting:
ul:before {
transition: .2s .2s;
}
ul li {
transition: .2s;
}
ul li:is(:hover,.active) {
transition: .2s .4s;
}
ul:has(li:hover) li.active:not(:hover) {
transition: .2s;
}
Kami memiliki rangkaian tiga animasi – mengecilkan tinggi gradien, menggeser elemen semu, dan menambah tinggi gradien – jadi kami perlu ada penundaan di antara keduanya untuk menyatukan semuanya. Itu sebabnya untuk menggeser elemen semu kita memiliki penundaan yang sama dengan durasi satu animasi (transition: .2 .2s
) dan untuk bagian yang sedang tumbuh, penundaannya sama dengan dua kali durasinya (transition: .2s .4s
).
Efek melenting? Mengapa tidak?!
Mari kita coba animasi mewah lainnya di mana persegi panjang yang disorot berubah menjadi lingkaran kecil, melompat ke item berikutnya, dan berubah kembali menjadi persegi panjang lagi!
Saya tidak akan menjelaskan terlalu banyak untuk contoh ini karena tugas Anda adalah membedah kodenya! Saya akan menawarkan beberapa petunjuk sehingga Anda dapat mengungkap apa yang terjadi.
Seperti efek sebelumnya, kami memiliki kombinasi dua animasi. Untuk yang pertama, saya akan menggunakan elemen semu dari setiap item menu di mana saya akan menyesuaikan dimensi dan border-radius
untuk mensimulasikan morphing. Untuk animasi kedua, saya akan menggunakan ul
elemen semu untuk membuat lingkaran kecil yang saya pindahkan di antara item menu.
Berikut adalah versi demo lainnya dengan warna berbeda dan transisi lebih lambat untuk memvisualisasikan setiap animasi dengan lebih baik:
Bagian yang sulit adalah efek lompatan saat saya menggunakan yang aneh cubic-bezier()
tapi saya punya artikel mendetail di mana saya menjelaskan tekniknya di artikel Trik CSS saya “Penggunaan Animasi CSS Tingkat Lanjut cubic-bezier()
”.
Kesimpulan
Saya harap Anda menikmati eksperimen kecil ini menggunakan fitur penentuan posisi jangkar. Kami hanya melihat tiga properti/nilai tetapi itu cukup untuk mempersiapkan Anda menghadapi fitur baru ini. Itu anchor-name
Dan position-anchor
properti adalah bagian wajib untuk menghubungkan satu elemen (sering disebut elemen “target” dalam konteks ini) ke elemen lain (yang kita sebut elemen “jangkar” dalam konteks ini). Dari sana, Anda memilikinya anchor()
berfungsi untuk mengontrol posisi.
Terkait: Panduan Pemosisian Jangkar CSS