Выпадающее меню с подсказками
Приветствую вас!
У меня небольшая радость — в пятницу, 18 августа 2016 года при последующем апдейте Яндекса моему сайту zacompom.ru присвоили ТИц 10. Я понимаю что это очень небольшое событие, но ведь это только начало. Буду и впредь писать полезные статьи для вас.
И сегодня я бы хотел написать небольшую статью про меню, выпадающе и с подсказками. Кому интересно — устраивайтесь поудобнее, мы начинаем!
Это очень простое меню, где подменю при наведении появляются или выше или ниже основного меню, в зависимости от доступного пространства.
Ко мне часто поступают вопросы про хостинг, которым я пользуюсь и поэтому решил указать хостинг в статье https://sprinthost.ru. Вы можете попробовать попользоваться хостингом 30 дней бесплатно. Чтобы понять, как будет работать Ваш сайт на этом хостинге просто перенести свой сайт (в этом поможет поддержка хостинга бесплатно) и и таким образом сможете понять подходит хостинг Вам или нет. На этом хостинге находятся сайты с 20 000 тысяч посещаемость и сайты чувствуют себя отлично. Рекомендую! Да, если делать оплату на 1 год то получаете скидку 25%. И что мне нравится — тех. поддержка всегда помогает в технических вопросах, за что им спасибо. Как Вы понимаете не всегда проходит всё гладко и нет желания, чтобы сайт не был доступен тем самым страдал трафик и доход.
Подменю может появиться выше или ниже основного меню, в зависимости от того, где доступно больше места, как я и сказал выше. Будем использовать плагин Modernizr’s для обнаружения прикосновения, который будет реагировать на наведении мыши или на клик! Медиа-запросы показывают как настроить стили чтобы все отражалось нормально не только на больших, но и небольших экранах.
HTML код
<ul class=»cbp-tm-menu»> <li> <a href=»#»>Главная</a> </li> <li> <a href=»#»>Программирование</a> <ul class=»zac_submenu»> <li><a href=»#» class=»zac_icon_archive»>Изучаем_1</a></li> <li><a href=»#» class=»zac_icon_cog»>Изучаем_2</a></li> <li><a href=»#» class=»zac_icon_location»>Изучаем_3</a></li> <li><a href=»#» class=»zac_icon_users»>Изучаем_4</a></li> <li><a href=»#» class=»zac_icon_earth»>Изучаем_5</a></li> <li><a href=»#» class=»zac_icon_location»>Изучаем_6</a></li> <li><a href=»#» class=»zac_icon_mobile»>Изучаем_7</a></li> </ul> </li> <li> <a href=»#»>Вордпресс</a> <ul class=»zac_submenu»> <li><a href=»#» class=»zac_icon_archive»>Изучаем_1</a></li> <li><a href=»#» class=»zac_icon_cog»>Изучаем_2</a></li> <li><a href=»#» class=»zac_icon_link»>Изучаем_3</a></li> <li><a href=»#» class=»zac_icon_users»>Изучаем_4</a></li> <li><a href=»#» class=»zac_icon_earth»>Изучаем_5</a></li> <li><a href=»#» class=»zac_icon_location»>Изучаем_6</a></li> <li><a href=»#» class=»zac_icon_mobile»>Изучаем_7</a></li> </ul> </li> <li> <a href=»#»>Начинающим</a> <ul class=»zac_submenu»> <li><a href=»#» class=»zac_icon_screen»>Изучаем_1</a></li> <li><a href=»#» class=»zac_icon_mail»>Изучаем_2</a></li> <li><a href=»#» class=»zac_icon_contract»>Изучаем_3</a></li> <li><a href=»#» class=»zac_icon_pencil»>Изучаем_4</a></li> <li><a href=»#» class=»zac_icon_article»>Изучаем_5</a></li> <li><a href=»#» class=»zac_icon_clock»>Изучаем_6</a></li> </ul> </li> </ul>
CSS код
/* подключаем шрифты-иконки */ @font-face { font-family: ‘cbp-tmicons’; src:url(‘../fonts/tmicons/cbp-tmicons.eot’); src:url(‘../fonts/tmicons/cbp-tmicons.eot?#iefix’) format(’embedded-opentype’), url(‘../fonts/tmicons/cbp-tmicons.woff’) format(‘woff’), url(‘../fonts/tmicons/cbp-tmicons.ttf’) format(‘truetype’), url(‘../fonts/tmicons/cbp-tmicons.svg#cbp-tmicons’) format(‘svg’); font-weight: normal; font-style: normal; } /* сбрасываем стили для списков нашего меню */ .zac_menu, .zac_menu ul { list-style: none; } /* зададим позиции для нашего меню */ .zac_menu { display: block; position: absolute; z-index: 1000; bottom: 0; width: 100%; background: #47a3da; text-align: right; padding: 0 2em; margin: 0; text-transform: capitalize; } /* начинается первый уровень нашего меню */ .zac_menu > li { display: inline-block; margin: 0 2.6em; position: relative; } .zac_menu > li > a { line-height: 4em; padding: 0 0.3em; font-size: 1.2em; display: block; color: #fff; } .no-touch .zac_menu > li > a:hover, .no-touch .zac_menu > li > a:active { color: #02639d; } /* сами подменю а также переходы нашего меню */ .zac_submenu { position: absolute; display: block; visibility: hidden; opacity: 0; padding: 0; text-align: left; pointer-events: none; -webkit-transition: visibility 0s, opacity 0s; -moz-transition: visibility 0s, opacity 0s; transition: visibility 0s, opacity 0s; } .cbp-tm-show .zac_submenu { width: 16em; left: 50%; margin: 0 0 0 -8em; opacity: 1; visibility: visible; pointer-events: auto; -webkit-transition: visibility 0s, opacity 0.3s; -moz-transition: visibility 0s, opacity 0.3s; transition: visibility 0s, opacity 0.3s; } .cbp-tm-show-above .zac_submenu { bottom: 100%; padding-bottom: 10px; } .cbp-tm-show-below .zac_submenu { top: 100%; padding-top: 10px; } /* extreme cases: not enough space on the sides */ .cbp-tm-nospace-right .zac_submenu { right: 0; left: auto; } .cbp-tm-nospace-left .zac_submenu { left: 0; } /* last menu item has to fit on the screen */ .zac_menu > li:last-child .zac_submenu { right: 0; } /* тут мы укажем позицию для стрелки */ .zac_submenu:after { border: solid transparent; content: » «; height: 0; width: 0; position: absolute; pointer-events: none; } .cbp-tm-show-above .zac_submenu:after { top: 100%; margin-top: -10px; } .cbp-tm-show-below .zac_submenu:after { bottom: 100%; margin-bottom: -10px; } .zac_submenu:after { border-color: transparent; border-width: 16px; margin-left: -16px; left: 50%; } .cbp-tm-show-above .zac_submenu:after { border-top-color: #fff; } .cbp-tm-show-below .zac_submenu:after { border-bottom-color: #fff; } .zac_submenu > li { display: block; background: #fff; } .zac_submenu > li > a { padding: 5px 2.3em 5px 0.6em; /* top/bottom paddings in ’em’ cause a tiny «jump» in Chrome on Win */ display: block; font-size: 1.2em; position: relative; color: #47a3da; border: 4px solid #fff; -webkit-transition: all 0.2s; -moz-transition: all 0.2s; transition: all 0.2s; } .no-touch .zac_submenu > li > a:hover, .no-touch .zac_submenu > li > a:active { color: #fff; background: #47a3da; } /* иконки для всего меню */ .zac_submenu li a:before, .zac_menu > li > a:before { font-family: ‘cbp-tmicons’; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; vertical-align: middle; margin-right: 0.6em; -webkit-font-smoothing: antialiased; } .zac_submenu li a:before { position: absolute; top: 50%; margin-top: -0.5em; right: 0.5em; } .zac_menu > li > a:not(:only-child):before { content: «f0c9»; font-size: 60%; opacity: 0.3; } .zac_icon_archive:before { content: «e002»; } .zac_icon_cog:before { content: «e003»; } .zac_icon_users:before { content: «e004»; } .zac_icon_earth:before { content: «e005»; } .zac_icon_location:before { content: «e006»; } .zac_icon_mobile:before { content: «e007»; } .zac_icon_screen:before { content: «e008»; } .zac_icon_mail:before { content: «e009»; } .zac_icon_contract:before { content: «e00a»; } .zac_icon_pencil:before { content: «e00b»; } .zac_icon_article:before { content: «e00c»; } .zac_icon_clock:before { content: «e00d»; } .zac_icon_videos:before { content: «e00e»; } .zac_icon_pictures:before { content: «e00f»; } .zac_icon_link:before { content: «e010»; } .zac_icon_refresh:before { content: «e011»; } .zac_icon_help:before { content: «e012»; } /* далее идут медиа-запросы для отображения на разных разрешениях экранов */ @media screen and (max-width: 55.6875em) { .zac_menu { font-size: 80%; } } @media screen and (max-height: 25.25em), screen and (max-width: 44.3125em) { .zac_menu { font-size: 100%; position: relative; text-align: center; padding: 0; top: auto; } .zac_menu > li { display: block; margin: 0; border-bottom: 4px solid #3793ca; } .zac_menu > li:first-child { border-top: 4px solid #3793ca; } li.cbp-tm-show > a, .no-touch .zac_menu > li > a:hover, .no-touch .zac_menu > li > a:active { color: #fff; background: #02639d; } .zac_submenu { position: relative; display: none; width: 100%; } .zac_submenu > li { padding: 0; } .zac_submenu > li > a { padding: 0.6em 2.3em 0.6em 0.6em; border: none; border-bottom: 2px solid #6fbbe9; } .zac_submenu:after { display: none; } .zac_menu .cbp-tm-show .zac_submenu { display: block; width: 100%; left: 0; margin: 0; padding: 0; bottom: auto; top: auto; } }
А тут JavaScript код
;( function( window ) { ‘use strict’; var document = window.document, docElem = document.documentElement; function extend( a, b ) { for( var key in b ) { if( b.hasOwnProperty( key ) ) { a[key] = b[key]; } } return a; } function getViewportH() { var client = docElem[‘clientHeight’], inner = window[‘innerHeight’]; if( client < inner ) return inner; else return client; } function getOffset( el ) { return el.getBoundingClientRect(); } function isMouseLeaveOrEnter(e, handler) { if (e.type != ‘mouseout’ && e.type != ‘mouseover’) return false; var reltg = e.relatedTarget ? e.relatedTarget : e.type == ‘mouseout’ ? e.toElement : e.fromElement; while (reltg && reltg != handler) reltg = reltg.parentNode; return (reltg != handler); } function cbpTooltipMenu( el, options ) { this.el = el; this.options = extend( this.defaults, options ); this._init(); } cbpTooltipMenu.prototype = { defaults : { // добавим задержку времени (небольшую) delayMenu : 100 }, _init : function() { this.touch = Modernizr.touch; this.menuItems = document.querySelectorAll( ‘#’ + this.el.id + ‘ > li’ ); this._initEvents(); }, _initEvents : function() { var self = this; Array.prototype.slice.call( this.menuItems ).forEach( function( el, i ) { var trigger = el.querySelector( ‘a’ ); if( self.touch ) { trigger.addEventListener( ‘click’, function( ev ) { self._handleClick( this, ev ); } ); } else { trigger.addEventListener( ‘click’, function( ev ) { if( this.parentNode.querySelector( ‘ul.zac_submenu’ ) ) { ev.preventDefault(); } } ); el.addEventListener( ‘mouseover’, function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._openMenu( this ); } ); el.addEventListener( ‘mouseout’, function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._closeMenu( this ); } ); } } ); }, _openMenu : function( el ) { var self = this; clearTimeout( this.omtimeout ); this.omtimeout = setTimeout( function() { var submenu = el.querySelector( ‘ul.zac_submenu’ ); if( submenu ) { el.className = ‘cbp-tm-show’; if( self._positionMenu( el ) === ‘top’ ) { el.className += ‘ cbp-tm-show-above’; } else { el.className += ‘ cbp-tm-show-below’; } } }, this.touch ? 0 : this.options.delayMenu ); }, _closeMenu : function( el ) { clearTimeout( this.omtimeout ); var submenu = el.querySelector( ‘ul.zac_submenu’ ); if( submenu ) { el.className = el.className.replace(new RegExp(«(^|\s+)» + «cbp-tm-show» + «(\s+|$)»), ‘ ‘); el.className = el.className.replace(new RegExp(«(^|\s+)» + «cbp-tm-show-below» + «(\s+|$)»), ‘ ‘); el.className = el.className.replace(new RegExp(«(^|\s+)» + «cbp-tm-show-above» + «(\s+|$)»), ‘ ‘); } }, _handleClick : function( el, ev ) { var item = el.parentNode, items = Array.prototype.slice.call( this.menuItems ), submenu = item.querySelector( ‘ul.zac_submenu’ ) // для начала закроем меню, если оно было открыто… if( this.current && items.indexOf( item ) !== this.current ) { this._closeMenu( this.el.children[ this.current ] ); this.el.children[ this.current ].querySelector( ‘ul.zac_submenu’ ).setAttribute( ‘data-open’, ‘false’ ); } if( submenu ) { ev.preventDefault(); var isOpen = submenu.getAttribute( ‘data-open’ ); if( isOpen === ‘true’ ) { this._closeMenu( item ); submenu.setAttribute( ‘data-open’, ‘false’ ); } else { this._openMenu( item ); this.current = items.indexOf( item ); submenu.setAttribute( ‘data-open’, ‘true’ ); } } }, _positionMenu : function( el ) { var vH = getViewportH(), ot = getOffset(el), spaceUp = ot.top , spaceDown = vH — spaceUp — el.offsetHeight; return ( spaceDown <= spaceUp ? ‘top’ : ‘bottom’ ); } } // добавляем в глобальное пространство имён window.cbpTooltipMenu = cbpTooltipMenu; } )( window );
Вот такой небольшой получился код. Можете скачать исходники или просто скопировать со страницы — все работает!
На этом буду с вами прощаться. Не на долго! Заходите чаще, подписывайтесь на обновления блога, а если что-то не понятно — задавайте вопрос в комментариях.
С вами был — ваш Юрич!
Демонстрация Исходники