Простой эффект YouTube-меню
23 мая 2013 | Опубликовано в css | 1 Комментарий »
Сегодня мы будем создавать маленькое меню с эффектом, который вы видели в левой части меню на YouTube. Меню состоит из маленькой иконки меню, ярлыка и списка пунктов меню, который появляется при нажатии либо на ярлыку, либо на иконке. Как только пользователь кликнул для открытия меню, ярлык будет перемещаться вверх, а иконку сдвигается вправо. Элементы списка меню будут появляться последовательно, так как для каждого элемента устанавливается разная задержка. Также, чтобы сделать наше меню более интересным, добавляем различные стили и эффекты. Давайте приступим!
Разметка
Для HTML мы будем использовать элемент NAV
и блок DIV внутри него, который будет вмещать иконку и описание. Для пунктов меню мы будем использовать неупорядоченный список:
<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.
CSS
Обратите внимание, что 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 будет иметь некоторые общие стили, такие как размер шрифта, высоту линий, цвет и размеры. Мы хотим, чтобы он был гибким, но не хотим, чтобы становился слишком большим или слишком маленьким, поэтому установим максимальную и минимальную ширину:
.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; }
Разделение, которое будет содержать span-элемент с иконкой меню и ссылкой, будет позиционирован абсолютно, а курсор мы будем устанавливать на “pointer”. Также он нуждается в большом z-index, чтобы убедиться, что в случае применению маркированного списка, он не будет вылазить.
.dr-menu > div { cursor: pointer; position: absolute; width: 100%; z-index: 100; }
Span с иконкой меню в разделении trigger также будет позиционироваться абсолютно. Зададим для него переход.
.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; }
При нажатии на разделение trigger, для nav мы будем задавать класс “dr-menu-open”. Иконка меню будет перемещена влево, и мы тоже ее сдвинем на расстояние собственной ширины, чтобы она в дальнейшем могла возвращаться в свое исходное положение без сдвигов.
.dr-menu.dr-menu-open > div .dr-icon { color: #60a773; left: 100%; transform: translateX(-100%); }
Наконец, добавим к иконке классы с IcoMoon. Иконка в элементе span для иконки нашего меню будет немного отличаться — мы будем использовать псевдо-класс :after. После добавим маленький треугольник. Давайте определим это следующим образом:
.dr-menu > div .dr-icon:after{
content: "\e008"; position: absolute; font-size: 50%; line-height: 3.25; left: -10%; opacity: 0; }
Иконка будет позиционироваться абсолютно, и мы будем ставить ее на место, задав left -10%. Первоначально непрозрачность будет установлена на 0, так как она должна быть невидимой при закрытом меню.
Как только мы открываем меню, нужно, чтобы она становилась видимой:
.dr-menu.dr-menu-open > div .dr-icon:after { opacity: 1; }
Для ярлыка, который является ссылкой в нашем HTML, также зададим общие стили, определим отступы padding , чтобы разместить его рядом с иконкой меню. Также добавим переходы, чтобы оживить его при открытии меню, и переместим по осу 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%); }
Неупорядоченный список изначально будет невидимым (непрозрачность 0):
.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; }
При открытии меню, нам нужно список сделать видимым и задать ему высокий Z-Index, чтобы div trigger не перекрывал его.
.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; }
Ссылки будут иметь некоторое отступы padding, и мы будем устанавливать их как встроенные блоки:
.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.
THE JAVASCRIPT
Создадим небольшой скрипт, который позаботиться о функциональности меню. При нажатии на разделение trigger, мы хотим, чтобы оболочка меню получила класс “dr-menu-open”. Так как мы собираемся анимировать ярлык и смещать иконку в правую сторону, нужно, чтобы закрытие происходило только в том случае, когда пользователь нажмет на иконку меню, как в меню 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(); })();
Вот и все! Надеемся, что этот урок будет полезным для вас!
Автор: MARY LOU
Перевод — Дежурка