/* When the `.menu-is-visible` class applied */ .menu-is-visible #nav {width:200px} .menu-is-visible #nav .inner {display:block} .menu-is-visible #main {margin-left:200px} /* Same with the `.menu-is-visible #nav` width */ .menu-is-visible #toggle-nav-btn {color:#aaa}
JavaScript
JavaScript ini digunakan untuk menambahkan dan melepaskan kelas .menu-is-visible pada elemen <body> secara bergantian:
(function() {
var page = document.body, btn = document.getElementById('toggle-nav-btn');
btn.onclick = function() {
// Toggle the `.menu-is-visible` class to the <body> tag based on `#toggle-btn-nav` click event page.className = (/(^| )menu-is-visible( |$)/.test(page.className)) ? page.className.replace(/menu-is-visible/,"") : page.className + " menu-is-visible";
// Toggle the toggle navigation title too... this.title = (this.title == "Show Navigation") ? "Hide Navigation" : "Show Navigation";
Kita juga bisa menggunakan plugin JQuery Toggle Sidebar untuk menampilkan dan menyembunyikan sidebar, dimana menu navigasi berada di dalam sidebar tersebut. Tapi dalam kasus ini Saya tidak menyarankannya, mengingat menggunakan JavaScript mentah saja masih bisa:
ul.tree ul li { background:transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAUAQMAAACK1e4oAAAABlBMVEUAAwCIiIgd2JB2AAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YIBhQIJYVaFGwAAAARSURBVAjXY2hgQIf/GTDFGgDSkwqATqpCHAAAAABJRU5ErkJggg==') no-repeat 0 0; }
ul.tree ul li.last, ul.tree ul li:last-child { background:white url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAUAQMAAACK1e4oAAAABlBMVEUAAwCIiIgd2JB2AAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YIBhQIIhs+gc8AAAAQSURBVAjXY2hgQIf/GbAAAKCTBYBUjWvCAAAAAElFTkSuQmCC') no-repeat 0 100%; }
Saya hanya akan menjelaskan konsep ini secara cepat dan nyaris nonverbal, jadi perhatikan dan jangan lupa untuk membaca komentar-komentar di dalam kode CSS dan HTML yang Saya tuliskan. Pada dasarnya kita hanya akan membuat menu biasa, yang kemudian kita lengkapi dengan ikon sebagai tombol penampil menu. Secara normal, ikon tersebut akan disembunyikan dan menu navigasi akan ditampilkan pada perangkat desktop/device berukuran besar, sampai ketika kita berada pada perangkat yang lebih kecil, maka CSS akan melakukan hal sebaliknya, yaitu akan menyembunyikan menu dan menampilkan ikon/navicon.
Kita membutuhkan enam buah elemen HTML yaitu <nav>, <ul>, <li>, <input type="checkbox">, <label> dan <a>
Tag HTML
Keperluan
<nav>, <ul>, <li>
Semantik. Semua navigasi standar dibangun dengan elemen ini
<a>
Setiap navigasi juga memiliki tautan-tautan yang berfungsi untuk mengarahkan pengunjung menuju sebuah tempat tertentu saat tautan-tautan tersebut diklik
<input type="checkbox">
Elemen ini digunakan untuk menampilkan dan menyembunyikan menu pada tampilan mobile. Dengan CSS3 :checked, kita bisa membuat efek toggle menggunakan elemen checkbox (baca di sini)
<label>
Elemen ini digunakan untuk keperluan visual saja. Lebih tepatnya, elemen ini akan menjadi ikon yang akan tampak sebagai tombol, padahal tombol menu yang sebenarnya adalah elemen checkbox yang disembunyikan dengan opacity:0.
Pertama-tama kita set dasar dimensi menu dengan mengatur tampilan elemen <nav> meliputi tipe font, warna latar dan huruf:
/* navigasi: tentukan font, warna huruf dan latar */ nav { font:normal bold 11px Arial,Sans-Serif; color:gray; background-color:black; height:30px; }
Kemudian set layout daftar menu menjadi horizontal. Hapus margin, padding dan bullet bawaan dari User Agent Style Sheet:
/* daftar menu: hilangkan margin, padding dan bullet */ nav ul, nav li { margin:0 0; padding:0 0; list-style:none; }
/* set tinggi menu */ nav ul {height:30px}
/* set layout menu menjadi berjajar/horizontal */ nav li { float:left; display:inline; }
Ubah semua tautan di dalam navigasi menjadi elemen blok agar lebih mudah dalam pengaturan tinggi, padding dan hal-hal lain yang kebanyakan bisa dilakukan oleh elemen blok:
/* tautan */ nav a { display:block; line-height:30px; padding:0 14px; text-decoration:none; color:white; }
Ganti juga warna item menu jika pointer mouse berada di atasnya:
/* sikap hover item menu */ nav a:hover {background-color:#39f}
Ikon Menu (Navicon)
Bentuknya seperti ini: `≡`. Simbol disamping Saya buat dengan entitas HTML ≡. Kita akan meletakkan simbol itu di dalam elemen <label> seperti ini:
<label>≡</label>
Sebenarnya ada beberapa bentuk lain yang biasa dijadikan sebagai simbol untuk menyatakan menu (baca di sini), tapi bentuk yang paling mudah dibuat dan yang paling umum digunakan adalah bentuk yang Saya tuliskan di atas.
Kali ini kita akan mengerjakan CSS elemen checkbox dan label. Secara normal tampilannya akan disembunyikan:
nav input {display:none} nav label {display:none}
Kemudian set beberapa pengaturan. Sembunyikan wujud elemen checkbox dengan mendeklarasikan opacity:0, dan atur dimensinya dengan tinggi dan lebar yang (disarankan) sama dengan tinggi menu:
/* checkbox: sebagai tombol menu pada tampian mobile */ nav input { display:none; margin:0 0; padding:0 0; width:30px; height:30px; opacity:0; /* sembunyikan wujud */ cursor:pointer; }
/* elemen label: sebagai ikon */ nav label { display:none; font-size:200%; width:30px; height:30px; /* teks berada di tengah secara vertikal dan horizontal */ line-height:30px; text-align:center; }
Media Queries
Hanya membutuhkan satu media query untuk menyatakan bahwa kita sedang berada pada perangkat mobile. Misalnya berada pada ukuran layar maksimal 767px
@media (max-width:767px) { ... }
Saat kita berada pada ukuran layar maksimal 767 piksel, set tampilan menu sebagai menu vertikal. Tampilkan ikon dan sembunyikan semua menu:
@media (max-width:767px) { nav { /* kita akan mengeset posisi menu dan ikon sebagai elemen absolut terhadap navigasi, jadi kita memerlukan deklarasi ini */ position:relative; } nav ul { background-color:#200; position:absolute; top:100%; right:0; left:0; height:auto; display:none; /* sembunyikan menu */ } /* set tampilan menu agar bersusun secara vertikal */ nav li { display:block; float:none; width:auto; } nav input, nav label { position:absolute; top:0; right:0; display:block; /* tampilkan elemen checkbox dan label */ } nav input {z-index:4} /* selalu pastikan bahwa checkbox berada di atas label */ }
Kemudian buat efek toggle dengan CSS :checked. Ubah warna ikon saat tombol menu diklik, dan tampilkan menu yang tersembunyi:
@media (max-width:767px) { ... ... /* ubah warna ikon saat tombol menu diklik, dan tampilkan menu yang tersembunyi saat checkbox dicek */ nav input:checked + label {color:white} nav input:checked ~ ul {display:block} }
/* horizontal navigation: define the navigation font and basic background */ nav { background-color:black; font:normal bold 11px Arial,Sans-Serif; color:gray; height:30px; }
/* lists: remove the nested list margin, padding & bullets */ nav ul, nav li { margin:0 0; padding:0 0; list-style:none; }
/* navigation height */ nav ul {height:30px}
/* inline layout menu */ nav li { float:left; display:inline; }
/* the anchor */ nav a { display:block; line-height:30px; padding:0 14px; text-decoration:none; color:white; }
/* hover state menu */ nav a:hover {background-color:#39f}
/* checkbox element: for mobile navigation button */ nav input { display:none; margin:0 0; padding:0 0; width:30px; height:30px; opacity:0; cursor:pointer; }
/* for visual purpose */ nav label { display:none; font-size:200%; width:30px; height:30px; /* center vertically and horizontally */ line-height:30px; text-align:center; }
/* MOBILE NAVIGATION */
@media (max-width:767px) {
nav { /* we want to absolute positioning the menu, checkbox and label element to its parent, so this is needed */ position:relative; }
nav ul { background-color:#200; position:absolute; top:100%; right:0; left:0; height:auto; display:none; /* hide the menu */ }
/* set the menu as a block list item */ nav li { display:block; float:none; width:auto; }
/* now show the checkbox and label element in mobile device */ nav input, nav label { position:absolute; top:0; right:0; display:block; /* show the menu icon */ }
nav input {z-index:4} /* always place the checkbox above the label element */
/* highlight the label element and show the menu if the checkbox is checked */ nav input:checked + label {color:white} nav input:checked ~ ul {display:block}
Dulu Saya pernah menuliskan potongan kode untuk menandai menu berdasarkan URL pada address bar dengan JQuery atau JavaScript di sini, kali ini Saya akan menggunakan tag kodisional untuk menandai menu berdasarkan persamaan URL halaman atau katakan saja pada halaman yang sedang aktif. Dengan begitu, saat Anda sedang berada pada halaman Tentang, maka menu navigasi Tentang akan berubah warna sesuai dengan pengaturan tampilan menu aktif yang Anda buat. Sebagai contoh.
Anggaplah Anda sudah memiliki menu navigasi di dalam template dengan kerangka seperti ini:
Setelah itu temukan kode </head> dan tambahkan kode-kode CSS yang berisi semua ID menu di atas. Isi selektor-selektor tersebut dengan deklarasi yang sama. Sebagai contoh, di sini Saya menuliskan warna latar hijau dan warna teks putih untuk menu yang sedang aktif:
<style type='text/css'> #home a {background-color:#0A7936;color:white;} #about a {background-color:#0A7936;color:white;} #archive a {background-color:#0A7936;color:white;} #contact a {background-color:#0A7936;color:white;} </style>
Letakkan kode di atas tepat di atas tag </head>
Mengatur Warna Menu dengan Tag Kondisional
Pada intinya kita hanya akan memecah semua selektor di atas menjadi kode CSS tunggal yang akan tampil hanya jika halaman yang sedang aktif merupakan halaman yang memiliki URL sama dengan URL pada menu. Jadi kita bisa menggunakan tag kodisional halaman khusus untuk kasus ini:
Pisahkan semua selektor item menu di atas menjadi seperti ini:
<style type='text/css'> <b:if cond='data:blog.url == "URL HALAMAN"'> #home a {background-color:#0A7936;color:white;} </b:if> <b:if cond='data:blog.url == "URL HALAMAN"'> #about a {background-color:#0A7936;color:white;} </b:if> <b:if cond='data:blog.url == "URL HALAMAN"'> #archive a {background-color:#0A7936;color:white;} </b:if> <b:if cond='data:blog.url == "URL HALAMAN"'> #contact a {background-color:#0A7936;color:white;} </b:if> </style>
Ganti kode URL HALAMAN dengan URL halaman pada menu yang terkait dengan ID menu dalam selektor CSS. Dalam contoh menu yang Saya ilustrasikan di atas, seharusnya kodenya akan menjadi seperti ini:
<style type='text/css'> <b:if cond='data:blog.url == data:blog.homepageUrl'> #home a {background-color:#0A7936;color:white;} </b:if> <b:if cond='data:blog.url == "http://test.blogspot.com/p/about.html"'> #about a {background-color:#0A7936;color:white;} </b:if> <b:if cond='data:blog.url == "http://test.blogspot.com/p/archive.html"'> #archive a {background-color:#0A7936;color:white;} </b:if> <b:if cond='data:blog.url == "http://test.blogspot.com/p/contact.html"'> #contact a {background-color:#0A7936;color:white;} </b:if> </style>
Catatan:data:blog.homepageUrl setara dengan "http://test.blogspot.com/" menurut sampel alamat blog di atas, dan juga setara dengan window.location.hostname dalam JavaScript.
Klik Simpan Template.
Alternatif Lain
Tanpa Tag Kondisional
Kita bisa membuat manipulasi ini tanpa tag kondisional, diantaranya adalah dengan cara menerapkan manipulasi JavaScript atau JQuery (baca di sini) yang lebih praktis. Tapi metode ini memiliki satu kekurangan yaitu efek tidak akan bekerja jika JavaScript dimatikan. Atau kita juga bisa menggunakan metode yang jauh lebih sederhana lagi, yaitu dengan cara menyisipkan kode CSS secara langsung ke dalam posting, sama seperti saat kita membuat posting Blogazine.
Hal yang paling penting dalam pembuatan manipulasi efek aktif pada menu sebenarnya hanya ada pada modifikasi ID atau kelas item menu agar mereka menjadi lebih spesifik/berbeda satu sama lain.
Dengan Widget Daftar Halaman (Page List)
Blogger memiliki widget bernama Daftar Laman. Dulu sebenarnya widget tersebut digunakan untuk menampilkan semua daftar tautan khusus untuk halaman statis, tapi saat ini widget tersebut sudah berkembang dan bisa ditambahi dengan tautan-tautan non-halaman statis. Dalam widget tersebut sudah terdapat peraturan kondisi tersendiri yaitu <b:if cond='data:link.isCurrentPage'> yang memiliki kemampuan untuk menambahkan kelas atau keadaan yang berbeda pada item menu jika halaman yang sedang aktif adalah halaman yang memiliki URL sama dengan URL pada menu tersebut:
Untuk menerapkan efek aktif pada menu, cukup gunakan CSS ini:
/* Versi daftar menu */ .PageList li.selected a { background-color:#0A7936; color:white; }
/* Versi selectbox */ .PageList option[selected] { font-weight:bold; }
Kekurangan manipulasi tampilan menu aktif pada widget Daftar Laman adalah kita tidak memiliki kemampuan untuk menambahkan sub-sub menu baru sebagai anak menu utama.
Eksperimen sederhana untuk menciptakan navigasi dengan efek hover menggulung dari Sohtanaka yang dulu pernah Saya tuliskan di artikel ini. Kali ini Saya hanya akan menggunakan CSS3 Transisi untuk menganimasikan efek menggulung tiap item menu:
Atribut data-clone digunakan untuk menyimpan nilai kloning yang dituliskan secara manual menggantikan fungsi .clone() dalam JQuery. Efek animasi dibuat dengan cara menganimasikan properti margin dengan CSS transisi.
Sebenarnya akan lebih baik jika dituliskan secara terpisah dalam selektor CSS eksternal seperti ini:
#nav li ul { max-height:300px; overflow-y:auto; }
Tapi untuk langkah awal (jika Anda masih belum mengerti mengenai penargetan selektor CSS dengan baik) lebih baik mulai dengan cara yang Saya tuliskan pertama kali.
Metode ke Dua: Kalkulasi Tinggi Submenu dengan JavaScript
Caranya adalah dengan menghitung tinggi layar dan menguranginya dengan jarak menu dengan bagian tepi atas layar dan tinggi menu. Hasilnya akan kita jadikan sebagai tinggi submenu:
var nav = $('#nav'), navLi = $('li', nav), winHeight = $(window).height();
// Saat pointer mouse berada di atas item menu... navLi.hover(function() { var ulHeight = $(this).children('ul').height(); // Dapatkan tinggi submenu // Tampilkan submenu dengan efek .fadeIn() $(this).children('ul').stop(true, true).fadeIn('fast'); // Batasi manipulasi tinggi submenu hanya untuk submenu dengan ukuran tinggi lebih dari tinggi layar if(ulHeight > winHeight) { $(this).children('ul').css({ // Set tinggi submenu setinggi layar dikurangi tinggi menu + offset menu sebelah atas 'height': winHeight - (nav.height() + nav.offset().top), 'overflow-y': 'auto' }); } }, function() { // Saat pointer mouse keluar dari atas item menu... // Sembunyikan submenu $(this).children('ul').hide(); });
Memadukan kalkulasi pada metode ke dua dengan konsep dasar efek paralaks. Memanfaatkan koordinat pointer mouse untuk mempengaruhi posisi elemen. Di sini kita hanya akan menggunakan koordinat sumbu-Y (selengkapnya):
var nav = $('#nav'), navLi = $('li', nav), winHeight = $(window).height();
// Saat pointer mouse berada di atas item menu... navLi.hover(function() { var ulHeight = $(this).children('ul').height(); // Dapatkan tinggi submenu // Tampilkan submenu dengan efek .fadeIn() $(this).children('ul').stop(true, true).fadeIn('fast'); // Batasi efek scroll hanya untuk submenu yang memiliki tinggi lebih besar dari tinggi layar if(ulHeight > winHeight) { // Set tinggi submenu setinggi layar dikurangi tinggi menu + offset menu sebelah atas $(this).children('ul').css({ 'height': winHeight - (nav.height() + nav.offset().top), 'overflow': 'hidden' }) // Saat pointer bergerak di atas submenu... .mousemove(function(e) { // Set margin-top elemen <li> pertama dengan nilai sebesar jarak koordinat pointer terhadap sumbu-Y // dikurangi tinggi dan offset sebelah atas menu, kemudian nilainya dikalikan 'negatif' dua untuk mempercepat gerakan // (e.pageY-$('#nav').height()-$('nav').offset().top)*-2 // [Negatif = Saat pointer bergerak ke bawah, menu akan bergerak ke atas] $(this).children('li:first').css('margin-top', (e.pageY - nav.height() - nav.offset().top)*-2); }); } }, function() { // Saat pointer mouse keluar dari atas item menu... // Sembunyikan submenu dengan efek .slideUp() dan kembalikan nilai margin dari elemen <li> yaitu = 0 $(this).children('ul').slideUp('fast').children('li:first').animate({'margin-top':0}, 400); });
Masalah yang tampak kecil tapi kita harap bisa diperbaiki adalah mengenai efek hover menu induk pada navigasi bertingkat yang akan menghilang setelah pointer memasuki submenu:
Efek hover pada menu induk menghilang saat pointer memasuki submenu
Itu terjadi karena pada umumnya kita menargetkan efek hover pada elemen tautan saja seperti ini:
nav li a:hover { background-color:blue; }
Padahal yang seharusnya kita targetkan adalah elemen list/daftar yang menjadi induk dari submenu, karena submenu berada di dalam elemen <li>, bukan di dalam elemen <a>:
Susunan Submenu
Sayangnya menargetkan elemen <li> secara sepihak untuk mempertahankan warna menu induk tidak bisa kita lakukan karena efek hover berada pada elemen <a>, sehingga saat pointer keluar dari <a> maka efek hover akan menghilang. Tapi berbeda jika kita menargetkan elemen <li> kemudian memanfaatkan sikap hover pada elemen tersebut untuk mengeset warna direct children tautan di dalamnya:
nav li a:hover, nav li:hover > a { background-color:blue; }
Dengan cara di atas maka warna pada menu induk akan tetap terjaga meskipun pointer sudah meninggalkannya. Karena meskipun sudah keluar, tapi pada dasarnya pointer masih berada di dalam elemen <li> induk:
Seringkali Saya melihat beberapa orang mencoba menuliskan semua kategori posting pada drop down menu. Mereka melakukannya secara manual. Saya pikir, seandainya Saya bisa menggunakan JSON untuk ini, maka mereka tidak perlu lagi repot-repot memperbaharui menu setiap kali label baru ditambahkan.
Tapi setelah Saya coba ternyata hasilnya proses muat halaman menjadi sangat lambat. Jadi Saya mencoba menggunakan alternatif menarik lainnya, yaitu widget recent post dan recent comment yang Saya letakkan pada menu-menu sekunder. Kita tahu bahwa kebanyakan widget semacam ini dibangun oleh elemen-elemen daftar, oleh karena itulah kita bisa menaruhnya dengan sangat pas ke dalam menu (yang juga dibangun oleh elemen-elemen daftar).
Masih sama. Halaman menjadi sedikit lebih lambat. Ya, itu terjadi karena widget-widget ini harus memanggil feed posting untuk menampilkan isi widget tersebut. Terlebih lagi, menu navigasi secara umum diletakan di bagian atas, sehingga jika proses pemuatan menu navigasi lebih lambat dari biasanya, maka peramban akan terlambat pula saat membaca elemen-elemen di bawahnya, karena peramban membaca seperti manusia, dari kiri atas menuju ke kanan bawah (Kesimpulan: Proses muat halaman menjadi lambat).
Solusi Saya adalah dengan cara meletakkan menu navigasi ini pada bagian paling bawah, tepatnya di atas </body> sehingga kita harap widget ini akan memulai proses pemuatan posting saat elemen-elemen di atasnya sudah cukup siap. Dan untuk mengangkat menu navigasi yang berada di bawah menuju ke atas, Saya menggunakan posisi absolute dengan nilai top sebesar 0:
/* Drop down menu untuk ukuran yang cukup lebar */ #autonav .wide {width:400px} </style> <script> //<![CDATA[ var numpost = 7, numcomment = 7, cmtext = "Komentar", cmsumm = 100, pBlank = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAA3NCSVQICAjb4U/gAAAADElEQVQImWOor68HAAL+AX7vOF2TAAAAAElFTkSuQmCC"; //]]> </script> <script src='http://dte-project.googlecode.com/svn/trunk/json-dropdown.js'></script>
Ini adalah perbaikan dari salah satu artikel yang sudah pernah Saya tuliskan sebelumnya. Hanya saja, karena versi yang lama tampak tidak begitu stabil jadi Saya memperbaikinya sekarang. Dengan beberapa drop-down menu tambahan yang sayangnya (menurut Saya) tidak begitu stabil. Seharusnya di sini kita memerlukan plugin hoverintent, tapi sudahlah. Artikel yang lama sudah Saya hapus T_T
Saya masih menggunakan kode dasar yang sama dari Quenees. Sedangkan inspirasi warna Saya ambil dari situs WebcamMax:
#lava li li { float:none; display:block; text-align:left; }
#lava li li a {padding:0px 15px;} #lava li li a:hover {background-color:#1E3B45;}
Setelah itu temukan kode ini:
</head>
salin script di bawah ini dan letakkan di atasnya:
<script type="text/javascript"> //<![CDATA[ // Original: http://www.queness.com/post/530/simple-lava-lamp-menu-tutorial-with-jquery // Modified by Taufik Nurrohman: http://hompimpaalaihumgambreng.blogspot.com $(function() { // Append the floating bar $('#lava').append('<div id="box"><div class="head"></div></div>') // remove the fallback class if JavaScript enabled .find('ul.fallback').removeClass('fallback'); // Retrieve the selected item position and width var default_left = Math.round($('#lava li.selected').offset().left - $('#lava').offset().left), default_width = $('#lava li.selected').width();
// Set the floating bar position and width $('#box').css({left: default_left}); $('#box .head').css({width: default_width});
// if mouseover the menu item $('#lava > ul > li').mouseenter(function() {
// Get the position and width of the menu item left = Math.round($(this).offset().left - $('#lava').offset().left); width = $(this).width();
// Set the floating bar position, width and transition $('#box').stop(false, true).animate({left:left},{duration:1000, easing:'easeOutElastic'}); $('#box .head').stop(false, true).animate({width:width},{duration:1000, easing:'easeOutElastic'}); $('ul', this).filter(':not(:animated)').slideDown(600, 'easeInOutExpo'); // if user click on the menu }).click(function() { // reset the selected item $('#lava li').removeClass('selected'); // select the current item $(this).addClass('selected'); });
// If the mouse leave the menu item, // hide the dropdown menu and reset the floating bar to the selected item $('#lava li').mouseleave(function() { $('ul', this).slideUp(600, 'easeOutQuart'); }).parents('#lava').mouseleave(function() { // Retrieve the selected item position and width default_left = Math.round($('#lava li.selected').offset().left - $('#lava').offset().left); default_width = $('#lava li.selected').width(); // Set the floating bar position, width and transition $('#box').stop(false, true).animate({left:default_left},{duration:1500, easing:'easeOutElastic'}); $('#box .head').stop(false, true).animate({width:default_width},{duration:1500, easing:'easeOutElastic'}); }); }); //]]> </script>
Terakhir, letakkan kerangka menu ini di tempat yang Anda inginkan (pelajari beberapa alternatif peletakkan menu navigasi horizontal di sini):
Kode yang Saya beri tanda digunakan untuk menentukan dimana lava akan berhenti. Di sini Saya meletakkannya di menu Komentar, itulah sebabnya mengapa lava selalu berhenti pada menu Komentar.
Ini adalah tentang bagaimana cara kita menangani masalah-masalah umum yang akan timbul pada situs-situs yang membutuhkan pengaktifan JavaScript. Katakanlah kita memiliki sebuah menu navigasi bertingkat dengan efek JavaScript. Namun biasanya syarat yang harus kita penuhi agar efek animasi berjalan dengan baik adalah dengan menghilangkan setiap item yang akan ditampilkan/disembunyikan dengan efek JavaScript:
nav ul ul { display:none; }
Anda bisa mempelajari maksud dari kode di atas pada artikel ini.
Tidak masalah (bahkan sebuah keharusan) jika kita menghilangkan elemen dengan deklarasi display:none karena JavaScript selalu bisa menampilkannya dengan efek yang baik. Tapi bagaimana jika JavaScript dinonaktifkan?
Menonaktifkan JavaScript
Kita tidak membicarakan tentang mengapa mereka melakukan itu, tapi katakanlah jika itu dilakukan, apa yang akan terjadi? Yang terjadi adalah sub-sub menu navigasi yang seharusnya muncul saat induk menu disorot akan mati karena tidak ada mesin yang bisa membuat mereka muncul kecuali JavaScript. Dan sekarang JavaScript telah dinonaktifkan.
Hal yang biasanya kita lakukan adalah menuliskan sebuah pesan yang akan muncul hanya jika JavaScript dinonaktifkan. Itu bisa dilakukan dengan <noscript>:
<noscript> <div id="js-message">Anda harus mengaktifkan JavaScript untuk melihat halaman ini!</div> </noscript>
Dan mungkin sedikit kode CSS untuk membuatnya tampak sebagai tabir yang akan menutupi seluruh layar:
Tapi Saya rasa cara itu tidak sepenuhnya keren jika setiap kali kita menonaktifkan JavaScript, sebuah tabir/overlay besar akan muncul menutupi seluruh layar. Kita harap kita bisa memberikan fallback yang baik tanpa harus menghilangkan apa yang seharusnya bisa kita lihat. Kita mencoba untuk melihat kepada CSS. Kita harap, jika JavaScript dinonaktifkan, maka CSS bisa menggantikannya untuk menampilkan/menyembunyikan elemen dengan baik, meski dengan efek yang sangat terbatas. Berikut ini adalah sebuah kerangka menu navigasi bertingkat sederhana. Terdiri dari empat menu utama dan dua level submenu:
Seperti yang Anda lihat bahwa Saya menambahkan kelas/classfallback pada masing-masing anak menu (tidak harus bernama fallback. Itu hanya contoh). Kelas tersebut akan kita gunakan pada kode CSS hanya jika JavaScript dinonaktifkan. Dalam artian: Kita akan menghilangkan kelas tersebut dengan JavaScript saat JavaScript diakifkan. Dan ini bisa dilakukan dengan cara yang sangat sederhana:
$('nav ul.fallback').removeClass('fallback');
Pada dasarnya inilah yang akan kita lakukan: Saat JavaScript dinonaktifkan, kita harap kita bisa mengakses elemen yang menghilang untuk ditampilkan dan disembunyikan dengan CSS tanpa harus mengganggu animasi JavaScript saat JavaScript diaktifkan. Itu bisa dilakukan dengan cara bergiliran. Saat JavaScript diaktifkan, kita harap kita bisa memberikan efek animasi yang baik saat sub-sub menu ditampilkan dan disembunyikan:
Namun saat JavaScript dinonaktifkan, kita tetap bisa memastikan bahwa sub-sub menu tersebut bisa tampil dan hilang dengan baik:
nav li ul { display:none; }
nav li:hover > ul.fallback { display:block; }
Gambaran Selengkapnya
Ini adalah gambaran selengkapnya. Saat JavaScript diaktifkan, maka kita akan menghilangkan kelas fallback pada semua elemen <ul>:
$('nav ul.fallback').removeClass('fallback');
Dengan begitu kode CSS pada bagian ini tidak akan bisa menampilkan dan menyembunyikan sub-sub menu, karena kelas fallback pada elemen submenu sudah menghilang:
nav li ul { /* ... */ display:none; }
nav li:hover > ul.fallback { display:block; /* Ini sudah tidak berlaku lagi, karena class="fallback" telah dihilangkan */ }
Namun itu tidak mengapa, karena saat ini JavaScript sedang diaktifkan, maka efek animasi JavaScript bisa kita dijalankan:
Dan saat JavaScript dinonaktifkan, maka fungsi-fungsi animasi dalam JavaScript tidak akan bekerja. Diutamakan pada bagian ini, sebagai perhatian utama kita:
$('nav ul.fallback').removeClass('fallback');
Oleh karena itu kelas fallback akan tetap berada pada tempatnya. Sehingga kode CSS pada bagian ini akan bekerja:
nav li:hover > ul.fallback { display:block; }
Coba Anda buka halaman ini kemudian perhatikan bahwa saat ini efek animasi .slideDown() dan .slideUp() masih bisa bekerja. Setelah itu nonaktifkan JavaScript pada peramban Anda dan segarkan halaman tersebut. Anda akan melihat bahwa sub-sub menu masih bisa ditampilkan dan disembunyikan meski dengan efek yang sangat terbatas:
$(function() { // Singkirkan class "fallback" pada anak <ul> // sehingga kode nav li:hover > ul.fallback {display:block;} tidak akan bekerja. $('ul.fallback').removeClass('fallback');
// Lakukan seperti biasa mulai dari sini... $('nav#nav li').hover(function() { $(this).children('ul').slideDown('fast'); }, function() { $(this).children('ul').slideUp('fast'); }); });
Lainnya
Selain itu, beberapa elemen seperti panel juga lebih banyak mengutamakan .hide() atau .css('display', 'none') untuk menyembunyikannya dibandingkan dengan menuliskan display:none secara langsung dengan CSS. Ini akan membuat panel tertutup saat JavaScript diaktifkan dan bisa terbuka saat sebuah pemicu (misalnya tombol) diklik. Tapi saat JavaScript dinonaktifkan, tombol-tombol tersebut tidak lagi berfungsi untuk membuka/menutup panel, sementara panel yang tadinya tertutup kini akan tetap terbuka. Kelihatannya memang jelek, tapi setidaknya kita masih tetap bisa melihat isinya.
Saat Anda mengunjungi situs Nettuts+, atau Tuts+ pasti Anda akan melihat sebuah menu melayang kecil di sebelah kiri layar. Kali ini Saya akan membuat versi yang mirip dengan itu. Pada dasarnya, cara kerjanya masih sama dengan JQuery Tooltip onClick, yaitu pada saat suatu elemen diklik, maka elemen tertentu yang telah ditentukan sebagai target akan tampil. Untuk menciptakan sedikit perbedaan, Saya telah menambahkan elemen tooltip dengan konten yang diproduksi dari teks di dalam menu:
#sidenav li ul a.social { background-image:url('social-sprites.png'); background-repeat:no-repeat; padding-left:30px !important; }
#sidenav li ul a.blogger {background-position:5px 4px; } #sidenav li ul a.facebook {background-position:5px -21px; } #sidenav li ul a.twitter {background-position:5px -47px; } #sidenav li ul a.googleplus {background-position:5px -73px; } #sidenav li ul a.flickr {background-position:5px -99px; } #sidenav li ul a.rss {background-position:5px -125px;} #sidenav li ul a.mail {background-position:5px -151px;}
Dan… sedikit kode JQuery yang merupakan pengembangan dari JQuery Tooltip onClick. Kodenya memang tampak banyak, tapi yang banyak itu pada dasarnya hanya deskripsi cara kerjanya saja:
$(function() {
// Menonaktifkan fallback CSS (Saya akan membahas ini suatu saat nanti) $('#sidenav .fallback').removeClass('fallback');
// Saat elemen <a> diklik... $('#sidenav li a[href="#"]').click(function(e) { // Hilangkan semua anak <ul> dan tooltip yang tampil $('#sidenav li ul:visible, span.ttp:visible').hide(); // Tampilkan elemen setelahnya (dalam hal ini adalah elemen <ul>) // dengan efek .show('fast') dan set nilai margin-left menjadi 10 piksel untuk menciptakan jarak $(this).next().css('margin-left', '10px').show('fast'); // Jangan biarkan event .click() pada elemen ini mempengaruhi elemen lain di dalam dokumen // Selengkapnya: http://api.jquery.com/event.stopPropagation/ e.stopPropagation(); return false; });
// Hilangkan semua anak elemen <ul> dan tooltip yang tampil saat elemen selain menu diklik $(document).click(function() { $('#sidenav li ul:visible, span.ttp:visible').hide(); });
});
Intinya adalah, saat sebuah menu diklik, maka anak menu di dalamnya akan tampil, sedangkan elemen sejenis lain yang sedang tampil akan menghilang, termasuk tooltip menu itu sendiri:
// Saat elemen <a> diklik... $('#sidenav li a[href="#"]').click(function(e) { // Hilangkan semua anak <ul> dan tooltip yang tampil $('#sidenav li ul:visible, span.ttp:visible').hide(); // Tampilkan elemen setelahnya (dalam hal ini adalah elemen <ul>) // dengan efek .show('fast') dan set nilai margin-left menjadi 10 piksel untuk menciptakan jarak $(this).next().css('margin-left', '10px').show('fast'); // Jangan biarkan event .click() pada elemen ini mempengaruhi elemen lain di dalam dokumen // Selengkapnya: http://api.jquery.com/event.stopPropagation/ e.stopPropagation(); return false; });
Kali ini Saya akan menjelaskan langkah demi langkah tentang bagaimana sebuah elemen list bisa menjadi sebuah menu navigasi dan juga submenunya. Mungkin tidak begitu detail, tapi setidaknya ini semua cukup untuk membantu Anda mempermudah memodifikasi setiap template drop down menu yang Anda dapatkan.
Pertama-tama, mungkin Anda merasa penasaran tentang bagaimana bisa sebuah elemen list/daftar bisa menjadi menu navigasi bertingkat. bagaimana bisa saat sebuah menu disentuh, beberapa menu tambahan akan muncul di bawahnya??
Dasar: Membangun Daftar
Setiap menu navigasi yang baik adalah berupa elemen <ul> yang dibungkus oleh elemen <nav>. Pertama-tama kita buat kerangka menu sederhana seperti ini:
Dari kode di atas bisa Anda bayangkan bahwa menu tersebut terdiri dari menu Beranda, Profil, Jurnal dan Komentar. Elemen <a> yang mengelilingi setiap menu adalah tautan yang digunakan untuk menentukan ke mana/ke halaman mana menu akan mengantarkan Anda saat menu tersebut diklik. (# mewakili URL halaman).
Hasil jadinya kira-kira seperti ini:
Langkah pertama, menyusun daftar menu.
Menambahkan Submenu
Setelah itu kita bisa menambahkan sub-sub daftar sebagai submenu yang nantinya akan menjadi drop down menu saat menu telah selesai dibuat. Caranya cukup dengan menyisipkan elemen <ul> baru ke dalam setiap elemen <li> yang ingin dilengkapi dengan submenu.
Penambahan submenu tidak ada batasan. Setiap elemen <li> bisa disisipi oleh elemen <ul> baru, dan setiap elemen <li> yang berada di dalam setiap elemen <ul> baru juga bisa disisipi dengan elemen <ul> yang baru lagi sebagai anak menu level 3 dan seterusnya:
Beginilah kira-kira setelah Saya menambahkan sub-sub menu pada menu Beranda, Profil, Jurnal dan Komentar. Khusus untuk menu Komentar Saya telah menambahkan satu level lagi pada salah satu anak menu:
Penambahan sub-sub daftar sebagai submenu
Metode Menampilkan dan Menghilangkan Submenu dengan CSS
Selanjutnya, kita hilangkan anak-anak menu dengan CSS. Caranya cukup dengan menargetkan elemen <ul> yang merupakan anak elemen <li> utama saja, yaitu elemen yang tidak memiliki induk selain elemen <ul> terdekat dari <nav>:
#nav li ul { display:none; }
Kode di atas akan menghilangkan elemen <ul> yang berada di dalam elemen <li> yang berada di dalam elemen <nav id='nav'>
Setelah itu kita ingin agar elemen <ul> yang merupakan anak dari elemen <li> muncul saat elemen <li> disentuh oleh pointer mouse. Ini bisa kita lakukan dengan CSS Pseudo Classes:hover
/* Hilangkan semua elemen `<ul>` yang merupakan anak dari elemen `<li>` yang berada paling dekat dengan elemen `<nav id='nav'>` */ #nav li ul { display:none; }
/* Saat pointer mouse berada di atas elemen `<li>`, ubah status elemen `<ul>` yang tadinya berupa `display:none` menjadi `display:block` */ #nav li:hover > ul { display:block; }
Kode #nav li:hover ul {display:block} sebenarnya bisa digunakan dan tampak lebih masuk akal, tapi ini adalah selektor yang tidak spesifik. Kode ini hanya efektif saat diterapkan pada menu yang hanya memiliki satu level anak menu saja. #nav li:hover > ul {display:block} lebih spesifik, karena selektor ini hanya akan mencari anak elemen <ul> yang merupakan anak pertamanya saja, sedangkan elemen <ul> yang merupakan anak dari anak level pertama tidak akan ikut mendapatkan deklarasi display:block.
Bagi Anda, mungkin ini adalah bagian yang cukup berat, yaitu saat mencoba untuk mengubah elemen daftar menjadi menu navigasi dengan orientasi horizontal. Tapi jangan khawatir. Pada dasarnya hanya ada beberapa bagian pokok saja yang harus diperhatikan, sementara yang lainnya merupakan dekorasi tambahan:
Selektor #nav umumnya hanya digunakan untuk mendeklarasikan hal-hal global seperti jenis fon menu, warna latar belakang dan warna huruf secara keseluruhan:
#nav { font:normal normal 12px/normal Arial,Sans-Serif; }
Selektor #nav li digunakan untuk mengatur penampilan elemen <li>. Di sini kita akan menghilangkan bulatan-bulatan yang berada di samping daftar dengan cara mendeklarasikan list-style:none dan juga mengatur orientasi daftar menjadi horizontal dengan mendeklarasikan float:left dan display:inline
#nav li { float:left; display:inline; list-style:none;
Atur posisi anak elmen <ul> sebagai elemen absolut dengan mendeklarasikan position:absolute. Selain itu, atur juga ukuran lebarnya. Dan juga, untuk anak-anak elemen <li> yang ada di dalamnya harus berupa elemen blok, oleh karena itu kita harus menetralkan deklarasi float:left dan display:inline pada deklarasi yang sudah kita tuliskan sebelumnya:
#nav li ul { position:absolute; top:100%; left:0; z-index:10; width:120px; display:none; }
#nav li li { float:none; display:block; }
#nav li:hover > ul { display:block; }
Dan beginilah kira-kira hasil akhirnya. Memang masih tampak berantakan, tapi kita sudah bisa membuat sistemnya berfungsi!
Pada dasarnya pekerjaan kita sudah berhasil sampai sejauh ini. Sisanya tinggal tahap penggantengan dan penambahan beberapa efek yang umum. Misalnya, saat menu-menu tersebut disentuh, kita ingin agar menu tersebut berubah warna menjadi biru tua. Kita bisa menerapkan selektor #nav a:hover {background-color:darkblue} untuk mengubah warna menu menjadi biru tua saat pointer mouse berada di atasnya:
#nav { background-color:black; color:white; font:normal normal 10px/normal Arial,Sans-Serif; text-transform:uppercase; }
#nav ul { margin:0; padding:0; height:30px; }
#nav li { /* Mengatur orientasi menu menjadi horizontal */ margin:0; padding:0; float:left; display:inline; list-style:none; position:relative; }
Secara default, setiap elemen pada dasarnya memiliki margin dan paddingnya sendiri-sendiri yang telah ditentukan oleh masing-masing CSS bawaan —User Agent Stylesheet— peramban. Oleh karena itu, kita seringkali harus menetralkan nilai margin dan padding bawaan dari peramban tersebut dengan menuliskannya di dalam selektor seperti ini:
#nav ul { margin:0; padding:0; }
#nav li { margin:0; padding:0; }
Tingkat Lanjut: JQuery untuk Menciptakan Efek
Hal pertama yang harus Anda perhatikan adalah bahwa saat kita menggunakan JavaScript untuk menciptakan efek, seringkali/disarankan agar kita menghilangkan deklarasi yang berhubungan degan :hover yang terkait langsung kepada proses pemunculan/penghilangan submenu karena proses pemuculan elemen dengan CSS terlalu cepat dan bisa mengganggu efek animasi yang seharusnya bisa ditampilkan dengan efek yang lambat.
Sebelum menerapkan JavaScript (JQuery), kita buang terlebih dahulu selektor #nav li:hover > ul dari kode CSS. Tugas pemunculan dan penghilangan submenu akan digantikan oleh JavaScript:
#nav li:hover > ul { display:block; }
JQuery
Kodenya sangat sederhana. Kita hanya akan menuliskan perintah bahwa saat pointer mouse berada di atas elemen <li>, tampilkan submenu yang ada di dalamnya dengan efek .slideDown():
$(function() { // Saat pointer mouse berada di atas menu... $('#nav li').hover(function() { // Tampilkan submenu dengan efek `.slideDown()` $(this).children('ul').slideDown('fast'); }, function() { // Sembunyikan submenu dengan efek `.slideUp()` saat pointer mouse meninggalkannya $(this).children('ul').slideUp('fast'); }); });
Saya telah membuat paket drop down menu lengkap dimulai dari menu horizontal, vertikal, drop down menu dengan submenu vertikal dan horizontal, menu terbalik, menu dengan efek JQuery dan beberapa yang lain. Ini semua adalah templat dasar yang sudah Saya buat sesederhana mungkin agar mudah dimodifikasi.