Адаптивное Retina-меню на CSS

В этом уроке мы создадим красочное Retina-меню, с использованием цветовой схемы от Maliwan, производителя игры Borderlands. Меню автоматически меняется на одну из трех различных раскладок, в зависимости от размера окна браузера. Для создания retina-меню, мы будем использовать иконочный шрифт.

Сложность

Подготовка шрифтов

Создание собственного иконочного шрифта довольно сложный процесс, но с таким инструментом, как IcoMoon, вам нужно лишь произвести импорт готовых иконок в приложение. Такие иконки отображаются как любой другой шрифт, так что вы можете легко манипулировать с его цветом и размером. Он идеально подходит для retina устройств.

Первое, что нам нужно сделать, это создать иконки для нашего адаптивного меню. Я использую Illustrator для создания иконок, но можно использовать любой другой редактор векторной графики, например, Inkscape. Нам нужно создать иконки и экспортировать их в виде SVG файлов. Чтобы убедиться, что иконка будет правильно отображаться во всех браузерах, мы должны преобразовать все строки в один объект и объединить все объекты в одну большую форму для каждой иконки. После того как все данные будут экспортированы в файлы SVG, мы можем импортировать их в инструмент App IcoMoon:

Мы также можем расширить наш набор иконок при помощи библиотеки иконок IcoMoon. После того как импортировали все необходимые иконки, нажимаем на кнопку «Font» в нижней части страницы, чтобы перейти к подробным настройкам. На этой странице, для шрифта, мы можем выбрать параметры кодировки, а также задать буквы для каждой иконки, либо можно оставить все параметры по умолчанию. Я рекомендую использовать второй вариант.

Далее нажимаем на кнопку "Download", скачиваем ZIP файл с 4 форматами шрифтов (SVG, СРВ, TTF и WOFF), стиль CSS и демонстрационную страницу.

Для того чтобы использовать иконки, скопируем и вставим код CSS IcoMoon в начало нашего 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" к нужному элементу. Также отметьте, что мы не стали добавлять класс no-js, который используется с библиотекой Modernizr, для того, чтобы была возможность оставить меню открытым, если у пользователя отключен JavaScript. Мы будем также использовать Modernizr, для определения сенсорной поддержки.

CSS и JavaScript

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);
}
  
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);
}/pre>

Затем зададим цвет фона для каждого элемента. Приведенный ниже код использует технику 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, вы сможете определять расположение элементов, на различных размерах экранов:

@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.4em;
}
 
.icon + span {
    margin-top: 2.1em;
    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.2em;
    transition: margin .5s;
}

Позиционируем иконки и добавим к ним CSS переходы:

.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.

.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) {
     .nav ul {
        font-size: 1.2em;
    }
 
}

Теперь, когда мы закончили десктопную версию, перейдем к «глобальному» CSS для экранов меньше 800px, что равняется 49.938em, используя медиа-запрос max-width.

@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), мы разделим на экране наше меню в 2 столбца и 3 строки. Добавляем небольшие отступы, и выведем иконки с левой и текст с правой.

@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;
    }

Анимация для десктопа слишком сложная, чтобы использовать её на мобильных устройствах, поэтому необходимо её упростить. На этом мы закончим с медиа-запросами.

.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);
    }
 
}

Адаптируем размер шрифта и ширину для небольших экранов.

@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:

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 id="menutoggle" class="navtoogle" type="button"><em class="icon-menu"> </em> Menu</button>');
 
//  Добавление класса для кнопки
document.getElementById('menutoggle').onclick = function() {
    changeClass(this, 'navtoogle active', 'navtoogle');
}/pre>

Я создал кнопку адаптивного меню и встроил ее в DOM с использованием JavaScript, для очищения HTML кода. Функция changeClass помогает нам переключать класс между активным элементом и элементом без класса, при нажатии по кнопке.

Следующий код стилизует кнопку меню:

.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) {
     .nav .navtoogle{
        margin: 0;
        display: block;
    }

При нажатии кнопки мы анимируем высоту навигации. Чтобы закрыть навигацию, мы зададим для неё высоту в 0em, чтобы открыть её, мы зададим макс.высоту в 30em. Если JavaScript не включен, мы не будем использовать класс no-js.

.no-js .nav ul {
    max-height: 30em;
    overflow: hidden;
}

При включенном JavaScript, мы скрываем меню по умолчанию и выводим его на экран, при нажатии по кнопке, которая затем получает активный класс:

/* Скрываем меню при включенном 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.5em;     
}
 
.icon + span {
    margin-left: 1em;
    font-size: 0.8em;
}

Мы также добавим 8px рамку слева у каждого элемента:

.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 .nav a {
        padding: 0.8em;
    }
}
ДЕМО СКАЧАТЬ

 

Перевод статьи Responsive Retina-Ready Menu

Тэги: menuresponsivemodernizr

Вход

Уважаемый пользователь! Мы обнаружили, что вы используете AdBlock и вынуждены скрыть часть материалов на нашем сайте. Siteacademy существует и развивается за счет доходов от рекламы. Просим внести наш сайт в список исключений или отключить Блокировщик рекламы на нашем сайте.