Подходы к реализации адаптивного меню. Большой обзор красивых многоуровневых меню с codepen

Сегодня мы поговорим о том, как создать адаптивное меню, используя только CSS3. Почему именно адаптивное? Мне кажется, это очень важно и должно стать нормой, ведь уже сегодня огромное число людей заходят в интернет через мобильные девайсы (ipad-ы, iphone-ы...). Этим пользователям необходимо дать возможность удобной навигации по вашему сайту. Для решения данной задачи можно воспользоваться jQuery или JavaScript-ом, но сегодня мы рассмотрим нечто иное.

По сути, у нас будет обычное выпадающее меню, основанное на списке UL > LI. Если же мы уменьшим экран, то все подменю будут доступны по клику. Давайте посмотрим, что у нас должно получиться:

Шаг 1. HTML

Вот и html код нашего демо примера:

index.html

Responsive menu | Script Tutorials

Тут я бы хотел отметить один момент - meta с атрибутом name=’viewpoint’. Это тег необходим для правильного масштабирования содержимого страницы на вашем экране, будь то монитор компа или мобилка. Весь остальной код не сложен для понимания. Многоуровневый список UL > LI.

Шаг 2. CSS

Итак, стили. В первую очередь, для самой страницы:

css/main.css

* { margin: 0; padding: 0; } html { background-color: #fff; height: 100%; } body { color: #333333; font: 0.75em/1.5em Arial,sans-serif; } .container { margin-left: auto; margin-right: auto; margin-top: 30px; width: 96%; }

Теперь напишем стили для верхних элементов меню:

/* common and top level styles */ #nav span { display: none; } #nav, #nav ul { list-style: none outside none; margin: 0; padding: 0; } #nav { background-color: #F5F5F5; border-bottom: 5px solid #333333; float: left; margin-left: 1%; margin-right: 1%; position: relative; width: 98%; } #nav ul.subs { background-color: #FFFFFF; box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2); color: #333333; display: none; left: 0; padding: 2%; position: absolute; top: 54px; width: 96%; } #nav > li { border-bottom: 5px solid transparent; float: left; margin-bottom: -5px; text-align: left; -moz-transition: all 300ms ease-in-out 0s; -ms-transition: all 300ms ease-in-out 0s; -o-transition: all 300ms ease-in-out 0s; -webkit-transition: all 300ms ease-in-out 0s; transition: all 300ms ease-in-out 0s; } #nav li a { display: block; text-decoration: none; -moz-transition: color 450ms ease-in-out 0s, background-color 450ms ease-in-out 0s; -ms-transition: color 450ms ease-in-out 0s, background-color 450ms ease-in-out 0s; -o-transition: color 450ms ease-in-out 0s, background-color 450ms ease-in-out 0s; -webkit-transition: color 450ms ease-in-out 0s, background-color 450ms ease-in-out 0s; transition: color 450ms ease-in-out 0s, background-color 450ms ease-in-out 0s; white-space: normal; } #nav > li > a { color: #333333; display: block; font-size: 1.3em; line-height: 49px; padding: 0 15px; text-transform: uppercase; } #nav > li:hover > a, #nav > a:hover { background-color: #F55856; color: #FFFFFF; } #nav li.active > a { background-color: #333333; color: #FFFFFF; }

Реализуем стили для подменю (выпадающий список):

/* submenu */ #nav li:hover ul.subs { display: block; } #nav ul.subs > li { display: inline-block; float: none; padding: 10px 1%; vertical-align: top; width: 33%; } #nav ul.subs > li a { color: #777777; line-height: 20px; } #nav ul li a:hover { color: #F55856; } #nav ul.subs > li > a { font-size: 1.3em; margin-bottom: 10px; text-transform: uppercase; } #nav ul.subs > li li { float: none; padding-left: 8px; -moz-transition: padding 150ms ease-out 0s; -ms-transition: padding 150ms ease-out 0s; -o-transition: padding 150ms ease-out 0s; -webkit-transition: padding 150ms ease-out 0s; transition: padding 150ms ease-out 0s; } #nav ul.subs > li li:hover { padding-left: 15px; }

Отлично. Теперь самое главное - каким образом меню станет адаптивным? На самом деле всё очень просто! Воспользуемся CSS3 медиа запросами, которые определят, какие из стилей отображать в зависимости от размеров пользовательского экрана. Также преобразовывать меню мы будем с помощью следующей хитрости. В нашем HTML коде, сразу за верхними уровнями меню, я поставил специальные SPAN-ы. Их мы и будем использовать, присвоив активное состояние (псевдо класс:target), при клике по верхним элементам меню. Таким образом, будет открываться подменю. Смотрим код:

/* responsive rules */ @media all and (max-width: 980px) { #nav > li { float: none; border-bottom: 0; margin-bottom: 0; } #nav ul.subs { position: relative; top: 0; } #nav li:hover ul.subs { display: none; } #nav li #s1:target + ul.subs, #nav li #s2:target + ul.subs { display: block; } #nav ul.subs > li { display: block; width: auto; } }

Итог

Итак, только что мы с нуля наклепали прикольное адаптивное меню. Надеюсь, оно вам пригодится. Удачи! До новых встреч!

Возвращаясь к теме всё возрастающей значимости мобильных устройств, невозможно обойти стороной меню сайта. По бо́льшей части для создания адаптивных меню используются решения на JavaScript, но всегда ли это оправдано? Пожалуй, нет. Ведь его можно сделать на чистом CSS, изменяя видимость элементов при помощи чекбокса.

Не будем долго разглагольствовать о плюсах и минусах данного подхода, а сразу обратимся к конкретному примеру. В данном случае это будет простое одноуровневное меню.

Что делать с многоуровневыми меню? Здесь есть несколько вариантов:

  • начать смотреть решения на JavaScript/jQuery
  • открывать второй уровень по наведению (что, надо сказать, не является хорошим решением)

Разметка будет чуть более многословной, чем нам это необходимо: здесь содержатся элементы, которые и вовсе могут не пригодиться. Однако, она довольно проста и разобраться в ней совсем несложно.

"initial-scale=1.0, width=device-width" > Pure CSS Menu

CSS Menu

Just css and html

Стили

На устройствах с экраном менее 640 пикселей пункты меню скрываются и остаётся только стилизованный через label чекбокс. Если чекбокс отмечен, меню становится видимым. Код для реализации:

/* Menu */ #menu-checkbox { /* чекбокс скрыт */ display : none ; } .main-menu { /* пункты меню скрыты */ display : none ; padding : 0 ; margin : 0 ; } .main-menu li { /* пункты меню расположены вертикально */ /* каждый имеет ширину 100% */ font-size : 1em ; display : block ; width : 100% ; } .main-menu a { /* немного стилизуем ссылки */ display : block ; border-bottom : 1px solid blueviolet ; color : lightslategray ; padding : .5em ; text-decoration : none ; } .main-menu a :hover { text-decoration : underline ; } .toggle-button { text-align : center ; display : block ; /* не забываем явно указать каким должен быть курсор */ cursor : pointer ; background-color : #333 ; color : #fff ; } .toggle-button :after { /* получаем данные из атрибута data-open в html */ content : attr (data-open ); display : block ; margin : 10px 0 ; padding : 10px 30px ; } #menu-checkbox :checked + nav [ role = "navigation" ] .main-menu { /* когда чекбокс активен меню становится видимым */ display : block ; } #menu-checkbox :checked + nav [ role = "navigation" ] .toggle-button :after { content : attr (data-close ); }

С мобильными устройствами разобрались. Осталось внести изменения для тех устройств, экран которых >= 640px. Делать это будем через медиа-запросы.

@media screen and (min-width : 640px ) { .toggle-button { /* label скрыт */ display : none ; } .main-menu { display : block ; margin : 0 auto ; background-color : #333 ; height : 30px ; } .main-menu li { /* теги

  • расположены в ряд */ width : calc (100% / 5 ); text-align : center ; display : inline-block ; margin-right : -4px ; } .main-menu a { display : inline-block ; margin-right : -4px ; font-size : .8em ; background-color : #333 ; text-decoration : none ; color : #fff ; text-transform : capitalize ; border-bottom : 0 ; } }

    Посмотрим, что получилось:

    Данный пример можно отыскать .

    Стилизация метки

    Разумеется, вместо data-open/close можно использовать что угодно. Например, добавить иконочный шрифт.

    Toggle-button :after { font-family : "fontello" ; content : "\e804" ; cursor : pointer ; padding : 15px ; font-size : 1.5em ; text-align : center ; } #menu-checkbox :checked + .main-menu .toggle-button :after { content : "\e804" ; }

    Или иконку с вместе с поясняющим текстом:

    Здесь мы получаем значение атрибутов data-open/close , отображаем данные через before , а саму иконку добавляем с помощью псевдоэлемента after .

    Toggle-button :before { content : attr (data-close ); font-size : 1rem ; position : relative ; right : 3px ; bottom : 3px ; } .toggle-button :after { content : "\f0c9" ; font-family : "FontAwesome" ; display : inline-block ; } #menu-checkbox :checked + nav [ role = "navigation" ] .menu { display : block ; } #menu-checkbox :checked + nav [ role = "navigation" ] .toggle-button :after { content : "\f0c9" ; font-family : "FontAwesome" ; color : green ; } #menu-checkbox :checked + nav [ role = "navigation" ] .toggle-button :before { color : green ; }

    В последних двух примерах читателю нужно будет самостоятельно поиграть с позиционированием иконок и расположением самого текста.

    Каких-то невероятных эффектов от подобной реализации меню ждать не приходится, хотя не сто́ит забывать о возможностях CSS-анимации.

    Привет. Очень давно не писал постов на тему работы html/css. Недавно как раз начал верстать новый макет и в процессе наткнулся на интересный прием, который позволяет сделать меню резиновым (в него можно будет добавлять новые пункты и размер не увеличиться, а всегда будет 100% родительского блока). Итак, сегодня реализуем на css резиновое меню.

    Кому лень читать статью, можно посмотреть это видео. Автор также все очень классно объясняет:

    Резиновое меню на CSS — шаг 1

    Первый шаг — это всегда html разметка, куда же без нее. Но в нашем случае все будет просто:

    1. блок обертка для меню
    2. само меню, выведенное через маркированный список (тег ul)
    3. ну и пункты меню внутри, а в них, соответственно, уже ссылки

    Все понятно, вот такой у меня код разметки:

    Выглядит это все стандартно, вот так:

    Теперь будем приводить все в нужный вид, за работу берется CSS.

    Шаг 2 — базовые стили

    Шаг 3 — реализуем резиновость

    Теперь беремся за само меню. У него (у тега ul) я уберу маркеры, сделаю фоновый , и, самое главное, свойством display: table-row заставлю контейнер для меню вести себя как табличный ряд. Это важно сделать для дальнейших манипуляций.

    R-menu{ background: linear-gradient(to right, #b0d4e3 0%,#88bacf 100%); display: table-row; list-style: none; }

    Как видите, приведенный код как раз решил все, о чем я писал. Кстати, градиенты удобно генерировать с помощью инструмента Ultimate CSS Gradient generator.

    R-menu li{ vertical-align: bottom; display: table-cell; width: auto; text-align: center; height: 50px; border-right: 1px solid #222; }

    • vertical-align: bottom — это свойство необходимо для того, чтобы в случае, если текст в пункте меню займет 2 строки, он отображался ровно. Когда мы сделаем меню, можете удалить это свойство, увеличить масштаб чтобы пункты сжались и текст перенесся на две строки и увидите проблему с отображением. Верните свойство и все будет нормально.
    • display: table-cell — поскольку мы задали самому меню отображения табличным рядом, логично будет задать его пунктам отображение как ячейки в таблице. Это обязательно.
    • width: auto — ширина будет вычисляться автоматически, в зависимости от длины текста в пункте
    • text-align: center — это просто для выравнивания текста внутри по центру
    • height: 50px — задаем высоту в 50 пикселей
    • ну и border-right это просто граница справа, такой разделитель для пунктов

    Пока меню выглядит неказисто, но ничего, настало время довести его до ума.

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

    R-menu li a{ text-decoration: none; width: 1000px; height: 50px; vertical-align: middle; display: table-cell; color: #fff; font: normal 14px Verdana; }

    И вот так теперь выглядит меню:

    Опять же, поясню некоторые строки:

    • свойство text-decoration отменяет подчеркивание у ссылок, которое ставится по умолчанию
    • width: 1000px — пожалуй, самая важная строка. Нужно задать ссылкам примерно такую ширину, можно и меньше, но обязательно больше максимально широкого пункта меню. Ссылки не станут в ширину 1000 пикселей, поскольку ширину ограничит пункт меню li, у которого ширина задана как auto, зато это позволит сделать так, чтобы при любом количестве пунктов в меню оно всегда было на 100 процентов ширины.
    • vertical-align: middle и display: table-cell — первое выровняет текст по вертикали по центру, а второе также делает отображение ссылок в виде ячеек. Оба свойства нужны.
    • font — ну это просто набор установок для шрифта. Читайте про css свойства для шрифтов в .

    Шаг 4 (по желанию) можно добавить интерактивности

    Например, чтобы при наведении изменялся цвет пункта меню. Реализуется это совсем просто, с помощью псевдокласса hover:

    R-menu li:hover{ background-color: #6bba70; }

    Тестируем меню на резиновость

    Отлично, меню готовы, но мы не проверили самое главное — насколько оно резиновое, как я вам и обещал. Что ж, добавлю в меню еще 2 пункта:

    Меню осталось в ширину на 600 пикселей. Остальные пункты просто немного ужались, чтобы поместились 2 новых.

    Добавлю еще 1 длинный пункт:

    Как видите, меню еще немного ужалось и длинный пункт отобразился вполне себе нормально. А если бы не было свойства vertical-align: bottom , о котором я вам говорил, то меню выглядело бы хуже.

    Уменьшу меню до трех пунктов.

    Пунктам стало гораздо свободнее, но само меню не поменялось в ширине. Вот мы и сделали 100% резиновое меню!

    Как его адаптировать?

    В принципе, если вы задали блоку-обертке не фиксированную, а максимальную ширину, то его даже не нужно адаптировать. В моем случае у меня стоит свойство max-width: 600px и когда ширина станет меньше 600 пикселей, блок просто будет уменьшаться вслед за экраном, не образуя горизонтальной прокрутки.

    Ну а если вы хотите как-то изменить или поправить меню на мобильных устройствах или широких экранах, то вам в помощь! Успехов в сайтостроении!

    Далеко не во всех проектах уместны излишние эффекты, которые могут значительно нагружать страницы, а особенно, если это касается адаптивной верстки, где пользователь может просматривать сайт на смартфонах или планшетах. Большинство таких эффектов, создаются с использованием JavaScript, поэтому, для примера, я решил показать, как можно сделать один из важнейших элементов сайта, а именно меню навигации , практически не прибегая к JS, а в основном только средствами CSS. Совсем нельзя отказаться от использования JS по той причине, что на мобильных устройствах и обычных компьютерах или ноутбуках, многие события отличаются и, если на компьютере в CSS мы можем спокойно использовать свойство :hover , то на планшете это уже не сработает так, как нам бы этого хотелось. Самые нетерпеливые, могут сразу (в примере изменяйте ширину окна браузера ).

    Итак, ставим такую задачу: создать резиновое по ширине меню, с переключением на мобильную его версию, где меню будет выпадающим по наведению или нажатию на кнопку. Структура HTML типичная для таких элементов, за исключением того, что мы добавляем еще один элемент - кнопку для раскрытия/скрытия меню в мобильной версии:

    CSS не совсем стандартный. Мы сделаем так, что наше меню будет вести себя так, как если бы мы использовали таблицу. Сразу хочу акцентировать внимание на том, что не все браузеры поддерживаю те свойства, которые мы будем использовать. Проблемы могут возникнуть с версиями IE ниже восьмой версии (хотя на них уже пора переставать ориентироваться ) и в пару моментах есть маленькие сложности с IE8, но как решить их - напишу ниже.

    * { margin: 0; padding: 0; } header { background-color: #C0C0C0; } #menu { display: table; /* описание ниже */ width: 100%; border-collapse: collapse; -webkit-box-sizing: border-box; /* описание ниже */ -moz-box-sizing: border-box; /* описание ниже */ box-sizing: border-box; /* описание ниже */ } #menu ul { display: table-row; /* описание ниже */ background-color: #FFFFFF; list-style: none; } #menu ul li { display: table-cell; /* описание ниже */ border: 1px solid #999999; } #menu ul li a { display: inline-block; width: 100%; height: 50px; line-height: 50px; font-size: 1.2em; text-align: center; } #menu ul li a:hover { background-color: #990000; color: #FFFFFF; } #nav_button { display: none; width: 50px; height: 50px; font-size: 2.5em; text-align: center; background-color: #FFFFFF; border: 1px solid #949494; cursor: pointer; } @media screen and (max-width: 600px) { /* описание ниже */ #menu { display: inline-block; position: relative; width: auto; } #menu ul { display: none; position: absolute; top: 0; width: 100%; z-index: 20; } #menu ul li { display: list-item; border-top: none; } #nav_button { display: inline-block; } #menu:hover, #menu.open_nav { width: 100%; -webkit-user-select: none; /* описание ниже */ -moz-user-select: none; /* описание ниже */ -webkit-touch-callout: none; /* описание ниже */ } #menu:hover ul, #menu.open_nav ul { display: block; margin-top: 50px; } }

    На некоторые стили обращать внимание не нужно; цвет бекграунда, размер шрифта и т.д. - это только для демонстрации. А нас должны интересовать следующие свойства с их значениями:

    Display: table; Указывает, что элемент будет себя вести аналогично элементу

    display: table-row; Элемент будет себя вести, как display: table-cell; Элемент будет себя вести, как
    или box-sizing: border-box; (и с вендорными префиксами) При расчетах ширины и высоты элемента, свойства width и height, будут включать в себя значения полей (padding ) и границ (border ). Нужно для того, чтоб избежать появления горизонтальной прокрутки, т.к. без этого свойства, при ширине меню в 100%, добавится еще и толщина border , а если есть, то и padding . -webkit-user-select: none; и -moz-user-select: none; Запрещает выделять элемент или текст. Нужно для мобильной версии, чтоб избежать неувязок, когда пользователь проводит по элементам меню, вместо того, чтобы нажать на него. -webkit-touch-callout: none; Отменяет всплытие подсказки при нажатии и удержании элемента. Работает только в Chrome и Safari. Так же, как и в предыдущем свойстве, служит для отмены нежелательных действий при работе с элементом. @media (медиа-запрос) Тема довольно обширная, но если в двух словах, то указывает браузеру, какие свойства применять для определенных типов носителей или технических характеристик устройства. В нашем случае - применять для screen (экранов мониторов) и max-width: 600px (если ширина окна браузера меньше 600px).

    Самое интересное, что на этом можно было бы поставить точку, если бы мы не учитывали смартфоны, планшеты и с уверенностью сказать, что меню сделано полностью на HTML и CSS. Но придётся прибегнуть к помощи JS/jQuery, а в данном случае, раз уж решено было сделать с наименьшей нагрузкой, именно к чистому JavaScript.

    Var d = document, navBut = d.getElementById("nav_button"), // кнопка включение меню navMenu = d.getElementById("menu"); // выпадающее меню // функция определения наличия родительского элемента по ID function hasParent(el, sId){ while(el) { if (el.id == sId) return true; el = el.parentNode; } return false; } // по касанию на кнопке, добавляем класс менюшке, // который соответствует свойству в css "#menu:hover" // и разворачиваем меню navBut.addEventListener("touchstart", function(e) { e.preventDefault(); navMenu.classList.add("open_nav"); }, false); // по касанию в документе, // если событие не было на каком-нибудь элементе меню (определяем с помощью функции "hasParent"), // убираем класс "open_nav" из меню, что привод к его закрытию d.addEventListener("touchstart", function(e) { if(!hasParent(e.target, "menu")) navMenu.classList.remove("open_nav"); }, false);

    Записываем этот код в отдельный js-файл и подключаем его в самом низу страницы, перед закрывающим тегом . Теперь пару слов о кроссбраузерности... Если вы рассчитываете на Internet Explorer ниже девятой версии, то для корректной работы, нужно подключить два фиксящих скрипта внутри тега :

    Первый позволяет старым браузерам адекватно воспринимать теги HTML5, а второй - "медиа-запросы", с которыми они так же не дружат. Хотя, с другой стороны, такие браузеры не используются на мобильных устройствах, а тот же тег