Lecaw

Учимся создавать Web-сайты

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

May 20, 2013
CSS
254hits

Сегодня мы создадим меню как на сайте 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;
}

Контейнер, который содержит иконки меню и ссылки, расположим абсолютно, а также установим курсор в значение "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();
 
})();

ДЕМО Исходные файлы

 

Дополнительная информация

Влерий Аликин - веб-разработчик & дизайнер. Соучредитель и член команды Lecaw.

Эл. почта
RATTING:
(1 Голосовать)

Оставить комментарий