Membuat Menu Drop-Down Untuk Halaman Mobile



Di tutorial ini kita akan membuat dan menganimasikan ikon menu hamburger dan kemudian melampirkan event listener melalui jQuery untuk melakukan proses trigger pada menu drop-down.

Saya akan menggunakan Jade (Pug) dan Sass dari pada menggunakan vanilla HTML dan CSS. Jadi Anda setidaknya harus memiliki pengetahuan dasar tentang template engine ini.


Kita akan mulai dengan implementasi area bermain yang sederahana. Saya hanya akan menyediakan template Jade bersama dengan styling menggunakan Sass, karena ini bukan ruang lingkup dari tutorial. Anda dapat mengambil dan menggunakannya atau Anda dapat memanipulasi dengan desain Anda sendiri.

Baca Juga : CodeIgniter ( Penanganan dan Validasi Form )


File Jade:

1:  body  
2:    #container  
3:      #header  
4:      #body  
5:        .content  
6:          .left  
7:          .right  
8:            - for (i=1; i <= 5 ; i++ )  
9:              div( id="text" + i )  
10:        .content  
11:          .left  
12:          .right  
13:            - for (j=6; j <= 10 ; j++ )  
14:              div( id="text" + j )  
15:        .content  
16:          .left  
17:          .right  
18:            - for (k=11; k <= 15 ; k++ )  
19:              div( id="text" + k )  

File Sass:

1:  =flex()  
2:   display: -webkit-box  
3:   display: -moz-box  
4:   display: -ms-flexbox  
5:   display: -webkit-flex  
6:   display: flex  
7:  =transition($time)  
8:   -webkit-transition: all $time ease  
9:   -moz-transition: all $time ease  
10:   -ms-transition: all $time ease  
11:   -o-transition: all $time ease  
12:   transition: all $time ease  
13:  html, body  
14:   margin: 0  
15:   padding: 20px 0  
16:   +flex()  
17:   justify-content: center  
18:  //----------------------------------//  
19:  #container  
20:   width: 320px  
21:   height: 550px  
22:   background-color: #ebebeb  
23:   overflow: hidden  
24:  #header  
25:   height: 45px  
26:   background-color: #9b9b9b  
27:   position: relative  
28:  #body  
29:   padding: 0 20px  
30:   padding-top: 40px  
31:   +flex()  
32:   flex-direction: column  
33:   justify-content: flex-start  
34:  .content  
35:   +flex()  
36:   flex-direction: row  
37:   justify-content: flex-start  
38:   margin-bottom: 25px  
39:   .left  
40:    width: 100px  
41:    height: 100px  
42:    margin-right: 15px  
43:    background-color: #e1e1e1  
44:   .right  
45:    @for $i from 1 through 15  
46:     #text#{$i}  
47:      margin-top: 10px  
48:      width: 50 + random(100) + px  
49:      height: 10px  
50:      background-color: #e1e1e1  

Catatan: Di sini saya membuat dua mixin yang bernama flex dan transition. Mixins mempermudah penggunaan kembali beberapa aturan CSS dengan mengelompokkan mereka. Setiap kali saya perlu menambahkan display:flex dengan semua awalan vendor, sebagai gantinya saya bisa menggunakan +flex(), ini berkat adanya mixin.

Kita akan menggunakan struktur ini dan membangunnya untuk sisa tutorial.

Hasil akhir akan terlihat seperti ini:





Untuk Melihat Source Code Lengkapnya Disini




Sekarang saatnya untuk membuat menu hamburger sederhana namun menarik dan menghidupkannya melalui CSS.

Tambahkan div baru didalam #header dan berikan nama #hamburger. Kemudian membuat dua div children di dalam #hamburger. Mereka harus memiliki class yang umum dan ID yang bersifat individu.

1:  #hamburger  
2:    .strip#top  
3:    .strip#bottom  


Sekarang kita perlu memberi style pada parent div #hamburger dan div children dengan class umum .strip.

1:  #hamburger  
2:   height: 100%  
3:   width: 45  
4:   +flex()  
5:   flex-direction: column  
6:   justify-content: space-between  
7:   padding-left: 20px  

Kita mengatur tinggi div sama dengan parent div, yaitu #header, dengan menentukan height:100%. Juga, kita menetapkan nilai lebar untuk div parent ini, yang akan menentukan wilayah "yang dapat diklik".

Selanjutnya, kita menambahkan flexbox dengan semua awalan vendor dengan menggunakan mixin, yang kita buat sebelumnya.

Karena kita ingin div .strip kita diposisikan secara vertikal, kita menetapkan flex-direction: column dan kemudian menggunakan justify-content: space-between untuk menempatkan spasi di antara div .strip.

Kemudian kita perlu mendorong div tersebut terhadap satu sama lain dengan menambahkan padding bawah dan atas ke div masing-masing.

1:  #top  
2:   margin-top: 17px  
3:  #bottom  
4:   margin-bottom: 17px  

Kita juga menambahkan padding-left: 20px untuk memindahkan div .strip lebih jauh ke kanan.

Hal berikutnya adalah menambahkan style pada strip. Ini relatif mudah dengan hanya mendefinisikan ukuran dan warna dari div.

1:  .strip  
2:   width: 25px  
3:   height: 2px  
4:   background-color: #ffffff  

Hasil akhir dengan ikon menu hamburger akan terlihat seperti ini:



Hal berikutnya adalah menganimasikan ikon menu sehingga ketika diklik, seharusnya akan melakukan animasi menjadi tanda silang.


Pada tahap ini, kita akan menggunakan jQuery dasar untuk beralih ke beberapa classs CSS.
Pertama mari kita buat class CSS yang akan diubah.

Kita akan menggunakan utilitas translate dan rotate dari properti transform CSS bersama dengan properti transition.

Pertama, tambahkan transisi ke div #top dan #bottom dengan menggunakan mixins dengan parameter timing tertentu.

1:  #top  
2:   margin-top: 17px  
3:   +transition(.25s)  
4:  #bottom  
5:   margin-bottom: 17px  
6:   +transition(.25s)  

Sekarang kita perlu mendefinisikan style dari class yang akan dilakukan proses toggle.

Kita akan melakukan proses rotate dan translate dari masing-masing .strip div secara individual, jadi kita perlu mengubah class yang berbeda baik untuk div #top dan #bottom.

1:  #top  
2:   margin-top: 17px  
3:   +transition(.25s)  
4:   &.topRotate  
5:    transform-origin: center  
6:    transform: translateY(4px) rotateZ(45deg)  
7:  #bottom  
8:   margin-bottom: 17px  
9:   +transition(.25s)  
10:   &.bottomRotate  
11:    transform-origin: center  
12:    transform: translateY(-5px) rotateZ(-45deg)  

Di sini kita mendefinisikan styling untuk dua kelas yang berbeda bernama .bottomRotate dan .topRotate, yang akan ditambahkan dan dihapus dari div referensi masing-masing, #top dan #bottom.

Perhatikan bahwa ukuran yang berbeda dari kelas .strip akan menghasilkan kebutuhan untuk nilai translateY dan rotateZ yang berbeda untuk melakukan animasi menjadi tanda silang yang tepat.


Kita mendefinisikan bagaimana setiap .strip div akan melakukan animasi ketika class topRotate dan bottomRotate hadir. Namun, kita belum melampirkan event listener untuk melakukan proses toggle terhadap class tersebut.

Buatlah file JavaScript baru dan gunakan kode berikut untuk mengaktifkan class topRotate dan bottomRotate ke div dengan ID #top dan #bottom masing-masing.

1:  $(document).ready(function(){  
2:   $("#hamburger").click(function(){  
3:     $("#top").toggleClass("topRotate");  
4:     $("#bottom").toggleClass("bottomRotate");  
5:   });  
6:  })  

Kita menyimpan semua kode kami di dalam $(document) .ready(function() { ... }) untuk menunggu seluruh halaman dimuat sebelum mengambil tindakan apa pun.

Ketika kita klik div #hamburger, itu akan mengalihkan class untuk div dengan ID khusus.

Catatan: Jangan lupa untuk menambahkan sumber file jQuery ke dalam proyek Anda.

Lihatlah kode saat ini


Langkah selanjutnya adalah membuat menu dengan daftar item.

Gunakan struktur berikut di bawah #header:

1:  #dropDown  
2:    #background  
3:    ul  
4:      li Home  
5:      li Blog  
6:      li Projects  
7:      li Authors  
8:      li Jobs  
9:      li Contact  

Jadi di sini kita menggunakan tag ul sebagai induk untuk mengelompokkan item dengan li tag sebagai children. Selain itu, untuk membuat animasi background yang meluas, kita juga menambahkan div dengan ID #background.

Mari kita styling element ul dan li terlebih dahulu.

1:  ul  
2:   list-style: none  
3:   padding: 0  
4:   margin: 0  

Mengatur list-style menjadi none untuk menghapus style bullet dari elemen ul dan juga mengatur padding dan margin ke 0 untuk menghapus semua nilai yang telah ditentukan.

Sekarang mari kita styling elemen li :

1:  li  
2:    //display: none  
3:    background-color: #9b9b9b  
4:    color: #ffffff  
5:    font-family: 'Quicksand', sans-serif  
6:    font-weight: lighter  
7:    font-size: 15px  
8:    padding: 20px  
9:    padding-left: 60px  
10:    &:after  
11:     position: absolute  
12:     content: ''  
13:     left: 60px  
14:     width: 60%  
15:     height: 1px  
16:     bottom: 4px  
17:     background: rgba(255, 255, 255, 0.25)  
18:    &:last-child:after  
19:     width: 0  

Di sini saya memberikan komentar menjadi display:none agar bisa melihat hasilnya. Namun, ketika proses animasi, kita akan menggunakan kondisi awal yaitu menyembunyikan elemen list.

Saya juga menambahkan pseudo-element after dan memberikan style pada element tersebut untuk memisahkan setiap element li agar sesuai dengan garis lurus. :last-child:after menghapus baris ini untuk elemen li yang terakhir.

Lihatlah kode saat ini
 

Sekarang kita akan menggunakan beberapa control directive pada Sass untuk menambahkan animasi CSS keyframe dengan atribut yang berbeda pada setiap element li.

1:  @keyframes drop  
2:   0%  
3:    opacity: 0  
4:    transform: scale(1.3)  
5:   100%  
6:    opacity: 1  
7:    transform: scale(1)  
8:  @keyframes fold  
9:   0%  
10:    opacity: 1  
11:    transform: scale(1)  
12:   100%  
13:    opacity: 0  
14:    transform: scale(0.7)  

Di sini kita mendefinisikan animasi keyframe dengan nama drop and fold.

drop adalah untuk memberikan animasi saat pembukaan list menu. Skala awal adalah 30% lebih, dan skala akan kembali ke ukuran semula ketika transparansi berjalan dari 0 hingga 1. Tindakan sebaliknya terjadi dalam fold.

Sekarang kita perlu melampirkan keyframe tersebut ke elemen li. Pada bagian ini menggunakan Sass menjadi sangat berguna.

1:  @for $i from 1 through 6  
2:   li:nth-child(#{$i})  
3:    animation:  
4:     name: fold  
5:     duration: 80ms*(6-$i) + 1ms  
6:     timing-function: ease-in-out  
7:     fill-mode: forwards  
8:   li.anim:nth-child(#{$i})  
9:    animation:  
10:     name: drop  
11:     duration: 100ms*$i  
12:     timing-function: ease-in-out  
13:     fill-mode: forwards  

Di sini saya menggunakan for loop yang berjalan dari 1 hingga 6 dengan index $i.
Sekarang kita perlu menggunakan index tersebut untuk melampirkan setiap animasi ke elemen li dengan durasi yang berbeda.

Pertama, perhatikan baris li.anim:nth-child(#{$i}).

Di sini kita meraih variabel $i selector th child dari elemen li dengan class anim.

Kita akan mengubah class anim ini. Jadi, ketika ditambahkan ke elemen li, keyframe animasi dengan nama drop akan mengambil tindakan. Ketika dihapus, animasi fold yang akan mengambil tindakan.

Hal penting berikutnya adalah atribut duration.

duration: 100ms*$i untuk animasi drop memperpanjang durasi animasi untuk setiap nomor yang bertambah. Jadi, ketika kode ini dikompilasi, li yang pertama akan memiliki duration: 100ms, dan untuk li terakhir akan memiliki duration: 600ms.

Ini akan memberikan animasi pada setiap elemen satu demi satu.

Kita melakukan hal yang sama untuk animasi fold. Kali ini, elemen terakhir harus memiliki animasi yang lebih cepat, maka durasinya menjadi duration: 80ms*(6-$ i) + 1ms. 1ms ditambahkan ke durasi karena fakta bahwa ketika Anda mengatur durasi ke 0, beberapa masalah mungkin terjadi, dan animasi Anda mungkin tidak berfungsi dengan baik.

Saat kita melakukan styling elemen li, saya menyebutkan bahwa kita perlu menggunakan display:none untuk menghindari pemutaran animasi yang tidak diinginkan. Jika Anda tidak mengaturnya menjadi none, Anda akan melihat bahwa animasi fold dijalankan sekali ketika halaman dimuat.

Jika kita mengatur properti display ke none, kita tidak akan melihat itu, dan kemudian kita perlu menunjukkan elemen li sebelum beralih menjadi classanim.

Kita ingin animasi dimainkan saat kami mengeklik ikon hamburger. Jadi mari kita gunakan beberapa jQuery untuk mengatur properti display dari setiap item li menjadi bernilai block dan juga mengganti class anim.

1:  $(document).ready(function(){  
2:   $("#hamburger").click(function(){  
3:     $("#top").toggleClass("topRotate");  
4:     $("#bottom").toggleClass("bottomRotate");  
5:     $("li").show();  
6:     $("li").toggleClass("anim");  
7:   });  
8:  })  

Lihatlah kode saat ini

Anda akan melihat bahwa kita dapat melihat animasi pada masing-masing elemen li secara individual. Namun, kita lebih suka jika menu menjadi meluas.

Untuk memperbaikinya, kita hanya perlu memperluas ketinggian div. Div itu adalah #background, yang awalnya kami tambahkan saat membuat elemen ul dan li.

1:  #background  
2:   width: 100%  
3:   height: 0  
4:   background-color: #9b9b9b  
5:   position: absolute  
6:   +transition(.45s)  
7:   &.expand  
8:    height: 550px  

Kita akan mengubah class expand untuk mengatur atribut height ke 550px dalam .45s. Perhatikan bahwa saya menggunakan transition mixin untuk menentukan transisi dengan parameter waktu tertentu.

Hasil Akhir


Sepanjang tutorial ini, kita berlatih bagaimana menggunakan loop dalam HTML dan CSS melalui template engine Jade dan Sass. Selain itu, kita membuat animasi CSS keyframe dan melampirkannya dengan atribut durasi yang berbeda untuk elemen HTML tertentu. Lalu kita menukar kelas dengan jQuery untuk mengontrol animasi tersebut.

Oke, mungkin itu saja untuk tutorial kali ini, See You Next Time :).