Навигация как на Stripe.Com
Реализуем выпадающий список, который анимируется в зависимости от контента выпадающего списка.
Несколько недель назад на stripe.com был вылит новый дизайн. Он великолепен. Одним из особых мест — стала навигация: вместо привычного выпадающего списка мы видим блоки с отличным оформлением.
Структура
HTML структура состоит из двух основных элементов: nav.main-nav
для топ-навигации и div.morph-dropdown-wrapper
— контейнера для выпадающих элементов.
Для каждого элемента nav.main-nav
создаём li.dropdown
.
<header class="cd-morph-dropdown"> <a href="#0" class="nav-trigger">Open Nav<span aria-hidden="true"></span></a> <nav class="main-nav"> <ul> <li class="has-dropdown gallery" data-content="about"> <a href="#0">About</a> </li> <li class="has-dropdown links" data-content="pricing"> <a href="#0">Pricing</a> </li> <li class="has-dropdown button" data-content="contact"> <a href="#0">Contact</a> </li> </ul> </nav> <div class="morph-dropdown-wrapper"> <div class="dropdown-list"> <ul> <li id="about" class="dropdown gallery"> <!-- dropdown content here --> </li> <li id="pricing" class="dropdown links"> <!-- dropdown content here --> </li> <li id="contact" class="dropdown button"> <!-- dropdown content here --> </li> </ul> <div class="bg-layer" aria-hidden="true"></div> </div> <!-- dropdown-list --> </div> <!-- morph-dropdown-wrapper --> </header>
Дополнительный элемент div.bg-layer
будет задействован для графических преобразований.
Стили
На небольших устройствах элемент div.morph-dropdown-wrapper
будет скрыт; отобразится только при клике по элементу с классом .nav-open
.
.cd-morph-dropdown { position: relative; } .cd-morph-dropdown .morph-dropdown-wrapper { display: none; position: absolute; top: 60px; left: 0; width: 100%; } .cd-morph-dropdown.nav-open .morph-dropdown-wrapper { display: block; }
На устройствах с крупным дисплеем изначально скрыты элементы .dropdown-list
и li.dropdown
.
@media only screen and (min-width: 1000px) { .cd-morph-dropdown .dropdown-list { position: absolute; top: 0; left: 0; visibility: hidden; } .cd-morph-dropdown .dropdown { position: absolute; left: 0; top: 0; opacity: 0; visibility: hidden; width: 100%; transition: opacity .3s, visibility .3s; } }
При наведении курсором мыши по элементам внутри nav.main-nav
будет добавлен класс .is-dropdown-visible
, чтобы отобразить выпадающий список.
@media only screen and (min-width: 1000px) { .cd-morph-dropdown .dropdown.active { opacity: 1; visibility: visible; } }
Фон выпадающего списка будет описан в элементе div.bg-layer
.
@media only screen and (min-width: 1000px) { .cd-morph-dropdown .bg-layer { /* morph dropdown background */ position: absolute; top: 0; left: 0; height: 1px; width: 1px; background: #FFFFFF; opacity: 0; transition: opacity .3s; transform-origin: top left; } .cd-morph-dropdown.is-dropdown-visible .bg-layer { opacity: 1; transition: transform .3s, opacity .3s; } }
Обработка событий
Создаём объект morphDropdown
и с помощью bindEvents
регистрируем события, которые будем прослушивать.
function morphDropdown( element ) { this.element = element; this.mainNavigation = this.element.find('.main-nav'); this.mainNavigationItems = this.mainNavigation.find('.has-dropdown'); this.dropdownList = this.element.find('.dropdown-list'); //... this.bindEvents(); }
Определяем события мыши по элементам .has-dropdown
и .dropdown
.
morphDropdown.prototype.bindEvents = function() { var self = this; this.mainNavigationItems.mouseenter(function(event){ //hover over one of the nav items -> show dropdown self.showDropdown($(this)); }).mouseleave(function(){ //if not hovering over a nav item or a dropdown -> hide dropdown if( self.mainNavigation.find('.has-dropdown:hover').length == 0 && self.element.find('.dropdown-list:hover').length == 0 ) self.hideDropdown(); }); //... };
В методе showDropdown
меняем высоту блока .dropdown-list
для преобразования элемента .bg-layer
.
morphDropdown.prototype.showDropdown = function(item) { var selectedDropdown = this.dropdownList.find('#'+item.data('content')), selectedDropdownHeight = selectedDropdown.innerHeight(), selectedDropdownWidth = selectedDropdown.children('.content').innerWidth(), selectedDropdownLeft = item.offset().left + item.innerWidth()/2 - selectedDropdownWidth/2; //update dropdown and dropdown background position and size this.updateDropdown(selectedDropdown, parseInt(selectedDropdownHeight), selectedDropdownWidth, parseInt(selectedDropdownLeft)); //add the .active class to the selected .dropdown and .is-dropdown-visible to the .cd-morph-dropdown //... }; morphDropdown.prototype.updateDropdown = function(dropdownItem, height, width, left) { this.dropdownList.css({ '-moz-transform': 'translateX(' + left + 'px)', '-webkit-transform': 'translateX(' + left + 'px)', '-ms-transform': 'translateX(' + left + 'px)', '-o-transform': 'translateX(' + left + 'px)', 'transform': 'translateX(' + left + 'px)', 'width': width+'px', 'height': height+'px' }); this.dropdownBg.css({ '-moz-transform': 'scaleX(' + width + ') scaleY(' + height + ')', '-webkit-transform': 'scaleX(' + width + ') scaleY(' + height + ')', '-ms-transform': 'scaleX(' + width + ') scaleY(' + height + ')', '-o-transform': 'scaleX(' + width + ') scaleY(' + height + ')', 'transform': 'scaleX(' + width + ') scaleY(' + height + ')' }); };
Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: https://codyhouse.co/gem/stripe-navigation/
Перевел: Станислав Протасевич
Урок создан: 8 Декабря 2016
Просмотров: 4659
Правила перепечатки
5 последних уроков рубрики "CSS"
-
Забавные эффекты для букв
Небольшой эффект с интерактивной анимацией букв.
-
Реализация забавных подсказок
Небольшой концепт забавных подсказок, которые реализованы на SVG и anime.js. Помимо особого стиля в примере реализована анимация и трансформация графических объектов.
-
Анимированные буквы
Эксперимент: анимированные SVG буквы на базе библиотеки anime.js.
-
Солнцезащитные очки от первого лица
Прикольный эксперимент веб страницы отображение которой осуществляется “от первого лица” через солнцезащитные очки.
-
Раскрывающаяся навигация
Экспериментальный скрипт раскрывающейся навигации.