Адаптивное меню без Javascript. Флексбокс для интерфейсов: основные паттерны Создание HTML5 контейнера

Если говорить коротко, то верстка с Flexbox дает нам простые решения некогда непростых задач. Например, когда нужно выровнять элемент по вертикали, или прижать подвал к низу экрана, или просто вставить несколько блоков в один ряд, так чтобы они занимали все свободно пространство. Подобные задачи решаются и без flex. Но как правило, эти решения больше похожи на «костыли» - приемы использовать css не по назначению. Тогда как с flexbox такие задачи решаются именно так, как задумывает flex-модель.

CSS Flexible Box Layout Module (CSS модуль для макетов с гибкими блоками), коротко flexbox, создана, чтобы убрать недостатки при создании самых разных HTML конструкций, в том числе адаптированных под разную ширину и высоту, и сделать верстку логичной и простой. А логичный подход, как правило работает в неожиданных местах, там где результат не проверялся - логика наше все!

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

Базовые знания

FlexBox состоит из Контейнера и его Дочерних элементов (items) (гибких элементов).

Для включения flexbox, любому HTML элементу достаточно присвоить css свойство display:flex; или display:inline-flex; .

1
2

После включения flex свойства, внутри контейнера создаются две оси: главная и поперечная (перпендикулярная (⊥), кросс ось). Все вложенные элементы (первого уровня) выстраиваются по главной оси. По умолчанию главная ось горизонтальная и имеет направление слева направо (→), а кросс ось соответственно вертикальная и направлена сверху вниз (↓).

Главную и кросс оси можно поменять местами, тогда элементы будут располагаться сверху вниз (↓) и когда перестанут вмещаться в высоту то будут двигаться слева направо (→) - то есть оси просто поменялись местами. При этом начало и конец расположения элементов не меняется - меняются только направления (оси)! Именно поэтому нужно представлять себе оси внутри контейнера. Однако не нужно думать, что есть какие-то там «физические» оси и они на что-то влияют. Ось тут - это только лишь направление движения элементов внутри контейнера. Например, если мы указали выравнивание элементов по центру основной оси и потом изменили направление этой основной оси, то изменится и выравнивание: элементы были в середине по горизонтали, а стали в середине по вертикали... См. пример.

Еще одной важной особенностью Флекс-бокс является наличие рядов в поперечном направлении. Чтобы понять о чем речь, давайте представим что есть главная горизонтальная ось, много элементов и они не «лезут» в контейнер, поэтому переходят на другой ряд. Т.е. контейнер выглядит так: контейнер, внутри него два ряда, в каждом ряду по несколько элементов. Представили? А теперь запомните, что выравнивать по вертикали мы можем не только элементы, но и ряды! Как это работает хорошо видно в примере к свойству . А вот так это выглядит схематически:

CSS свойства, которые могут влиять на модель построения макета: float , clear , vertical-align , columns не работают во flex конструкции. Тут используется другая модель построения макета и эти css свойства просто игнорируются.

CSS свойства Flexbox

Flexbox содержит разные css правила для управления всей flex конструкцией. Одни нужно применять к основному контейнеру, а другие к элементам этого контейнера.

Для контейнера

display:

Включает flex свойство для элемента. Под это свойство попадает сам элемент и вложенные в него элементы: затрагиваются только потомки первого уровня - они станут элементами flex контейнера.

  • flex - элемент растягивается на всю ширину и имеет свое полное пространство среди окружающих блоков. Происходит перенос строк в начале и в конце блока.
  • inline-flex - элемент обтекается другими элементами. При этом его внутренняя часть форматируется как блочный элемент, а сам элемент - как встроенный.

flex и inline-flex отличаются тем что по-разному взаимодействуют с окружающими элементами, подобно display:block и display:inline-block .

flex-direction:

Изменяет направление главной оси контейнера. Поперечная ось меняется соответственно.

  • row (default) - направление элементов слева направо (→)
  • column - направление элементов сверху вниз (↓)
  • row-reverse - направление элементов справа налево (←)
  • column-reverse - направление элементов снизу вверх ()
flex-wrap:

Управляет переносом непомещающихся в контейнер элементов.

  • nowrap (default) - вложенные элементы располагаются в один ряд (при direction=row) или в одну колонку (при direction=column) независимо от того помещаются они в контейнер или нет.
  • wrap - включает перенос элементов на следующий ряд, если они не помещаются в контейнер. Так включается движение элементов по поперечной оси.
  • wrap-reverse - тоже что wrap только перенос будет не вниз, а вверх (в обратном направлении).
flex-flow: direction wrap

Объединяет оба свойства flex-direction и flex-wrap . Они часто используются вместе, поэтому чтобы писать меньше кода было создано свойство flex-flow .

flex-flow принимает значения двух этих свойств, разделенные пробелом. Или можно указать одно значение любого свойства.

/* только flex-direction */ flex-flow: row; flex-flow: row-reverse; flex-flow: column; flex-flow: column-reverse; /* только flex-wrap */ flex-flow: nowrap; flex-flow: wrap; flex-flow: wrap-reverse; /* сразу оба значения: flex-direction и flex-wrap */ flex-flow: row nowrap; flex-flow: column wrap; flex-flow: column-reverse wrap-reverse; justify-content:

Выравнивает элементы по основной оси: если direction=row, то по горизонтали, а если direction=column, то по вертикали.

  • flex-start (default) - элементы будут идти с начала (в конце может остаться место).
  • flex-end - элементы выравниваются по концу (место останется в начале)
  • center - по центру (место останется слева и права)
  • space-between - крайние элементы прижимаются к краям (место между элементами распределяется равномерно)
  • space-around - свободное пространство равномерно распределяется между элементами (крайние элементы не прижимаются к краям). Пространство между краем контейнера и крайними элементами будет в два раза меньше чем пространство между элементами в середине ряда.
  • space-evenly
align-content:

Выравнивает ряды, в которых находятся элементы по поперечной оси. То же что justify-content только для противоположной оси.

Заметка: Работает когда есть как минимум 2 ряда, т.е. при наличии только 1 ряда ничего не произойдет.

Т.е. если flex-direction: row , то это свойство будет выравнивать невидимые ряды по вертикали ¦ . Тут важно заметить, что высота блока должна быть задана жестко и должна быть больше высоты рядов иначе сами ряды будут растягивать контейнер и любое их выравнивание теряет смысл, потому что между ними нет свободного места... А вот когда flex-direction: column , то ряды движется по горизонтали → и ширина контейнера почти всегда больше ширины рядов и выравнивание рядов сразу приобретает смысл...

  • stretch (default) - ряды растягиваются заполняя строку полностью
  • flex-start - ряды группируются в верхней части контейнера (в конце может остаться место).
  • flex-end - ряды группируются в нижней части контейнера (место останется в начале)
  • center - ряды группируются по центру контейнера (место останется по краям)
  • space-between - крайние ряды прижимаются к краям (место между рядами распределяется равномерно)
  • space-around - свободное пространство равномерно распределяется между рядами (крайние элементы не прижимаются к краям). Пространство между краем контейнера и крайними элементами будет в два раза меньше чем пространство между элементами в середине ряда.
  • space-evenly - тоже что space-around , только расстояние у крайних элементов до краев контейнера такое же как и между элементами.
align-items:

Выравнивает элементы по поперечной оси внутри ряда (невидимой строки). Т.е. сами ряды выравниваются через align-content , а элементы внутри этих рядов (строк) через align-items и все это по поперечной оси. По главной оси такого разделения нет, там нет понятия рядов и элементы выравниваются через justify-content .

  • stretch (default) - элементы растягиваются заполняя строку полностью
  • flex-start - элементы прижимаются к началу ряда
  • flex-end - элементы прижимаются к концу ряда
  • center - элементы выравниваются по центру ряда
  • baseline - элементы выравниваются по базовой линии текста

Для элементов контейнера

flex-grow:

Задает коэффициент увеличения элемента при наличии свободного места в контейнере. По умолчанию flex-grow: 0 т.е. никакой из элементов не должен увеличиваться и заполнять свободное место в контейнере.

По умолчанию flex-grow: 0

  • Если всем элементам указать flex-grow:1 , то все они растянуться одинаково и заполнять все свободное место в контейнере.
  • Если одному из элементов указать flex-grow:1 , то он заполнит все свободное место в контейнере и выравнивания через justify-content работать уже не будут: свободного места нет выравнивать нечего...
  • При flex-grow:1 . Если один из них имеет flex-grow:2, то он будет в 2 раза больше, чем все остальные
  • Если все flex-блоки внутри flex-контейнера имеют flex-grow:3 , то они будут одинакового размера
  • При flex-grow:3 . Если один из них имеет flex-grow:12 , то он будет в 4 раза больше, чем все остальные

Как это работает? Допустим, что контейнер имеет ширину 500px и содержит два элемента, каждый из которых имеет базовую ширину 100px. Значит в контейнере остается 300 свободных пикселей. Теперь, если первому элементу укажем flex-grow:2; , а второму flex-grow: 1; , то блоки займут всю доступную ширину контейнера и ширина первого блока будет 300px, а второго 200px. Объясняется это тем, что доступные 300px свободного места в контейнере распределились между элементами в соотношении 2:1, +200px первому и +100px второму.

Заметка: в значении можно указывать дробные числа, например: 0.5 - flex-grow:0.5

flex-shrink:

Задает коэффициент уменьшения элемента. Свойство противоположное flex-grow и определяет как элемент должен сжиматься, если в контейнере не остается свободного места. Т.е. свойство начинает работать, когда сумма размеров всех элементов больше чем размер контейнера.

По умолчанию flex-shrink:1

Допустим, что контейнер имеет ширину 600px и содержит два элемента, каждый из которых имеет ширину 300px - flex-basis:300px; . Т.е. два элемента полностью заполняют контейнер. Первому элементу укажем flex-shrink: 2; , а второму flex-shrink: 1; . Теперь уменьшим ширину контейнера на 300px, т.е. элементы должны сжаться на 300px чтобы находится внутри контейнера. Сжиматься они будут в соотношении 2:1, т.е. первый блок сожмется на 200px, а второй на 100px и новые размеры элементов станут 100px и 200px.

Заметка: в значении можно указывать дробные числа, например: 0.5 - flex-shrink:0.5

flex-basis:

Устанавливает базовую ширину элемента - ширину до того как будут высчитаны остальные условия влияющие на ширину элемента. Значение можно указать в px, em, rem, %, vw, vh и т.д. Итоговая ширина будет зависеть от базовой ширины и значений flex-grow, flex-shrink и контента внутри блока. При auto элемент получает базовую ширину относительно контента внутри него.

По умолчанию: auto

Иногда лучше установить ширину элемента жестко через привычное свойство width . Например, width: 50%; будет означать, что элемент внутри контейнера будет ровно 50%, однако при этом все также будут работать свойства flex-grow и flex-shrink . Такое может быть нужно, когда элемент растягивается контентом внутри него, больше указанного во flex-basis. Пример .

flex-basis будет «жестким», если обнулить растяжение и сжатие: flex-basis:200px; flex-grow:0; flex-shrink:0; . Все это можно записать так flex:0 0 200px; .

flex: {grow shrink basis}

Короткая запись трех свойств: flex-grow flex-shrink flex-basis .

По умолчанию: flex: 0 1 auto

Однако можно указать и одно, и два значения:

Flex: none; /* 0 0 auto */ /* число */ flex: 2; /* flex-grow (flex-basis переходит в 0) */ /* не число */ flex: 10em; /* flex-basis: 10em */ flex: 30px; /* flex-basis: 30px */ flex: auto; /* flex-basis: auto */ flex: content; /* flex-basis: content */ flex: 1 30px; /* flex-grow и flex-basis */ flex: 2 2; /* flex-grow и flex-shrink (flex-basis переходит в 0) */ flex: 2 2 10%; /* flex-grow и flex-shrink и flex-basis */ align-self:

Позволяет изменить свойство align-items , только для отдельного элемента.

По умолчанию: от align-items контейнера

  • stretch - элемент растягиваются заполняя строку полностью
  • flex-start - элемент прижимаются к началу строки
  • flex-end - элемент прижимаются к концу строки
  • center - элемент выравниваются по центру строки
  • baseline - элемент выравниваются по базовой линии текста

order:

Позволяет менять порядок (позицию, положение) элемента в общем ряду.

По умолчанию: order: 0

По умолчанию элементы имеют order: 0 и ставятся в порядке их появления в HTML коде и направления ряда. Но если изменить значение свойства order, то элементы будут выстраиваться в порядке значений: -1 0 1 2 3 ... . Например если одному из элементов указать order: 1 , то сначала будут идти все нулевые, а потом элемент с 1.

Так можно, например, первый элемент перекинуть в конец, при этом не меняя направление движения остальных элементов или HTML код.

Заметки

Чем отличается flex-basis от width?

Ниже важные различия между flex-basis и width / height:

    flex-basis работает только для главной оси. Это значит что при flex-direction:row flex-basis контролирует ширину (width), а при flex-direction:column контролирует высоту (height). .

    flex-basis применяется только к flex элементам. А значит если отключить flex у контейнера это свойство не будет иметь эффекта.

    Абсолютные элементы контейнера не участвуют во flex конструкции... А значит, flex-basis не влияет на элементы flex контейнера, если они абсолютны position:absolute . Им нужно будет указать width / height.

  • При использовании свойства flex 3 значения (flex-grow/flex-shrink/flex-basis) можно скомбинировать и записать коротко, а для width grow или shrink нужно писать отдельно. Например: flex:0 0 50% == width:50%; flex-shrink:0; . Иногда это просто неудобно.

По возможности все же отдавайте предпочтение flex-basis . Используйте width только когда не подходит flex-basis .

Отличие flex-basis от width - баг или фича?

Контент внутри flex элемента распирает его и не может выйти за его пределы. Однако если установить ширину через width или max-width , а не flex-basis , то элемент внутри flex контейнера сумеет выйти за пределы этого контейнера (иногда нужно именно такое поведение). Пример:

Примеры Flex верстки

В примерах нигде не используются префиксы для кроссбраузерности. Сделал я так для удобного чтения css. Поэтому примеры смотрите в последних версиях Chrome или Firefox.

#1 Простой пример с выравниванием по вертикали и горизонтали

Начнем с самого простого примера - выравнивание по вертикали и горизонтали одновременно и при любой высоте блока, даже резиновой.

Текст по середине

Или так, без блока внутри:

Текст по середине

#1.2 Разделение (разрыв) между элементами флекс блока

Чтобы расположить элементы контейнера по краям и произвольно выбрать элемент после которого будет разрыв, нужно использовать свойство margin-left:auto или margin-right:auto .

#2 Адаптивное меню на flex

Сделаем меню в самом верху страницы. На широком экране оно должно быть справа. На среднем выравниваться по середине. А на маленьком каждый элемент должен быть на новой строке.

#3 Адаптивные 3 колонки

Этот пример показывает как быстро и удобно сделать 3 колонки, которые при сужении будут превращаться в 2 и затем в 1.

Обратите внимание, что сделать это можно без использования media правил, все на flex.

1
2
3
4
5
6

Перейдите в jsfiddle.net и изменяйте ширину секции «результат»

#4 Адаптивные блоки на flex

Допустим нам нужно вывести 3 блока, один большой и два маленьких. При этом нужно чтобы блоки подстраивались под маленькие экраны. Делаем:

1
2
3

Перейдите в jsfiddle.net и изменяйте ширину секции «результат»

#5 Галерея на flex и transition

Этот пример показывает как быстро можно сделать симпатичный аккордеон с картинками на flex. Обратите внимание на свойство transition для flex.

#6 Флекс во флекс (просто пример)

Задача сделать гибкий блок. Так чтобы начало текста в каждом блоке находилось на одной линии по горизонтали. Т.е. при сужении ширины, блоки растут в высоту. Нужно, чтобы картинка была вверху, кнопка всегда внизу, а текст по середине начинался по одной горизонтальной линии...

Для решения этой задачи, сами блоки растягиваются флексом и им установлена максимально возможная ширина. Каждый внутренний блок также является флекс конструкцией, с повернутой осью flex-direction:column; и элемент в середине (где находится текст) растягивается flex-grow:1; чтобы заполнить всё свободное пространство, так достигается результат - текст начинался с одной линии...

Еще примеры

Поддержка браузерами - 98.3%

Полной поддержки разумеется нет, однако все современные браузеры поддерживают flexbox конструкции. Для некоторых все еще нужно указывать префиксы. Для реальной картины заглянем в caniuse.com и видим, что без префиксов будут работать 96.3% используемых сегодня браузеров, с префиксами 98.3%. Это отличный показатель для того чтобы смело использовать flexbox.

Чтобы знать какие префиксы актуальны на сегодня (июнь. 2019), приведу пример всех flex правил с нужными префиксами :

/* Контейнер */ .flex { display:-webkit-box; display:-ms-flexbox; display:flex; display:-webkit-inline-box; display:-ms-inline-flexbox; display:inline-flex; -webkit-box-orient:vertical; -webkit-box-direction:normal; -ms-flex-direction:column; flex-direction:column; -ms-flex-wrap:wrap; flex-wrap:wrap; -ms-flex-flow:column wrap; flex-flow:column wrap; -webkit-box-pack:justify; -ms-flex-pack:justify; justify-content:space-between; -ms-flex-line-pack:distribute; align-content:space-around; } /* Элементы */ .flex-item { -webkit-box-flex:1; -ms-flex-positive:1; flex-grow:1; -ms-flex-negative:2; flex-shrink:2; -ms-flex-preferred-size:100px; flex-basis:100px; -ms-flex:1 2 100px; flex:1 2 100px; -ms-flex-item-align:center; align-self:center; -webkit-box-ordinal-group:3; -ms-flex-order:2; order:2; }

Лучше если свойства с префиксами будут идти до оригинального свойства.
В этом списке нет ненужных на сегодня (по caniuse) префиксов, но вообще префиксов больше.

Chrome Safari Firefox Opera IE Android iOS
20- (old) 3.1+ (old) 2-21 (old) 10 (tweener) 2.1+ (old) 3.2+ (old)
21+ (new) 6.1+ (new) 22+ (new) 12.1+ (new) 11+ (new) 4.4+ (new) 7.1+ (new)
  • (new) - новый синтаксис: display: flex; .
  • (tweener) - старый неофициальный синтаксис 2011 года: display: flexbox; .
  • (old) - старый синтаксис 2009 года: display: box;

Видео

Ну и не забывайте про видео, там порой тоже интересно и понятно. Вот парочка популярных:

Полезные ссылки по Flex

    flexboxfroggy.com - игра обучающая flexbox.

    Flexplorer - наглядный конструктор flex кода.

Всем привет! На начало 2018 года, по данным сайта Can I Use , верстка на flexbox-ах , поддерживается браузерами на 97.8%. Это отличные показатели для этой уже далеко не новой технологии по верстки сайтов. Теперь уже нет причин, почему не пользоваться этим удобным способом верстки. Чем мы сейчас и займемся.

Сверстав несколько макетов на CSS flexbox-ах , уже не хочется возвращаться к устаревшим float-ам и даже к такому любимому среди верстальщиков фреймворку, как Bootstrap . Хотя, Bootstrap ещё рано списывать со счетов, ведь используя его знаменитую сетку, можно "не париться" по поводу медиа запросов.

На этом уроке мы сверстаем шапку сайта с типичным адаптивным меню с применением flexbox CSS метода.

Шапка состоит из трех логичных блоков:

  1. Блок с логотипом
  2. Блок с меню, сделанное на списках
  3. Блок с иконкой и номером телефона

Эти три блока будут помещены в общий внешний блок-обертку header , который внутри себя будет делать display: flex; для трех блоков.

Внутри блока nav , еще раз пропишем display: flex; для пунктов меню. Таким образом мы добьёмся гибкости, при уменьшении размеров экрана, пункты меню могут выстраиваться друг под другом.

Для наглядной демонстрации сделаем всю HTML разметку для шапки сайта.







+380973457685



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

А сейчас внимание! Достаточно указать двум блокам display: flex; и всё содержимое шапки вытянется в строчку.

Header {
display: flex;
}

Header .menu ul {
display: flex;
}

Вот так работает flexbox .

*{
margin: 0;
padding: 0;
}

Body {
background-color: #fff;
font-family: "Open Sans", sans serif;
line-height: 1.5;
}

Header {
border: 2px solid #ccc;
display: flex;
flex-wrap: wrap; /*перенос строки */
justify-content: space-between; /*прижимает содержимое к краям */
align-items: center; /*выравнивает элементы по центру на вертикальной */
}

Header .logo {
padding-left: 30px;
}

Header .menu ul {
display: flex;
list-style: none;
}

Header .menu ul li {
margin: 20px 10px;
}

Header .menu ul a {
text-transform: uppercase;
text-decoration: none;
font-weight: bold;
color: #06a327;
}

Phone {
font-size: 110%;
color: #333;
padding-right: 40px;
}

Работаем над адаптивностью шапки

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

Например, на ширине экрана 900 пикселей, блок с телефон прижался к левому краю шапки.

В данном выпуске сделаем горизонтальное меню с эффектом при наведении. Подключим с шрифтовые иконки, задействуем режим наложения слоев при помощи mix-blend-mode: multiply , используем псевдоклассы :hover , и познакомимся с desplay:flax , все сделаем на чистом CSS3 .

Каркас меню в HTML

Скачивайте архив к себе на компьютер и разархивируйте. В нем находятся три папки, css где расположены файлы стилей, fonts папка с иконками, img в ней картинка на задний фон.

Перенесите все в свою среду разработки, в которой вы работаете. Я весь код буду писать в phpstorm . Копирую все папки и файлы в него, открываю index.html и приступим к описанию каркаса меню.

Прописываем body , тег

, в нем пишем div с классом .dws-menu , далее ul с классом .dws-ul ,затем списки li с классом .dws-li в количестве пяти штук. В списки вложим ссылку, затем I с классом .fa и классом fa- куда пропишем название иконок, далее атрибут aria-hidden=”true” , жмем применить.

Div.dws-menu>ul.dws-ul>li.dws-li*5>a>i.fa.fa-

Название иконок:

  • shopping-cart
  • server
  • folder-open
  • newspaper-o
  • Главная
  • Магазин
  • Услуги
  • Портфолио
  • Новости


Оформление CSS стилей

После того как сделали разметку, приступаем к оформлению стилей. Открываем style.css в body задаем задний фон и шрифт Verdana .

Body{ background-image: url("../img/escheresque_ste.png"); font-family: Verdana; }

Блоку с меню задаем фон, с верху делаем отступы в 100 пик. и ширину на весь экран.

Dws-menu{ background-color: white; margin-top: 100px; width: 100%; }

В блоки Ul выстраиваем списки горизонтально с помощью desplay:flax , убираем отступы, и центруем наши элементы при помощи justify-content:center .

Ul.dws-ul{ display: flex; padding: 0; justify-content: center; }

У списков LI убираем маркер и делаем отступ со всех сторон в 10 пик.

Li.dws-li { list-style: none; padding: 10px; }

У ссылок убираем подчеркивание, увеличим текст до 18 пик. и сделаем его черным цветом.

Li.dws-li a{ text-decoration: none; font-size: 18px; color: #000; }

Иконку немного сдвинем правее при помощи margin-right:10px .

Li.dws-li a i{ margin-right: 10px; }

Анимация при наведении

После того как сделали основное оформление приступим к анимированию при наведении.

Создадим дополнительные псевдо элементы, которые будут при наведении подчеркивать название элемента.

Опишем левую часть, отбираем ссылки и присвоим им псевдоэлемент li.dws-li a::before , пишем пустой content:’’; , шириной в 20 пик. и высоту в 3 пик. достаточно. Зададим цвет и для того что бы блок у нас появился присвоим ссылкам position: relative; , и с позиционируем абсолютно ссылкам, спустим его в самый низ, прижмем к левому краю.

Li.dws-li a{ ... position: relative; } li.dws-li a::before{ ... position: absolute; top: 100%; left: 0; }

Дублируем этот блок и присваиваем ему псевдоэлемент ::after . Меняем параметр left на right , цвет выбираем другой #ff2117 .

Li.dws-li a::after{ content: ""; width: 20px; height: 3px; background-color: #ff2117; position: absolute; top: 100%; right: 0; }

Затем делаем анимацию при наведении. Отбираем li и задаем им background чуть темнее.

Li.dws-li:hover{ background-color: #e5eae8; }

Для этого отбираем списки при наведении и добавляем к ним псевдоэлемент с шириной в 50% и задаем трансформацию по оси Х с лева на право. Это предаст ей движение.

Li.dws-li:hover a:before{ width: 50%; transform: translateX(100%); }

Тоже самое повторим для псевдоэлементом ::after , только теперь движение зададим с права на лево.

Li.dws-li:hover a:after{ width: 50%; transform: translateX(-100%); }

Li.dws-li a::before{ ... transition: .5s; mix-blend-mode: multiply; } li.dws-li a::after{ ... transition: .5s; mix-blend-mode: multiply; }

Получилось довольно не плохо, давайте теперь ширину поставим в ноль и при наведении ссылке добавим красный цвет.

Li.dws-li a:hover{ color: #e62117; }

Li.dws-li a{ ... padding: 5px; } li.dws-li a::before{ ... top: 90%; } li.dws-li a::after{ ... top: 90%; }

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



Урок подготовил Горелов Денис.