Создание меню в стиле YouTube

Сегодня мы создадим меню в стиле YouTube. Меню состоит из небольшой иконки меню, ссылки и списка элементов меню, которые появляются при нажатии на ссылку или иконку. Для того чтобы раскрыть меню, нужно нажать на иконку с правой стороны, возле первого пункта раскрывающегося списка, иконка меню с меткой поднимется на уровень выше, в то время как элементы списка постепенно появятся под ней. Мы добавим еще некоторые эффекты, чтобы сделать меню ещё более интересным.

Сложность

HTML разметка

В HTML разметке мы будем использовать элемент nav, внутри добавим контейнер, в котором будет находиться иконка меню и ссылка. Мы будем использовать неупорядоченный список для элементов списка YouTube меню:

<nav id="dr-menu" class="dr-menu">
    <div class="dr-trigger"><span class="dr-icon dr-icon-menu"></span><a class="dr-label">Account</a></div>
    <ul>
        <li><a class="dr-icon dr-icon-user" href="#">Xavier Densmore</a></li>
        <li><a class="dr-icon dr-icon-camera" href="#">Videos</a></li>
        <li><a class="dr-icon dr-icon-heart" href="#">Favorites</a></li>
        <li><a class="dr-icon dr-icon-bullhorn" href="#">Subscriptions</a></li>
        <li><a class="dr-icon dr-icon-download" href="#">Downloads</a></li>
        <li><a class="dr-icon dr-icon-settings" href="#">Settings</a></li>
        <li><a class="dr-icon dr-icon-switch" href="#">Logout</a></li>
    </ul>
</nav>

У каждого элемента меню будет небольшая иконка, для этого необходимо задать для каждого уникальные классы. При помощи приложения IcoMoon, мы создали пользовательский набор необходимых нам иконок.

CSS

Для начала подключим иконочный шрифт:

@font-face {
    font-family: 'icomoon';
    src:url('../fonts/icomoon.eot');
    src:url('../fonts/icomoon.eot?#iefix') format('embedded-opentype'),
        url('../fonts/icomoon.woff') format('woff'),
        url('../fonts/icomoon.ttf') format('truetype'),
        url('../fonts/icomoon.svg#icomoon') format('svg');
    font-weight: normal;
    font-style: normal;
}

Для основного контейнера nav установим общие стили, такие как размер шрифта, высота, цвет и размеры. Нам нужно сделать его гибким, но чтобы он был слишком большим или слишком маленьким, для этого добавим свойства max-width и min-width:

.dr-menu {
    width: 100%;
    max-width: 400px;
    min-width: 300px;
    position: relative;
    font-size: 1.3em;
    line-height: 2.5;
    font-weight: 400;
    color: #fff;
    padding-top: 2em;
}

Для контейнера, который содержит иконки меню и ссылки, добавим свойства position: absolute, cursor: pointer и высокий z-index, чтобы неупорядоченный список находился под ним:

.dr-menu > div  {
    cursor: pointer;
    position: absolute;
    width: 100%;
    z-index: 100;
}

Для контейнера с иконками добавим свойство position: absolute, а также добавим переход:

.dr-menu > div .dr-icon {
    top: 0;
    left: 0;
    position: absolute;
    font-size: 150%;
    line-height: 1.6;
    padding: 0 10px;
    transition: all 0.4s ease;
}

При нажатии по контейнеру, задаем класс dr-menu-open для элемента nav. Иконка YouTube меню будет перемещаться в левую сторону:

.dr-menu.dr-menu-open > div .dr-icon {
    color: #60a773;
    left: 100%;
    transform: translateX(-100%);
}

Напоследок мы добавим наши классы иконок от IcoMoon. Иконки в контейнере меню будут несколько отличаться, используем псевдо-класс :after, чтобы добавить небольшой треугольник.

.dr-menu > div .dr-icon:after {
    content: "\e008";
    position: absolute;
    font-size: 50%;
    line-height: 3.25;
    left: -10%;
    opacity: 0;
}

Для иконки, зададим абсолютную позицию с отступом по горизонтали в -10%. Начальная непрозрачность установлена в 0, чтобы она отображалась при закрытом меню.

Как только мы открываем меню, меняем значение непрозрачности до 1:

.dr-menu.dr-menu-open > div .dr-icon:after {
    opacity: 1;
}

Текст, который является привязкой в нашем HTML коде, получит общий стиль, установим для него небольшие отступы, чтобы он находился рядом с иконкой YouTube меню.  Мы также добавим переход, для того чтобы анимировать текст, как только мы открываем меню, перемещая его по оси Y:

.dr-menu > div .dr-label {
    padding-left: 3em;
    position: relative;
    display: block;
    color: #60a773;
    font-size: 0.9em;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    line-height: 2.75;
    transition: all 0.2s ease-in;
}
 
.dr-menu.dr-menu-open > div .dr-label {
    transform: translateY(-90%);
}

Неупорядоченный список изначально будет невидимым:

.dr-menu ul {
    padding: 0;
    margin: 0 3em 0 0;
    list-style: none;
    opacity: 0;
    position: relative;
    z-index: 0;
    pointer-events: none;
    transition: opacity 0s linear 205ms;
}

При открытии YouTube меню, нам нужно чтобы оно стало видимым, установим z-index таким образом, чтобы меню покрывало весь контейнер:

.dr-menu.dr-menu-open ul {
    opacity: 1;
    z-index: 200;
    pointer-events: auto;
    transition: opacity 0s linear 0s;
}

Это два перехода для открытия и закрытия меню. Когда мы открываем меню, нам нужно чтобы оно сразу появилось без задержки, а когда мы закрываем его, т.е. удаляем класс, меню будет закрываться с небольшой задержкой. Время задержки определенно задержкой последнего элемента в списке.

Элементы списка также сделаем невидимыми, для них мы установим переход в непрозрачности:

.dr-menu ul li {
    display: block;
    margin: 0 0 5px 0;
    opacity: 0;
    transition: opacity 0.3s ease;
}
 
.dr-menu.dr-menu-open ul li {
    opacity: 1;
}

Теперь, каждый элемент списка будет появляться с различной задержкой: первый элемент сразу появится, последний элемент появится в конце:

.dr-menu.dr-menu-open ul li:nth-child(2) {
    transition-delay: 35ms;
}
 
.dr-menu.dr-menu-open ul li:nth-child(3) {
    transition-delay: 70ms;
}
 
.dr-menu.dr-menu-open ul li:nth-child(4) {
    transition-delay: 105ms;
}
 
.dr-menu.dr-menu-open ul li:nth-child(5) {
    transition-delay: 140ms;
}
 
.dr-menu.dr-menu-open ul li:nth-child(6) {
    transition-delay: 175ms;
}
 
.dr-menu.dr-menu-open ul li:nth-child(7) {
    transition-delay: 205ms;
}

Ссылкам добавим отступы, установим их как встроенные inline-blocks:

.dr-menu ul li a {
    display: inline-block;
    padding: 0 20px;
    color: #fff;
}

Изменим цвет при наведении:

.dr-menu ul li a:hover {
    color: #60a773;
}

Определим для иконок псевдо-элементы:

.dr-icon:before, 
.dr-icon:after {
    position: relative;
    font-family: 'icomoon';
    speak: none;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    -webkit-font-smoothing: antialiased;
}
 
.dr-menu ul .dr-icon:before {
    margin-right: 15px;
}
 
.dr-icon-bullhorn:before {
    content: "\e000";
}
 
.dr-icon-camera:before {
    content: "\e002";
}
 
.dr-icon-heart:before {
    content: "\e003";
}
 
.dr-icon-settings:before {
    content: "\e004";
}
 
.dr-icon-switch:before {
    content: "\e005";
}
 
.dr-icon-download:before {
    content: "\e006";
}
 
.dr-icon-user:before {
    content: "\e001";
}
 
.dr-icon-menu:before {
    content: "\e007";
}

JavaScript

Теперь, настало время перейти к JavaScript коду. Добавим небольшой скрипт для функциональности меню. При нажатии по контейнеру, необходимо чтобы контейнер меню получил класс dr-menu-open. Так как мы будем анимировать текст и иконку YouTube меню, необходимо чтобы закрытие происходило только при нажатии по иконке меню, точно так же, как в меню YouTube:

var YTMenu = (function() {
 
    function init() {
         
        [].slice.call( document.querySelectorAll( '.dr-menu' ) ).forEach( function( el, i ) {
 
            var trigger = el.querySelector( 'div.dr-trigger' ),
                icon = trigger.querySelector( 'span.dr-icon-menu' ),
                open = false;
 
            trigger.addEventListener( 'click', function( event ) {
                if( !open ) {
                    el.className += ' dr-menu-open';
                    open = true;
                }
            }, false );
 
            icon.addEventListener( 'click', function( event ) {
                if( open ) {
                    event.stopPropagation();
                    open = false;
                    el.className = el.className.replace(/\bdr-menu-open\b/,'');
                    return false;
                }
            }, false );
 
        } );
 
    }
 
    init();
 
})();
ДЕМО СКАЧАТЬ

 

Перевод статьи Simple YouTube Menu Effect

Тэги: transitionmenu

Вход

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