Адаптивне меню для екранів RETINA

14

Від автора: адаптивне меню для Retina з підтримкою сенсорного введення і трьома розмітками для різних розмірів браузера.

Сьогодні ми створимо яскраве адаптивне і відповідне до екранів Retina меню, натхнена колірною палітрою Maliwan, виробника гри Borderlands». Меню автоматично змінюється під одну з трьох різних розміток в залежності від розміру вікна браузера: вбудовану версію «десктопа», оптимізовану під «таблетку» версію з двома колонками і мобільну версію з посиланням на меню для відображення та приховування навігації для маленьких екранів. Щоб зробити меню повністю під retina, ми застосуємо шрифти-іконки з тим, щоб іконки меню при зміні розміру не піддавалися пикселизации.

Адаптивне меню для екранів RETINAАдаптивне меню для екранів RETINA

Підготовка шрифту-іконки

Створення користувальницького шрифту-іконки може здатися дещо складною, але з допомогою таких інструментів, як IcoMoon справа тільки за створенням іконок і їх імпортом в інструмент. Шрифти-іконки ведуть себе як будь-які шрифти, тому можна легко змінювати їх колір, підганяти розмір, і вони не піддаються пикселизации. Ідеальні для пристроїв retina, і для різних дозволів екрану не потрібно використовувати безліч об’єктів.

Перше, що слід зробити – це створити іконки для меню. Я користуюся Illustrator’ом, але підійде будь-редактор векторної графіки, наприклад, Inkscape. Потрібно створити кожну іконку і експортувати їх як файл SVG. Щоб гарантувати правильну роботу іконки в будь-якому браузері, нам потрібно перетворити всі рядки цілі об’єкти і з’єднати всі об’єкти для іконки в одну велику фігуру. Коли всі вже експортовано у відповідні файли SVG, можна імпортувати в додаток інструменту IcoMoon:

Адаптивне меню для екранів RETINA

Також можна посилити свій шрифт іконками з величезної бібліотеки, пропонованої IcoMoon. Коли всі потрібні нам іконки готові, клацаємо по кнопці «Font» внизу сторінки, щоб зайти в детальні установки. На цій сторінці можна вибрати установки кодування шрифту, а також вибрати, чи ми хочемо призначити кожній іконці літери, або воліємо застосувати Private Use Area шрифту, щоб читачі не змогли його вивести. Я раджу використовувати установки за замовчуванням, які дуже добре працюють.

Адаптивне меню для екранів RETINA

При натисканні на «Download» ми отримуємо файл ZIP з 4 форматами шрифту (SVG, EOT, TTF і WOFF), CSS і демо-сторінку.
Перше, що слід зробити для використання іконок – скопіювати і вставити CSS, надається IcoMoon, верх свого файлу CSS і переконатися, що папка зі шрифтом теж скопійована. Ви, можливо, захотіли б дізнатися про маленькому хаке зробити шрифти у вікнах Chrome ще симпатичніше.

HTML-код меню

Ось як виглядає HTML нашої навігації:

  • Home
  • Services
  • Portfolio
  • Blog
  • The team
  • Contact

Щоб використовувати шрифт-іконку, просто застосовуємо клас «icon-iconname» всередині елемента i (span теж спрацює). Також зауважте, що ми додали клас no-js, який зміниться на js з допомогою Modernizr’а. Ідея полягає в тому, щоб меню залишалося відкритим, якщо у користувача відключений JavaScript. Також ми застосуємо Modernizr для визначення підтримки сенсорного введення.

CSS і JavaScript

Зверніть увагу, що тут я не буду додавати префікси властивостей CSS3, але в файлах ви виявите версії з префіксами. Глобальний CSS, застосовний до всіх розмірами екранів, виглядає наступним чином:

/* Глобальний CSS, застосовний до всіх розмірами екранів */
.nav ul {
max-width: 1240px;
margin: 0;
padding: 0;
list-style: none;
font-size: 1.5 em;
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);
}

Нам потрібно перший невеликий перехід для всієї навігації, при якому знижується непрозорість всіх елементів, крім того, над яким проводять мишею. Ось код для цього:

/* Ефект проведення мишею для всієї навігації з метою виділення елемента */
.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);
}

Застосовуючи медиазапрос min-width, можна вибрати екрани більш 800px (50em при розмірі шрифту body в 15px), щоб трансформувати свій список в красиву горизонтальну навігацію:

@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 з різними квітами. Ми застосовуємо її при проведенні мишею, а також у фокусі і при активному стані, щоб вона працювала на сенсорних пристроях і при роботі з клавіатури.

/* ефекти проведення мишею, фокусування та активного стану додають різним елементам невелику кольорову рамку */
.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);
}

Потім поміщаємо іконки і текст:

/* Розміщення іконки */
.icon {
padding-top: 1.4 em;
}
.icon + span {
margin-top: 2.1 em;
transition: margin .5s;
}

Ми анимируем висоту елементів коли проводимо над ними мишею:

/*Анімація висоти елемента*/
.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.2 em;
transition: margin .5s;
}

Потім розміщуємо іконки і готуємо їх до переходу CSS:

/* Розміщення іконок і підготовка до анімації*/
.nav i {
position: relative;
display: inline-block;
margin: 0 auto;
padding: 0.4 em;
border-radius: 50%;
font-size: 1.8 em;
box-shadow: 0 0 0 0.8 em transparent;
background: rgba(255,255,255,0.1);
transform: translate3d(0, 0, 0);
transition: box-shadow .6s ease-in-out;
}

Для створення потрібного візуального ефекту ми робимо перехід тіні блоку і змінюємо її розмір з 0.8 em до 0, а її колір з прозорого на який-небудь колір з високою прозорістю. Тут же закриваємо свій перший медиазапрос.

/* Анімуються тінь блоку 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:

@media (min-width: 50em) and (max-width: 61.250 em) {
/*Регулювання розміру та шрифту до більш підходящих */
.nav ul {
font-size: 1.2 em;
}
}

Тепер, коли ми закінчили з версією для десктопів (під ВЕЛИЧЕЗНИМ питанням, так як сьогодні все більше таблеток мають розміри екрану 1024px і більше), подбаємо про глобальне CSS для екранів розміром менше 800px, що дорівнює 49.938 em, застосувавши медиазапрос max-width.

/* Версія для «пігулок», мобільних пристроїв */
@media (max-width: 49.938 em) {
/*Замість додавання рамки робимо перехід фонового кольору */
.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.5 s;
}
}

При розмірі екрану від 520px (32.5 em) до 799px (49.938 em) нам потрібно відобразити своє меню в розмітці з двох колонок і трьох рядків. Додаємо відступ, щоб елементів можна було легко торкнутися, і відображаємо іконки зліва, а текст праворуч.

/* CSS для версії з колонками */
@media (min-width: 32.5 em) and (max-width: 49.938 em) {
/* Створюємо розмітку двох колонок, знову з допомогою «плаваючих» елементів */
.nav li {
display: block;
float: left;
width: 50%;
}
/* Додаємо відступ, щоб елементи краще виглядали*/
.nav a {
padding: 0.8 em;
}
/* Відображаємо іконки зліва, а текст по правій стороні за допомогою 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.2 em;
}

Анімація, підходить для великих екранів, занадто складна для більш дрібних, тому зробимо її простіше і стриманіше – просто анимируем рамку. Тут ми закриваємо свій медиазапрос.

/* Більш стримано адаптуємо іконки до анімації розміру і рамки закругленого фону */
.nav li i {
display: inline-block;
padding: 8% 9%;
border: 4px solid transparent;
border-radius: 50%;
font-size: 1.5 em;
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);
}
}

І знову адаптуємо розмір шрифту і ширину до більш маленьких екранів.

/* Адаптуємо розмір шрифту і ширину для маленьких екранів*/
@media (min-width: 32.5 em) and (max-width: 38.688 em) {
.nav li span.icon {
width: 50%;
}
.nav li .icon + span {
font-size: 0.9 em;
}
}

Для дуже маленьких екранів ми приховаємо навігацію і відобразимо кнопку «menu», яку користувач може клацнути, якщо захоче відобразити навігацію. Щоб зробити це, довіримося кількома рядками JavaScript’а:

// Функція для зміни класу
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’,’ Меню’);
// Перемикайте клас при клацанні для показу/приховування меню
document.getElementById(‘menutoggle’).onclick = function() {
changeClass(this, ‘navtoogle active’, ‘navtoogle’);
}

Щоб HTML став чистішим, я вирішив створити кнопку «menu» і вставити її в DOM з допомогою JavaScript’а. Функція changeClass допомагає нам перемикати клас з active на no при клацанні користувача по кнопці. Тепер у нас є все, що потрібно для малоэкранной версії, і можна призначати їй стилі за допомогою CSS. Визначає стилі кнопки меню наступний код:

/* Стилі перемикання посилання меню і її приховування */
.nav .navtoogle{
display: none;
width: 100%;
padding: 0.5 em 0.5 em 0.8 em;
font-family: ‘Lato’,Calibri,Arial,sans-serif;
font-weight: normal;
text-align: left;
color: rgb(7, 16, 15);
font-size: 1.2 em;
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.6 em;
}

За замовчуванням кнопка меню прихована. Потрібно відобразити її для екранів розміром менше 519px (32.438 em):

@media (max-width: 32.438 em) {
/* Відкриття посилання меню зі стилями */
.nav .navtoogle{
margin: 0;
display: block;
}

Ми анимируем висоту навігацію при натисканні кнопки. Щоб закрити навігацію, призначаємо їй висоту 0em, щоб відкрити – призначаємо max-height у 30em. При відключеному JavaScript’е у нас немає жодної кнопки, тому застосуємо клас no-js, щоб навігація відображалася завжди.

/* Анімація висоти навігації при натисканні на кнопку */
/* Якщо JavaScript відключений, меню залишається відкритим */
.no-js .nav ul {
max-height: 30em;
overflow: hidden;
}

При включеному JavaScript’е ми за замовчуванням приховуємо меню, і відображаємо його, коли користувач клацає на кнопці, яка потім отримує клас active:

/* При включеному JavaScript’е приховуємо меню */
.js .nav ul {
max-height: 0em;
overflow: hidden;
}
/* Відображення меню при клацанні користувача по кнопці */
.js .nav .active + ul {
max-height: 30em;
overflow: hidden;
transition: max-height .4s;
}

Ми адаптуємо розмітку для маленьких екранів, представляючи навігацію в списку елементів з іконкою зліва і текстом по правій стороні:

/* Адаптація розмітки меню для маленьких екранів: іконка ліворуч і текст праворуч */
.nav li span {
display: inline-block;
height: 100%;
}
.nav a {
padding: 0.5 em;
}
.icon + span {
margin-left: 1em;
font-size: 0.8 em;
}

Також додаємо рамку красивого кольору в 8px зліва від кожного елемента

/* Додавання зліва межі в 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. Його можна застосовувати для поліпшення враження від сенсорних пристроїв і невеликого збільшення елементів навігації, щоб їх було легше стосуватися. І тут ми закриваємо свій останній медиазапрос.

/* зробіть nav більше на сенсорних екранах */
.touch .nav a {
padding: 0.8 em;
}
}

Ось і все, ми створили красиву, зручну для сенсорних і retina-пристроїв навігацію, відмінно працює як на десктопах, так і на «таблетках» і мобільних пристроях. Сподіваюся, вона вам сподобалася!