Адаптивное Retina-меню
16 мая 2013 | Опубликовано в css | 1 Комментарий »
Сегодня мы будем создавать яркое меню для Retina-дисплеев. В зависимости от размера окна браузера меню будет автоматически изменять раскладку. Это десктопная версия — обычное расположение меню, двухколоночное меню для планшетов и мобильная версия со скрытой навигацией. Чтобы адаптировать меню под retina-дисплеи и избежать пикселизации при изменении размеров, мы будем использовать шрифты-иконки. Также обратите внимание, что некоторые эффекты работают только в браузерах, которые поддерживают соответствующие свойства CSS.
Подготовка шрифта-иконки
Создание собственных шрифтов-иконок может показаться достаточно сложным, но с помощью IcoMoon делать это намного проще. В шрифте-иконке, аналогично как ив любом шрифте, можно легко изменить цвет, настроить размер и он, в свою очередь, не будет пикселизированным. Такой шрифт отлично подойдет для Retina-дисплеев, так как отпадает необходимость использовать разные наборы для разных разрешений.
Первое, что нам нужно сделать — создать иконки для меню. Автор использовал иллюстратор, но для этого отлично также подойдет любой векторный редактор. Нам нужно создать иконку и экспортировать их в SVG. После этого мы можем импортировать их и использовать ресурс App IcoMoon:
Также мы можем выбирать наши шрифты с большой библиотеки, которую предлагает coMoon. После того, как мы получили все нужные иконки, мы нажимаем на кнопку “Font” в нижней части страницы и переходим к настройкам. Здесь мы можем выбирать параметры кодирования шрифта и назначать определенные буквы для каждой иконки. Нам вполне достаточно будет начальных настроек.
Первое, что нужно сделать — скопировать css код, который предоставляет ресурс, и вставить в наш файл CSS. Также нужно не забыть проверить правильно прописанные пути и скопировать папку с самими шрифтами.
HTML
HTML разметка нашего меню будет выглядеть следующим образом:
<nav id="menu" class="nav"> <ul> <li> <a href="#" title=""> <span class="icon"> <i aria-hidden="true" class="icon-home"></i></span><span>Home</span> </a> </li> <li> <a href="#" title=""><span class="icon"> <i aria-hidden="true" class="icon-services"></i></span><span>Services</span></a> </li> <li> <a href="#" title=""><span class="icon"><i aria-hidden="true" class="icon-portfolio"></i></span><span>Portfolio</span></a> </li> <li> <a href="#" title=""><span class="icon"><i aria-hidden="true" class="icon-blog"></i></span><span>Blog</span></a> </li> <li> <a href="#" title=""><span class="icon"><i aria-hidden="true" class="icon-team"></i></span><span>The team</span></a> </li> <li> <a href="#" title=""><span class="icon"><i aria-hidden="true" class="icon-contact"></i></span><span>Contact</span></a> </li> </ul> </nav>
Для использования иконок мы объявляем класс “icon-iconname” внутри тега i (для этого также отлично подойдет span). Также обратите внимание, что в тело мы также добавляем класс no-js, который будем изменять с помощью Modernizr на js.
Идея заключается в том, чтобы меню оставалось открытым в том случае, если в браузерах отключен JavaScript. Также Modernizr будем использовать для обнаружения сенсорных устройств.
CSS & JAVASCRIPT
Здесь мы на будем рассматривать префиксы CSS3, но вы из сможете найти в сходных файлах.
Стили, который будут применены для всех типов экранов следующие:
/* 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); }
Первое, что мы сделаем — увеличим прозрачность для всех иконок, за исключение той, на которую наведен курсор:
/* 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); }
Далее Для фона элементов добавляем цвета. Для выбора элементов списка будем использовать nth-child. Если вы будете добавлять элементы списка — цвет будет повторятся.
.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); }
Для экранов размерами больше 800px (50em, размер шрифта 15px) используем медиа-запрос min-width, наша навигация будет преобразовываться в горизонтальную.
@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; }
Продолжаем использовать nth-child, чтобы добавить к пунктам меню различные цвета и четырех пиксельную рамку. Рамка будет применяться не только при наведении, но и на focus и active для возможности работы на сенсорных устройствах.
/* 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); }
Размещаем иконки и текст:
/* Placing the icon */ .icon { padding-top: 1.4em; } .icon + span { margin-top: 2.1em; transition: margin .5s; }
Анимируем высота элементов при наведении:
/* 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; }
Позиционируем иконки:
/* 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; }
Добавляем визуальный эффект (изменяем размера тени и переход от полупрозрачного до непрозрачного) и закрываем первый медиа-запрос.
/* 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; } }
Вписываем второй медиа-запрос для экранов от 800 до 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; } }
Когда мы закончили со стилями для десктопных версий, переходим к стилям для экранов, размеры которых меньше 800px ( здесь 49.938em ), используя свойство max-width.
/* 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; } }
Для размеров экрана между 520px (32.5em) и 799px (49.938em) меню будем размещать в 2 столбца и по три элемента в каждом.Добавляем отступы padding. Иконку теперь будем размещать слева, текст справа.
/* CSS for a 2×3 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; }
Анимация, которую мы использовали для больших экранов, достаточно сложная, поэтому менб будем адаптировать и делать проще.
/* 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); } }
Изменяем размер шрифта и ширину.
/* 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; } }
Для очень маленьких экранов, мы прячем навигацию под кнопкой "Меню" , и пользователь сам сможет выбрать, хочет ли он, чтобы меню отображалось или нет. Чтобы сделать это, будем использовать 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','<button type="button" id="menutoggle" class="navtoogle" aria-hidden="true"><i aria-hidden="true" class="icon-menu"> </i> Menu</button>'); // Toggle the class on click to show / hide the menu document.getElementById('menutoggle').onclick = function() { changeClass(this, 'navtoogle active', 'navtoogle'); }
Для более чистого кода HTML, создаем кнопку «Меню» и вставляем ее в DOM, используя JavaScript. Функция changeClass помогает нам переключаться между активным классом и классом, когда пользователь нажимает на кнопку.
Стили для кнопки меню:
/* 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; }
По умолчанию кнопка меню скрыта. Мы хотим отобразить ее для экранов с размерами не более 519px (32.438em ):
@media (max-width: 32.438em) { /* Unhiding the styled menu link */ .nav .navtoogle{ margin: 0; display: block; }
Анимируем высоту навигации при нажатии кнопки. Для скрытой навигации объявляем высоту — 0em, для открытой — 30em max-heigh. При отключенном JavaScript, кнопку мы отображать не будем, так как используем класс no-js
и наша навигация будет отображаться всегда.
/* 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; }
При включенном JavaScript меню будет скрыто по умолчанию и будет отображаться при нажатии кнопки.
/* 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; }
Адаптируем макета для небольших экранов, представляя навигацию со списком элементов с иконкой слева от текста.
/* 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; }
Также добавляем рамку размером в 8px возле каждого элемента.
/* 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); }
При использовании навигации на мобильных устройствах, могут возникнуть трудности. Поэтому будем использовать Modernizr, который позволяет обнаружить сенсорные устройства. Если устройство сенсорное, добавляем класс touch. Это позволит сделать элементы навигации крупнее, что обеспечит пользователю более легкое касание. Закрываем последний медиа-запрос.
/* make the nav bigger on touch screens */ .touch .nav a { padding: 0.8em; } }
Вот и все! У нас получилась неплохое навигационное retina-меню, которое отлично будет работать на десктопных, планшетных и мобильных устройствах.
Автор: STÉPHANIE WALTER
Перевод — Дежурка