Bagaimana Membuat Efek Perubahan Garis Bawah Ketika Melakukan Hovering Dengan CSS Dan JavaScript
Indonesian (Bahasa Indonesia) translation by Yosef Andreas (you can also view the original English article)
Di dalam tutorial hari ini, kita akan menggunakan sedikit CSS dan JavaScript untuk membuat efek menu hover yang cantik. Itu bukan merupakan hasil akhir yang rumit, namun membuatnya akan menjadi peluang bagus untuk mempraktikkan skill paling depan kita.
Tanpa pengantar lebih jauh lagi, mari kita periksa apa yang akan kita buat:
Markup
Kita mulai dengan beberapa markup yang sangat dasar; sebuah elemen nav
yang berisi menu dan sebuah elemen span
yang kosong:
<nav class="mynav"> <ul> <li> <a href="">Home</a> </li> <li> <a href="">About</a> </li> <li> <a href="">Company</a> </li> <li> <a href="">Work</a> </li> <li> <a href="">Clients</a> </li> <li> <a href="">Contact</a> </li> </ul> </nav> <span class="target"></span>
CSS
Dengan markup yang sudah siap, berikutnya kita menentukan beberapa style dasar untuk elemen terkait:
.mynav ul { display: flex; justify-content: center; flex-wrap: wrap; list-style-type: none; padding: 0; } .mynav li:not(:last-child) { margin-right: 20px; } .mynav a { display: block; font-size: 20px; color: black; text-decoration: none; padding: 7px 15px; } .target { position: absolute; border-bottom: 4px solid transparent; z-index: -1; transform: translateX(-60px); } .mynav a, .target { transition: all .35s ease-in-out; }
Perhatikan bahwa elemen span
(.target
)
diposisikan secara absolut. Seperti yang kita lihat sesaat, kita akan menggunakan JavaScript untuk menentukan posisi tepatnya. Sebagai tambahan, itu hendaklah tampak di belakang tautan menu, sehingga kita memberikan z-index
yang negatif.
JavaScript
Pada titik ini, mari kita fokuskan perhatian kita pada JavaScript yang diperlukan. Untuk memulainya, kita menargetkan elemen yang diinginkan. Kita juga menentukan sebuah rangkaian warna yang akan kita gunakan nantinya.
const target = document.querySelector(".target"); const links = document.querySelectorAll(".mynav a"); const colors = ["deepskyblue", "orange", "firebrick", "gold", "magenta", "black", "darkblue"];
Events
Berikutnya kita mendengarkan events click
dan mouseenter
pada tautan menu.
Ketika event click
terjadi, kita mencegah halaman dari memuat ulang. Tentu saja, ini berkerja dalam kasus kita karena semua tautan memiliki atribut href
yang kosong. Namun di dalam project yang sebenarnya, tiap tautan menu akan membuka pada halaman yang berbeda.
Yang paling penting, segera setelah event mouseenter
dijalankan, fungsi callback mouseenterFunc
dieksekusi:
for (let i = 0; i < links.length; i++) { links[i].addEventListener("click", (e) => e.preventDefault()); links[i].addEventListener("mouseenter", mouseenterFunc); }
mouseenterFunc
Bagian badan fungsi mouseenterFunc
tampak seperti ini:
function mouseenterFunc() { for (let i = 0; i < links.length; i++) { if (links[i].parentNode.classList.contains("active")) { links[i].parentNode.classList.remove("active"); } links[i].style.opacity = "0.25"; } this.parentNode.classList.add("active"); this.style.opacity = "1"; const width = this.getBoundingClientRect().width; const height = this.getBoundingClientRect().height; const left = this.getBoundingClientRect().left; const top = this.getBoundingClientRect().top; const color = colors[Math.floor(Math.random() * colors.length)]; target.style.width = `${width}px`; target.style.height = `${height}px`; target.style.left = `${left}px`; target.style.top = `${top}px`; target.style.borderColor = color; target.style.transform = "none"; }
Di dalam fungsi ini kita melakukan hal berikut:
- Menambahkan class
active
pada parent langsung (li
) tautan target. - Menurunkan
opacity
dari semua tautan menu, terlepas dari yang "aktif". - Menggunakan metode
getBoundingClientRect
untuk menarik ukuran dan tautan terkait dan posisinya relatif pada viewport. - Mendapatkan warna acak dari rangkaian tersebut di atas dan melewatkan itu sebagai nilai pada properti
border-color
elemenspan
. Ingat, nilai properti awal diatur ketransparent
. - Tentukan nilai yang ditarik dari dari metode
getBoundingClientRect
pada properti masing-masing elemenspan
. Dengan kata lain, tagspan
mewarisi ukuran dan posisi tautan yang diarahkan di atasnya. - Reset transformasi default yang diterapkan pada elemen
span
. Perilaku ini hanya penting untuk pertama kalinya kita menempatkan kursor di atas sebuah tautan. Di dalam kasus ini, transformasi elemen pergi daritransform: translateX(-60px)
ketransform: none
. Itu memberikan kita efek masuk ke dalam yang bagus.
If Active
Penting untuk dicatat bahwa code di atas dieksekusi setiap kali kita mengarahkan mouse pada sebuah tautan. Karena itu juga berjalan ketika kita mengarakan mouse pada sebuah tautan "aktif". Untuk mencegah perilaku ini, kita membungkus code di atas di dalam pernyataan if
:
function mouseenterFunc() { if (!this.parentNode.classList.contains("active")) { // code here } }
Sejauh ini, demo kita tampak sebagai berikut:
Hampir, Namun Belum Cukup
Jadi, semuanya tampak berkerja seperti yang diharapkan, bukan? Nah, itu tidak benar karena jika kita melakukan scroll sepanjang halaman, atau mengubah ukuran viewport, dan kemudian mencoba untuk memilih sebuah tautan, semua bisa berantakan. Khususnya, posisi elemen span
menjadi tidak benar.
Mainkan demo halaman lengkap untuk melihat apa yang maksudkan.
Untuk menyelesaikan itu, kita harus menghitung seberapa jauh kita melakukan scroll dari bagian atas jendela dan menambahkan nilai ini ke nilai top
terkini elemen target. Di dalam cara yang sama kita hendaklah menghitung seberapa jauh dokumen dilakukan scroll secara horizontal (untuk berjaga-jaga). Nilai hasilnya ditambahkan ke nilai left
terkini elemen target.
Berikut dua baris code yang kita perbarui:
const left = this.getBoundingClientRect().left + window.pageXOffset; const top = this.getBoundingClientRect().top + window.pageYOffset;
Perlu diingat bahwa semua code di atas dijalankan segera setelah browser memproses DOM dan menemukan script terkait. Sekali lagi, untuk penerapan dan desain sendiri kamu mungkin ingin menjalankan code ini ketika halaman memuat, atau sesuatu seperti itu. Di dalam skenario seperti ini, kamu harus menempelkan itu di dalam event handler (misalnya load
)
Viewport
Hal terakhir yang harus kita lakukan adalah memastikan bahwa efek akan tetap berkerja saat kita mengubah ukuran jendela browser. Untuk mencapai ini, kita mendengarkan event resize
dan mendaftarkan event handler resizeFunc
.
window.addEventListener("resize", resizeFunc);
Berikut body handler ini:
function resizeFunc() { const active = document.querySelector(".mynav li.active"); if (active) { const left = active.getBoundingClientRect().left + window.pageXOffset; const top = active.getBoundingClientRect().top + window.pageYOffset; target.style.left = `${left}px`; target.style.top = `${top}px`; } }
Di dalam fungsi di atas, kita melakukan hal berikut:
- Memeriksa apakah ada item daftar menu dengan class
active
. Jika ada elemen seperti itu, itu menyatakan bahwa kita telah menempatkan mouse di atas tautan. - Mendapatkan properti
left
dantop
yang baru pada item "aktif" bersamaan dengan properti jendela terkait dan menempatkan mereka pada elemenspan
. Perhatikan bahwa kita menarik nilai hanya untuk properti yang berubah selama eventresize
. Itu berarti, tidak diperlukan untuk menghitung ulang lebar dan tinggi tautan menu.
Dukungan Browser
Demo ini berkerja dengan baik di dalam semua browser terbaru. Jika kamu mengalami permasalahan, silahkan beritahu saya di dalam komentar di bawah. Juga, seperti yang mungkin kamu perhatikan, kami menggunakan Babel untuk mengkompilasi code ES6 turun ke ES5.
Kesimpulan
Di dalam tip singkat ini kita melalui proses pembuatan sebuah efek hover pada menu yang sederhana namun menarik.
Saya harap kamu menikmati apa yang kami buat di sini dan mengambil inspirasi untuk mengembangkan efek menu yang bahkan lebih ampuh seperti yang tampil pada (pada saat penulisan ini) situs Stripe.
Apakah kamu pernah membuat sesuatu yang serupa? Jika demikian, pastikan untuk membagikan dengan kami tantangan yang kamu hadapi.
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post