- PVSM.RU - https://www.pvsm.ru -
В этой публикации я хочу показать один из способов реализации адаптивного горизонтального меню с использованием Flexbox. Данный способ реализации меню используется на сайте Warface Hub [1], но немного с другой структурой и большим количеством свистелок.
Где-то с год назад, я попал в одну компанию, в которой мне сказали замечательную фразу: «Сначала делаем все с помощью CSS, а потом только добавляем JavaScript». Совет, вроде, хороший, и я ему последовал. Но как бывает, меня понесло. Сейчас мне это аукнулось тем, что не все нужно делать с таким подходом.
И так, ближе к делу. Я приступил к изучению и реализации.
Вы можете использовать свой набор инструментов
Для организации структуры стилей для меню я пользовался концепцией, которая описана тут [5]. Автор данной концепции предлагает разбить все описания стилей на несколько частей:
Таким образом мое понимание концепции привело меня к такой структуре:
Прежде чем начать рисовать HTML разметку, я бы хотел напомнить/показать интересное поведение CSS селекторов, которое нам пригодится.
<label for="input-0" class="label">Текст 1</label>
<input type="radio" name="input-trigger" id="input-0" class="input" />
<label for="input-1" class="label">Текст 1</label>
<input type="radio" name="input-trigger" id="input-1" class="input" />
В данном примере Вы можете заметить, что при нажатии на label Вы получите выбранный input. В этом ничего особенного нет (см. документацию [7]), но самое интересное происходит со стороны CSS селекторов.
.input:checked {
border-color: red;
}
Данный CSS селектор будет обработан только тогда, когда будет выбран input (см. :checked [8])
Второй момент, на который нужно обратить внимание в CSS селекторах — это выбор следующего элемента (см. Adjacent sibling selectors [9] и General sibling selectors [10]). То есть мы можем выбрать следующий элемент после текущего.
.input:checked + .label {
color: red;
}
В этом примере мы получили следующее поведение: при выбранном элементе с классом input следующий за ним элемент с классом label будет изменен в соответствии с описанными стилями.
Теперь это все можно объединить воедино.
<input type="radio" name="menu-item-trigger" id="menu-close" class="input input-hidden">
<nav class="menu">
<input type="radio" name="menu-item-trigger" id="menu-item-0" class="input input-hidden" />
<div class="menu-item menu-item-trigger">
<label for="menu-close" class="menu-item-close"> </label>
<label for="menu-item-0" class="menu-item-label">
<i class="fa fa-home"></i>
<span class="menu-item-label-text">Menu Item 0</span>
</label>
<div class="menu-sub">
<li class="menu-item menu-item-sub">
<a href="#" class="menu-item-label">
<span class="menu-item-label-text">Sub Item Menu 0</span>
</a>
</li>
<li class="menu-item menu-item-sub">
<a href="#" class="menu-item-label">
<span class="menu-item-label-text">Sub Item Menu 1 - With long label</span>
</a>
</li>
<li class="menu-item menu-item-sub">
<a href="#" class="menu-item-label">
<span class="menu-item-label-text">Sub Item Menu 2 - Withtooolongwordslikeingerman</span>
</a>
</li>
</div>
</div>
</nav>
В данном примере я добавил несколько элементов input и label, чтобы получилось следующее поведение:
Не выбран ни один пункт меню:
Выбран один пункт меню:
После таких манипуляций остается только скрыть элементы input.
Теперь необходимо добавить стили, чтобы данное меню хорошо отображалось при различных разрешениях и различных браузерах. На текущий момент мы сосредоточили наши усилия на поддержке тех браузеров, которые больше всего используются посетителями нашего ресурса. Получился небольшой список: Chrome, Firefox, IE Edge, IE 11 и их мобильные варианты последних версий.
Поддержка осуществляется путем добавления префиксов (postcss [11]) и отдельного написания стилей для конкретного браузера.
Адаптивность в Flexbox достигается очень просто. Достаточно описать контейнер, но иногда будет необходимо решить проблемы с контентом внутри. Например:
.label-text {
// @link: http://htmlbook.ru/css/text-overflow
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
display: inline-block;
}
В данном примере контейнер для элементов описан так:
.menu {
display: flex;
align-items: center;
flex-wrap: wrap;
}
Для каждого элемента в контейнере необходимо задать стили так, чтобы он заполнял все возможное пространство и выравнивали контент внутри себя в центре по вертикали:
.menu-item {
flex: 1 1 auto;
display: flex;
flex-direction: column;
align-items: stretch;
}
Более красивого отображения меню можно достичь с помощью media queries [12] и более точных размеров и позиций элементов.
После реализации данного примера я доработал его в рамках болевого проекта, который сейчас использует подобное адаптивное меню. Так же были выявлены плюсы и минусы избавления от Javascript в пользу CSS:
Плюсы:
Минусы:
Автор: OxCom
Источник [19]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/html/220329
Ссылки в тексте:
[1] Warface Hub: https://www.warface.com
[2] NPM: https://www.npmjs.com/
[3] GruntJs: http://gruntjs.com/
[4] SASS: http://sass-lang.com/
[5] тут: https://github.com/dsheiko/pcss
[6] normalize.css: https://github.com/necolas/normalize.css/
[7] документацию: http://www.w3schools.com/tags/tag_label.asp
[8] :checked: https://developer.mozilla.org/en-US/docs/Web/CSS/:checked
[9] Adjacent sibling selectors: https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors
[10] General sibling selectors: https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_selectors
[11] postcss: https://github.com/postcss/postcss
[12] media queries: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
[13] will-change: https://developer.mozilla.org/en-US/docs/Web/CSS/will-change
[14] Guide To Flexbox (EN): https://css-tricks.com/snippets/css/a-guide-to-flexbox/
[15] Guide To Flexbox (RUS): http://frontender.info/a-guide-to-flexbox/
[16] Mr. Froggy: http://flexboxfroggy.com/
[17] Demo: https://oxcom.github.io/pub-menu/
[18] Github Project: https://github.com/OxCom/pub-menu
[19] Источник: https://habrahabr.ru/post/317528/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.