От автора: адаптивное меню для Retina с поддержкой сенсорного ввода и тремя разметками для разных размеров браузера.
Сегодня мы создадим яркое адаптивное и подходящее к экранам Retina меню, вдохновленное цветовой палитрой Maliwan, производителя игры «Borderlands». Меню автоматически изменяется под одну из трех разных разметок в зависимости от размера окна браузера: встроенную версию «десктопа», оптимизированную под «таблетку» версию с двумя колонками и мобильную версию с ссылкой на меню для отображения и сокрытия навигации для маленьких экранов. Чтобы сделать меню полностью под retina, мы применим шрифты-иконки с тем, чтобы иконки меню при изменении размера не поддавались пикселизации.
Подготовка шрифта-иконки
Создание пользовательского шрифта-иконки может показаться немного сложным, но с помощью таких инструментов, как IcoMoon дело стало только за созданием иконок и их импортом в инструмент. Шрифты-иконки ведут себя как любые шрифты, поэтому можно легко менять их цвет, подгонять размер, и они не поддаются пикселизации. Идеальны для устройств retina, и для разных разрешений экрана не нужно использовать множество объектов.
Первое, что следует сделать – это создать иконки для меню. Я пользуюсь Illustrator’ом, но подойдет любой редактор векторной графика, например, Inkscape. Нужно создать каждую иконку и экспортировать их как файл SVG. Чтобы гарантировать правильную работу иконки в любом браузере, нам нужно преобразовать все строки в целые объекты и соединить все объекты для иконки в одну большую фигуру. Когда все уже экспортировано в соответствующие файлы SVG, можно импортировать их в приложение инструмента IcoMoon:
Также можно усилить свой шрифт иконками из огромной библиотеки, предлагаемой IcoMoon. Когда все нужные нам иконки готовы, щелкаем по кнопке “Font” внизу страницы, чтобы зайти в детальные установки. На этой странице можно выбрать установки кодирования шрифта, а также выбрать, хотим ли мы назначить каждой иконке буквы, или предпочтем применить Private Use Area шрифта, чтобы читатели не смогли его вывести. Я советую использовать установки по умолчанию, которые весьма хорошо работают.
При щелчке на “Download” мы получаем файл ZIP с 4 форматами шрифта (SVG, EOT, TTF и WOFF), стили CSS и демо-страницу.
Первое, что следует сделать для использования иконок – скопировать и вставить CSS, предоставляемый IcoMoon, в верх своего файла CSS и убедиться, что папка со шрифтом тоже скопирована. Вы, возможно, захотели бы узнать о маленьком хаке сделать шрифты в окнах Chrome еще симпатичнее.
HTML-код меню
Вот как выглядит HTML нашей навигации:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<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, который изменится на js с помощью Modernizr’а. Идея состоит в том, чтобы меню оставалось открытым, если у пользователя отключен JavaScript. Также мы применим Modernizr для определения поддержки сенсорного ввода.
CSS и JavaScript
Обратите внимание, что здесь я не стану добавлять префиксы свойствам CSS3, но в файлах вы обнаружите версии с префиксами. Глобальный CSS, применимый ко всем размерам экранов, выглядит следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/* Глобальный CSS, применимый ко всем размерам экранов */ .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{ /* Отшлифуйте шрифт для Chrome */ transform: translate3d(0, 0, 0); } /*Удалите голубой фон Webkit при касании элемента */ a, button { -webkit-tap-highlight-color: rgba(0,0,0,0); } |
Нам требуется первый небольшой переход для всей навигации, при котором снижается непрозрачность всех элементов, кроме того, над которым проводят мышью. Вот код для этого:
1 2 3 4 5 6 7 8 9 |
/* Эффект проведения мышью для всей навигации с целью выделения элемента */ .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. Так можно добавить столько элементов списка, сколько нужно, код цвета будет повторяться.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
.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); } |
Применяя медиазапрос min-width, можно выбрать экраны более 800px (50em при размере шрифта body в 15px), чтобы трансформировать свой список в красивую горизонтальную навигацию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@media (min-width: 50em) { /*Трансформирует список в горизонтальную навигацию */ .nav li { float: left; width: 16.66666666666667%; text-align: center; transition: border .5s; } .nav a { display: block; width: auto; } |
Продолжим пользоваться методикой отбора nth-child, чтобы добавить каждому элементу нашего меню рамку в 4px с разными цветами. Мы применяем ее при проведении мышью, а также в фокусе и при активном состоянии, чтобы она работала на сенсорных устройствах и при работе с клавиатуры.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/* эффекты проведения мышью, фокусирования и активного состояния добавляют разным элементам небольшую цветную рамку */ .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); } |
Затем помещаем иконки и текст:
1 2 3 4 5 6 7 8 9 10 |
/* Размещение иконки */ .icon { padding-top: 1.4em; } .icon + span { margin-top: 2.1em; transition: margin .5s; } |
Мы анимируем высоту элементов когда проводим над ними мышью:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/*Анимация высоты элемента*/ .nav a { height: 9em; } .no-touch .nav a:hover , .no-touch .nav a:active , .no-touch .nav a:focus { height: 10em; } /* Текст последует за анимацией высоты */ .no-touch .nav a:hover .icon + span { margin-top: 3.2em; transition: margin .5s; } |
Затем размещаем иконки и готовим их к переходу CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* Размещение иконок и подготовка к анимации*/ .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; } |
Для создания нужного визуального эффекта мы делаем переход тени блока и изменяем ее размер с 0.8em до 0, а ее цвет с прозрачного на какой-либо цвет с высокой непрозрачностью. Здесь же закрываем свой первый медиазапрос.
1 2 3 4 5 6 7 8 9 |
/* Анимируйте тень блока box-shadow для создания эффекта */ .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:
1 2 3 4 5 6 7 8 |
@media (min-width: 50em) and (max-width: 61.250em) { /*Регулировка размера и шрифта до более подходящих */ .nav ul { font-size: 1.2em; } } |
Теперь, когда мы закончили с версией для десктопов (под ОГРОМНЫМ вопросом, так как сегодня все больше «таблеток» имеют размеры экрана 1024px и более), позаботимся о глобальном CSS для экранов размером менее 800px, что равняется 49.938em, применив медиазапрос max-width.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
/* Версия для «таблеток» и мобильных устройств */ @media (max-width: 49.938em) { /*Вместо добавления рамки делаем переход фонового цвета */ .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) нам нужно отобразить свое меню в разметке из двух колонок и трех строк. Добавляем отступ, чтобы элементов можно было легко коснуться, и отображаем иконки слева, а текст справа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/* CSS для версии с колонками */ @media (min-width: 32.5em) and (max-width: 49.938em) { /* Создаем разметку двух колонок, снова с помощью «плавающих» элементов */ .nav li { display: block; float: left; width: 50%; } /* Добавляем отступ, чтобы элементы лучше смотрелись*/ .nav a { padding: 0.8em; } /* Отображаем иконки слева, а текст по правой стороне с помощью 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; } |
Анимация, подходящая для больших экранов, слишком сложна для более мелких, поэтому сделаем ее проще и сдержаннее – просто анимируем рамку. Здесь мы закрываем свой медиазапрос.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* Более сдержанно адаптируем иконки к анимации размера и рамки закругленного фона */ .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; } /*Эффект перехода цвета рамки */ .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); } } |
И снова адаптируем размер шрифта и ширину к более маленьким экранам.
1 2 3 4 5 6 7 8 9 10 11 |
/* Адаптируем размер шрифта и ширину для маленьких экранов*/ @media (min-width: 32.5em) and (max-width: 38.688em) { .nav li span.icon { width: 50%; } .nav li .icon + span { font-size: 0.9em; } } |
Для очень маленьких экранов мы скроем навигацию и отобразим кнопку “menu”, которую может щелкнуть пользователь, если захочет отобразить навигацию. Чтобы сделать это, доверимся нескольким строкам JavaScript’а:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Функция для изменения класса 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; }; // Создание кнопки для маленьких экранов 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>'); // Переключайте класс при щелчке для показа/скрытия меню document.getElementById('menutoggle').onclick = function() { changeClass(this, 'navtoogle active', 'navtoogle'); } |
Чтобы HTML стал чище, я решил создать кнопку “menu” и вставить ее в DOM с помощью JavaScript’а. Функция changeClass помогает нам переключать класс с active на no при щелчке пользователя по кнопке. Теперь у нас есть все, что нужно для малоэкранной версии, и можно назначать ей стили с помощью CSS. Определяет стили кнопки меню следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* Стили переключения ссылки меню и ее сокрытие */ .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):
1 2 3 4 5 6 7 |
@media (max-width: 32.438em) { /* Открытие ссылки меню со стилями */ .nav .navtoogle{ margin: 0; display: block; } |
Мы анимируем высоту навигации при нажатии кнопки. Чтобы закрыть навигацию, назначаем ей высоту в 0em, чтобы открыть – назначаем max-height в 30em. При отключенном JavaScript’е у нас нет никакой кнопки, поэтому применим класс no-js, чтобы навигация отображалась всегда.
1 2 3 4 5 6 7 |
/* Анимация высоты навигации при щелчке на кнопку */ /* Если JavaScript отключен, меню остается открытым */ .no-js .nav ul { max-height: 30em; overflow: hidden; } |
При включенном JavaScript’е мы по умолчанию скрываем меню, и отображаем его, когда пользователь щелкает по кнопке, которая затем получает класс active:
1 2 3 4 5 6 7 8 9 10 11 12 |
/* При включенном JavaScript’е скрываем меню */ .js .nav ul { max-height: 0em; overflow: hidden; } /* Отображение меню при щелчке пользователя по кнопке */ .js .nav .active + ul { max-height: 30em; overflow: hidden; transition: max-height .4s; } |
Мы адаптируем разметку для маленьких экранов, представляя навигацию в списке элементов с иконкой слева и текстом по правой стороне:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* Адаптация разметки меню для маленьких экранов: иконка слева и текст справа */ .nav li span { display: inline-block; height: 100%; } .nav a { padding: 0.5em; } .icon + span { margin-left: 1em; font-size: 0.8em; } |
Также добавляем рамку красивого цвета в 8px слева от каждого элемента
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* Добавление слева рамки в 8 px с разными цветами для каждого элемента меню*/ .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’а можно определить сенсорную производительность устройства. Если у устройства есть сенсорные возможности, в body добавляется класс touch. Его можно применять для улучшения впечатления от сенсорных устройств и небольшого увеличения элементов навигации, чтобы их было легче касаться. И тут мы закрываем свой последний медиазапрос.
1 2 3 4 5 |
/* сделайте nav больше на сенсорных экранах */ .touch .nav a { padding: 0.8em; } } |
Вот и все, мы создали красивую, удобную для сенсорных и retina-устройств навигацию, отлично работающую как на десктопах, так и на «таблетках» и мобильных устройствах. Надеюсь, она вам понравилась!
Автор: Stephanie Walter
Источник: //tympanus.net/
Редакция: Команда webformyself.
Комментарии (4)