Hari ini kita akan membuat Retina-siap dan responsif menu berwarna-warni terinspirasi oleh warna-warna produsen Maliwan dari permainan Borderlands. Menu secara otomatis berubah ke salah satu dari tiga layout yang berbeda tergantung pada ukuran jendela browser: a "desktop" versi inline, dua kolom versi tablet-dioptimalkan dan versi mobile dengan link menu untuk menampilkan dan menyembunyikan navigasi untuk layar yang lebih kecil. Untuk membuat menu penuh retina-siap, kita akan menggunakan font ikon sehingga ikon menu tidak akan pixelized di resize.
Preparing the icon font
Membuat font ikon kustom mungkin terlihat sedikit rumit, tetapi dengan alat seperti IcoMoon itu hanya masalah menciptakan ikon dan mengimpor mereka ke dalam perangkat. Ikon font berperilaku seperti huruf apapun, sehingga Anda dapat dengan mudah mengubah warna, menyesuaikan ukuran dan tidak akan mendapatkan pixelized. Sempurna untuk perangkat retina tanpa harus menggunakan beberapa aset untuk resolusi layar yang berbeda.
Hal pertama yang perlu kita lakukan adalah untuk menciptakan ikon untuk menu. Saya menggunakan Illustrator, tetapi setiap vektor editor grafis seperti, misalnya Inkscape, akan dilakukan. Kita perlu untuk membuat setiap ikon dan ekspor mereka sebagai file SVG. Untuk memastikan ikon akan bekerja dengan baik di setiap browser, kita harus mengkonversi semua garis menjadi obyek penuh, dan menggabungkan semua benda ke dalam satu bentuk yang besar bagi setiap ikon. Setelah semua telah diekspor ke file SVG yang bagus, kita dapat mengimpor mereka ke dalam alat App IcoMoon:

Kami juga dapat meningkatkan font yang kita dengan ikon dari perpustakaan besar yang menawarkan IcoMoon. Setelah kita memiliki semua ikon yang kita butuhkan, kita klik pada "Font" tombol di bagian bawah halaman untuk memasukkan pengaturan rinci. Pada halaman ini kita dapat memilih pengaturan pengkodean untuk font, dan juga memilih jika kita ingin menetapkan beberapa surat untuk setiap ikon, atau lebih suka menggunakan Gunakan Private Area font untuk membuat layar pembaca pasti tidak akan mampu keluaran mereka. Saya sarankan menggunakan pengaturan default yang bekerja cukup baik.
Ketika kita klik "Download" kita mendapatkan file ZIP dengan 4 format font (SVG, EOT, TTF dan WOFF), styling CSS dan halaman demo.
Hal pertama yang harus dilakukan untuk dapat menggunakan ikon adalah untuk copy dan paste CSS IcoMoon menyediakan ke atas file CSS kami dan memastikan bahwa kita juga copy folder font. Ada juga sedikit "hack" untuk membuat font terlihat lebih bagus pada Chrome Windows yang Anda mungkin ingin check it out.
The HTML of the menu
HTML untuk navigation akan seperti :
Untuk menggunakan font icon, kita hanya menggunakan class "icon-iconname" di dalam elemen i (span akan bekerja dengan baik). Juga dicatat bahwa kami menambahkan kelas no-js untuk tubuh yang akan berubah menjadi js dengan Modernizr. Idenya adalah untuk dapat meninggalkan menu terbuka jika pengguna telah JavaScript dinonaktifkan. Kami juga akan menggunakan Modernizr untuk mendeteksi dukungan sentuh.
CSS & JavaScript
Perhatikan bahwa saya tidak akan awalan CSS3 properti di sini tetapi Anda akan menemukan versi diawali dalam file.
CSS global yang akan diterapkan untuk semua ukuran layar terlihat sebagai berikut:
/* Global CSS that are applied for all screen sizes */
.nav ul {
max-width: 1240px;
margin: 0;
padding: 0;
list-style: none;
font-size: 1.5em;
font-weight: 300;
}
.nav li span {
display: block;
}
.nav a {
display: block;
color: rgba(249, 249, 249, .9);
text-decoration: none;
transition: color .5s, background .5s, height .5s;
}
.nav i{
/* Make the font smoother for Chrome */
transform: translate3d(0, 0, 0);
}
/* Remove the blue Webkit background when element is tapped */
a, button {
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
Kami ingin transisi kecil pertama di seluruh navigasi yang menurunkan opacity dari semua item, kecuali satu yang sedang melayang. Ini adalah kode untuk itu:
/* Hover effect for the whole navigation to make the hovered item stand out */
.no-touch .nav ul:hover a {
color: rgba(249, 249, 249, .5);
}
.no-touch .nav ul:hover a:hover {
color: rgba(249, 249, 249, 0.99);
}
Kemudian kita ingin menambahkan beberapa warna latar belakang yang bagus untuk semua item. Kode di bawah ini menggunakan teknik n-anak untuk memilih item daftar. Dengan cara ini, Anda dapat menambahkan daftar item yang Anda inginkan, kode warna akan terulang.
.nav li:nth-child(6n+1) {
background: rgb(208, 101, 3);
}
.nav li:nth-child(6n+2) {
background: rgb(233, 147, 26);
}
.nav li:nth-child(6n+3) {
background: rgb(22, 145, 190);
}
.nav li:nth-child(6n+4) {
background: rgb(22, 107, 162);
}
.nav li:nth-child(6n+5) {
background: rgb(27, 54, 71);
}
.nav li:nth-child(6n+6) {
background: rgb(21, 40, 54);
}
Menggunakan query media yang min-lebar, kita dapat menargetkan layar yang lebih besar dari 800px (50em, dengan ukuran font tubuh 15px) untuk mengubah daftar kami menjadi navigasi horizontal bagus:
@media (min-width: 50em) {
/* Transforms the list into a horizontal navigation */
.nav li {
float: left;
width: 16.66666666666667%;
text-align: center;
transition: border .5s;
}
.nav a {
display: block;
width: auto;
}
Kami terus dengan teknik memilih n-anak, untuk menambahkan border 4px dengan warna yang berbeda untuk masing-masing item menu kita. Kami menerapkannya di hover, tetapi juga pada fokus dan aktif untuk membuatnya bekerja pada perangkat sentuh dan keyboard akses.
/* hover, focused and active effects that add a little colored border to the different items */
.no-touch .nav li:nth-child(6n+1) a:hover,
.no-touch .nav li:nth-child(6n+1) a:active,
.no-touch .nav li:nth-child(6n+1) a:focus {
border-bottom: 4px solid rgb(174, 78, 1);
}
.no-touch .nav li:nth-child(6n+2) a:hover,
.no-touch .nav li:nth-child(6n+2) a:active,
.no-touch .nav li:nth-child(6n+2) a:focus {
border-bottom: 4px solid rgb(191, 117, 20);
}
.no-touch .nav li:nth-child(6n+3) a:hover,
.no-touch .nav li:nth-child(6n+3) a:active,
.no-touch .nav li:nth-child(6n+3) a:focus {
border-bottom: 4px solid rgb(12, 110, 149);
}
.no-touch .nav li:nth-child(6n+4) a:hover,
.no-touch .nav li:nth-child(6n+4) a:active,
.no-touch .nav li:nth-child(6n+4) a:focus {
border-bottom: 4px solid rgb(10, 75, 117);
}
.no-touch .nav li:nth-child(6n+5) a:hover,
.no-touch .nav li:nth-child(6n+5) a:active,
.no-touch .nav li:nth-child(6n+5) a:focus {
border-bottom: 4px solid rgb(16, 34, 44);
}
.no-touch .nav li:nth-child(6n+6) a:hover,
.no-touch .nav li:nth-child(6n+6) a:active,
.no-touch .nav li:nth-child(6n+6) a:focus {
border-bottom: 4px solid rgb(9, 18, 25);
}
/* hover, focused and active effects that add a little colored border to the different items */
.no-touch .nav li:nth-child(6n+1) a:hover,
.no-touch .nav li:nth-child(6n+1) a:active,
.no-touch .nav li:nth-child(6n+1) a:focus {
border-bottom: 4px solid rgb(174, 78, 1);
}
.no-touch .nav li:nth-child(6n+2) a:hover,
.no-touch .nav li:nth-child(6n+2) a:active,
.no-touch .nav li:nth-child(6n+2) a:focus {
border-bottom: 4px solid rgb(191, 117, 20);
}
.no-touch .nav li:nth-child(6n+3) a:hover,
.no-touch .nav li:nth-child(6n+3) a:active,
.no-touch .nav li:nth-child(6n+3) a:focus {
border-bottom: 4px solid rgb(12, 110, 149);
}
.no-touch .nav li:nth-child(6n+4) a:hover,
.no-touch .nav li:nth-child(6n+4) a:active,
.no-touch .nav li:nth-child(6n+4) a:focus {
border-bottom: 4px solid rgb(10, 75, 117);
}
.no-touch .nav li:nth-child(6n+5) a:hover,
.no-touch .nav li:nth-child(6n+5) a:active,
.no-touch .nav li:nth-child(6n+5) a:focus {
border-bottom: 4px solid rgb(16, 34, 44);
}
.no-touch .nav li:nth-child(6n+6) a:hover,
.no-touch .nav li:nth-child(6n+6) a:active,
.no-touch .nav li:nth-child(6n+6) a:focus {
border-bottom: 4px solid rgb(9, 18, 25);
}
Then we place the icons and the text:
/* Placing the icon */
.icon {
padding-top: 1.4em;
}
.icon + span {
margin-top: 2.1em;
transition: margin .5s;
}
We animate the height of the elements when they are hovered:
/* Animating the height of the element*/
.nav a {
height: 9em;
}
.no-touch .nav a:hover ,
.no-touch .nav a:active ,
.no-touch .nav a:focus {
height: 10em;
}
/* Making the text follow the height animation */
.no-touch .nav a:hover .icon + span {
margin-top: 3.2em;
transition: margin .5s;
}
Then we position the icons and prepare them for the CSS transition:
/* Positioning the icons and preparing for the animation*/
.nav i {
position: relative;
display: inline-block;
margin: 0 auto;
padding: 0.4em;
border-radius: 50%;
font-size: 1.8em;
box-shadow: 0 0 0 0.8em transparent;
background: rgba(255,255,255,0.1);
transform: translate3d(0, 0, 0);
transition: box-shadow .6s ease-in-out;
}
To give the visuel effect we want, we transition a box shadow and
change its size from 0.8em to 0, and its color from transparent to some
color with a high opacity. This is also where we close our first
media-query.
/* Animate the box-shadow to create the effect */
.no-touch .nav a:hover i,
.no-touch .nav a:active i,
.no-touch .nav a:focus i {
box-shadow: 0 0 0px 0px rgba(255,255,255,0.2);
transition: box-shadow .4s ease-in-out;
}
}
We set a second media query to make some little adjustments for screens between 800 and 980px:
@media (min-width: 50em) and (max-width: 61.250em) {
/* Size and font adjustments to make it fit better */
.nav ul {
font-size: 1.2em;
}
}
Now that we have finished the “desktop” version (with BIG quotation
mark since more and more tablets now have 1024px and larger screens), we
take care of the “global” CSS for screens that are smaller than 800px
which equals to 49.938em here, using a max-width media query.
/* The "tablet" and "mobile" version */
@media (max-width: 49.938em) {
/* Instead of adding a border, we transition the background color */
.no-touch .nav ul li:nth-child(6n+1) a:hover,
.no-touch .nav ul li:nth-child(6n+1) a:active,
.no-touch .nav ul li:nth-child(6n+1) a:focus {
background: rgb(227, 119, 20);
}
.no-touch .nav li:nth-child(6n+2) a:hover,
.no-touch .nav li:nth-child(6n+2) a:active,
.no-touch .nav li:nth-child(6n+2) a:focus {
background: rgb(245, 160, 41);
}
.no-touch .nav li:nth-child(6n+3) a:hover,
.no-touch .nav li:nth-child(6n+3) a:active,
.no-touch .nav li:nth-child(6n+3) a:focus {
background: rgb(44, 168, 219);
}
.no-touch .nav li:nth-child(6n+4) a:hover,
.no-touch .nav li:nth-child(6n+4) a:active,
.no-touch .nav li:nth-child(6n+4) a:focus {
background: rgb(31, 120, 176);
}
.no-touch .nav li:nth-child(6n+5) a:hover,
.no-touch .nav li:nth-child(6n+5) a:active,
.no-touch .nav li:nth-child(6n+5) a:focus {
background: rgb(39, 70, 90);
}
.no-touch .nav li:nth-child(6n+6) a:hover,
.no-touch .nav li:nth-child(6n+6) a:active,
.no-touch .nav li:nth-child(6n+6) a:focus {
background: rgb(32, 54, 68);
}
.nav ul li {
transition: background 0.5s;
}
}
For screen size between 520px (32.5em) and 799px (49.938em), we want
to display our menu into a 2 columns and 3 rows layout. We add some
padding to make the elements easy to “tap”, and display the icons on the
left and the text on the right.
/* CSS for a 2x3 columns version */
@media (min-width: 32.5em) and (max-width: 49.938em) {
/* Creating the 2 column layout using floating elements once again */
.nav li {
display: block;
float: left;
width: 50%;
}
/* Adding some padding to make the elements look nicer*/
.nav a {
padding: 0.8em;
}
/* Displaying the icons on the left, and the text on the right side using inline-block */
.nav li span,
.nav li span.icon {
display: inline-block;
}
.nav li span.icon {
width: 50%;
}
.nav li .icon + span {
font-size: 1em;
}
.icon + span {
position: relative;
top: -0.2em;
}
The animation for big screen is too complex to fit into smaller
screens, so we adapt it to make it simpler and more discreet and simply
animate the border. This is where we close our media query.
/* Adapting the icons to animate the size and border of the rounded background in a more discreet way */
.nav li i {
display: inline-block;
padding: 8% 9%;
border: 4px solid transparent;
border-radius: 50%;
font-size: 1.5em;
background: rgba(255,255,255,0.1);
transition: border .5s;
}
/* Transition effect on the border color */
.no-touch .nav li:hover i,
.no-touch .nav li:active i,
.no-touch .nav li:focus i {
border: 4px solid rgba(255,255,255,0.1);
}
}
Again, for smaller screens we adapt the font-size and width.
/* Adapting the font size and width for smaller screns*/
@media (min-width: 32.5em) and (max-width: 38.688em) {
.nav li span.icon {
width: 50%;
}
.nav li .icon + span {
font-size: 0.9em;
}
}
For very small screens, we hide the navigation and display a “menu”
button the user can click if he wants to display the navigation. To do
this, we rely on some lines of JavaScript:
// The function to change the class
var changeClass = function (r,className1,className2) {
var regex = new RegExp("(?:^|\\s+)" + className1 + "(?:\\s+|$)");
if( regex.test(r.className) ) {
r.className = r.className.replace(regex,' '+className2+' ');
}
else{
r.className = r.className.replace(new RegExp("(?:^|\\s+)" + className2 + "(?:\\s+|$)"),' '+className1+' ');
}
return r.className;
};
// Creating our button for smaller screens
var menuElements = document.getElementById('menu');
menuElements.insertAdjacentHTML('afterBegin','');
// Toggle the class on click to show / hide the menu
document.getElementById('menutoggle').onclick = function() {
changeClass(this, 'navtoogle active', 'navtoogle');
}
In order to have a cleaner HTML, I chose to create the “menu” button
and insert it in the DOM using JavaScript. The function changeClass
helps us to toggle the class between active and no class when the users
clicks on the button.
Now that we have all we need for the small screen version, we can style it with CSS. The following code styles the menu button:
/* Styling the toggle menu link and hiding it */
.nav .navtoogle{
display: none;
width: 100%;
padding: 0.5em 0.5em 0.8em;
font-family: 'Lato',Calibri,Arial,sans-serif;
font-weight: normal;
text-align: left;
color: rgb(7, 16, 15);
font-size: 1.2em;
background: none;
border: none;
border-bottom: 4px solid rgb(221, 221, 221);
cursor: pointer;
}
.icon-menu {
position: relative;
top: 3px;
line-height: 0;
font-size: 1.6em;
}
By default, the menu button is hidden. We want to display it for screens smaller than 519px (
32.438em):
@media (max-width: 32.438em) {
/* Unhiding the styled menu link */
.nav .navtoogle{
margin: 0;
display: block;
}
We animate the height of the navigation when the button is clicked.
To close the navigation, we give it a 0em height, to open it, we give it
a 30em max-height. If JavaScript is not enabled, we don’t have any
button, so we use the
no-js class to always display the navigation.
/* Animating the height of the navigation when the button is clicked */
/* If JavaScript is disabled, the menu stays open */
.no-js .nav ul {
max-height: 30em;
overflow: hidden;
}
When JavaScript is enabled we hide the menu by default, and display it when the users clicks on the button which then gets the
active class:
/* When JavaScript is enabled, we hide the menu */
.js .nav ul {
max-height: 0em;
overflow: hidden;
}
/* Displaying the menu when the user has clicked on the button */
.js .nav .active + ul {
max-height: 30em;
overflow: hidden;
transition: max-height .4s;
}
We adapt the layout for smaller screens, presenting the navigation in
a list of items with the icon on the left and the text on the right
side:
/* Adapting the layout of the menu for smaller screens: icon on the left and text on the right */
.nav li span {
display: inline-block;
height: 100%;
}
.nav a {
padding: 0.5em;
}
.icon + span {
margin-left: 1em;
font-size: 0.8em;
}
We also add a 8px border on the left of each item with a nice color
/* Adding a left border of 8 px with a different color for each menu item*/
.nav li:nth-child(6n+1) {
border-left: 8px solid rgb(174, 78, 1);
}
.nav li:nth-child(6n+2) {
border-left: 8px solid rgb(191, 117, 20);
}
.nav li:nth-child(6n+3) {
border-left: 8px solid rgb(13, 111, 150);
}
.nav li:nth-child(6n+4) {
border-left: 8px solid rgb(10, 75, 117);
}
.nav li:nth-child(6n+5) {
border-left: 8px solid rgb(16, 34, 44);
}
.nav li:nth-child(6n+6) {
border-left: 8px solid rgb(9, 18, 25);
}
The navigation looks nice when testing its small version on desktop.
But on mobile devices the items might be hard to tap. Using
Modernizr we can detect the touch capability of the device. If the device has touch capabilities, a
touch
class is added to the body. We can use this class to enhance the
experience on touch devices and make the navigation items a little bit
bigger so that the user can tap them more easily. And here we close our
last media query.
/* make the nav bigger on touch screens */
.touch .nav a {
padding: 0.8em;
}
}
And that’s it, we’ve build a nice, touch-friendly and retina-ready
navigation that works fine on desktop, tablet and mobile devices. Hope
you liked it!