Как сделать плавное выпадающее меню на CSS
Приветствую! Если ты начинающий верстальщик, то рано или поздно ты столкнешься с тем, что захочешь как-то оживить свои страницы, сделать их хоть немного интерактивными. Как нельзя лучше тут тебя смогут выручить CSS анимации. Но нужно знать, где и как их применять.
Сегодня я расскажу, как сделать выпадающее меню на чистом CSS и как добавить ему плавности с помощью CSS анимации. Если ты не знаешь, что такое CSS анимация, то самое время ознакомиться с азами.
Верстаем меню HTML + CSS
Для начала, чтобы нам было с чем работать, давайте сверстаем простое одноуровневое меню. Не будем сильно заморачиваться с дизайном, для наглядности хватит и этого:
Что мы имеем? Самый обыкновенные ненумерованный список с идентификатором «top_menu» и со ссылками, обернутыми в элементы этого самого списка. Все банально и просто. При наведении пункты меню меняют цвет… это все вы уже знаете и понимаете, как это сделать (я надеюсь).
Добавляем меню второго уровня
Чтобы сделать многоуровневое меню, нам нужно добавить второй ненумерованный список внутрь первого. Думаю, это вы проходили где-то на начальных уроках. А также то, что его вставить нужно не просто внутри нашего списка, а именно внутри элемента списка, то есть тега «li», сразу после закрывающего тега «a».
Позиционируем вложенные списки абсолютно по отношению к «li», в которые они вложены. А все «li» верхнего уровня позиционируем относительно (relative). Чтобы выпадающее меню находилось СРАЗУ же после нашего меню верхнего уровня, ему (выпадающему – “inner_menu”) нужно задать
position: absolute; top: 100%;
То есть отступ от верхней границы родителя будет равен высоте родителя. Очень логично, по-моему.
Помимо позиционирования нужно придать выпадающему меню стиль как у меню верхнего уровня. Яблочко от яблоньки, как говорится…
Как видите, наше выпадающее меню пока выглядит не выпадающим, а выпавшим и висящим. Но ничего, это мы скоро исправим.
Как сделать выпадающее меню действительно выпадающим
Нет ничего проще! Чтобы наш вложенный список сделать выпадающим меню, его нужно просто скрыть! А потом открывать только тогда, когда курсор мыши будет проноситься над пунктом меню верхнего уровня, который содержит в себе выпадающее меню. Звучит, может быть, немного сложно, но на самом деле это решается буквально несколькими строчками кода.
Выпадающему меню добавляем:
А чтобы его отобразить, нужно прописать:
Что нам говорит это целое скопище селекторов? Читаем с конца. Мы задаем стили (видмости) для списка второго уровня, который лежит внутри элемента списка первого уровня, но стили эти сработают только в том случае, если мы наведем мышкой (ховер) на элемент «li» в который вложен наш список второго уровня.
Надеюсь, я выразился понятно. Если нет, попробуйте прочитать несколько раз. А еще лучше просто понимать это, глядя на код. Смотрим, что у нас получилось:
Да, мы вроде бы добились того, чего хотели – мы сделали выпадающее меню, самое настоящее выпадающее меню, мать его! Но ему чего-то не хватает. А знаете чего? Плавности! Ведь все выглядит так, как будто меню не выпадает, а просто появляется. Причем очень резко, моментально даже, я бы сказал.
Ну что же, давайте еще немного поколдуем над ним.
Плавное выпадающее меню – это просто
Итак, давайте сделаем плавное выпадающее меню на чистом CSS. Зачем это делать? Потому что люди любят, когда все плавненько и мягонько… и это выглядит красиво. Будет плюс к юзабилити вашего сайта. Погнали!
Запомните, вы можете анимировать только точные математические величины, например 50px и 300px, 0 и 100%, 0,5 и 1,0 и так далее. В нашем случае мы не сможем анимировать два состояния нашего выпадающего меню (display:none; и display:block;).
Но мы можем заменить их на прозрачность – opacity:0 и opacity:1. И задать время в течение которого наше меню будет проявляться из прозрачного состояния. Да, это действительно сработает, однако это не совсем тот эффект, который вы возможно ожидали. Поэтому давайте сделаем немного сложнее. Но это того стоит, поверьте.
Чтобы анимация получилась более плавной и предсказуемой, пришлось задать фиксированную высоту пунктам выпадающего меню, хотя можно было обойтись и без этого. Методов уйма, только придумывай комбинации и решай задачи.
Как видно из кода, мы анимировали высоту элементов выпадающего списка и их прозрачность. Этого оказалось достаточно для того, чтобы сделать красивую плавную анимацию выпадающего меню.
Что нам понадобилось для анимации? Два состояния пунктов нашего меню, а также свойство transition, которое проинтерполировало эти состояния, то есть заполнило все промежуточные значения за отведенный промежуток времени. Вот и все!
Еще проще можно было бы сделать с применением jQuery, но мы же оговорили сначала, что будем сегодня работать с чистым CSS. А еще красивее можно было сделать, добавив к анимациям кривые Безье, однако эта тема немного выходит за рамки сегодняшней. Но мы к ней обязательно вернемся позже.
Вывод:
Теперь вы можете похвастаться своим друзьям и близким, что знаете, как сделать выпадающее меню на чистом CSS. Это действительно полезный навык, который вам еще не раз пригодится. Ну, сами посудите, много ли вы видели сайтов со статичным меню? Нет, большинство сайтов имеют именно выпадающее меню.
Кстати это был мой первый урок по CSS. Опишите, как вам? Понятно все объяснил или нужно еще подробнее разжевывать? И стоит ли вообще продолжать писать статьи на тему лайфхаков в CSS?
Спасибо за внимание и до скорых встреч!
Друзья, если вы заметили на сайте какой-нибудь баг, то напишите об этом в комментариях или отправьте сообщение на почту через контакты, и мы его исправим.
А также мы будем рады услышать ваши пожелания, если вам по какой-то причине неудобно пользоваться сайтом.
Не будьте равнодушными к проекту. Спасибо! 🙂
Нам очень приятно! Не могли бы вы поделиться этой статьей с друзьями? А также мы будем рады, если вы оставите комментарий.
Обещаем исправиться! Если вам есть, чем дополнить статью, напишите об этом в комментариях. А также будем благодарны за конструктивную критику. Спасибо!
Добавить комментарий Отменить ответ
Огромное спасибо, решили насущную мою проблему! Пробовал реализовать то же самое через div и a вместо ul и li — отказывается работать, не воспринимает ссылки как часть div, а потому при наведении на меню оно сразу исчезает..
С «div» и «a» тоже должно все работать нормально. Но ul более правильно использовать для меню. А в идеале еще и в nav все это дело обернуть
10 Dropdown Menu Animations with CSS Transforms
Dropdown menus allow the user to see more information about a particular topic without overwhelming the page with too much information. Most dropdown menu animations follow one of two patterns, animating the whole menu as a group or animating each item within the menu individually. CSS transforms allow us to animate either pattern with great performance because CSS transforms affect the Composite step in your browser’s Critical Rendering Path rather than the Paint, Layout, or Styles step. Below are five animations using CSS transforms for both the whole menu and each item individually. The CSS syntax is Stylus, which is a similar to SASS.
While animations can add some fun visual flair, keep in mind these examples are slightly exaggerated to make the mechanics of the animation more obvious.
Animating the Whole Dropdown Menu
The structure is the same for all menus: dropdown is the container for the menu title and the hidden menu. dropdown_menu is the actual menu itself, which is by default hidden.
1 . li class="dropdown dropdown-6">2 . Scale Down3 . ul class="dropdown_menu dropdown_menu--animated dropdown_menu-6">4 . li class="dropdown_item-1">Item 1li>5 . li class="dropdown_item-2">Item 2li>6 . li class="dropdown_item-3">Item 3li>7 . li class="dropdown_item-4">Item 4li>8 . li class="dropdown_item-5">Item 5li>9 . ul>10 . li>
The dropdown_menu is displayed only when the whole dropdown (the title and button) is hovered. This will display the dropdown menu on hover without any animations.
1 . .dropdown_menu2 . position: absolute3 . top: 100%4 . left: 05 . width: 100%6 . perspective: 1000px7 . display: none8 . .dropdown:hover .dropdown_menu--animated9 . display: block
To animate the menu we need to add the animation property to the dropdown_menu . The animation-name property should be set the name we give to the @keyframes rule, in this case, growDown . The animation-fill-mode property defines what styles should be applied at the end of the animation. In our case, we are animating the menu from the closed state to the open state. This means we want the dropdown menu to preserve the styles of the final animation state, the value forwards allows us to do that.
1 . .dropdown_menu-62 . animation: growDown 300ms ease-in-out forwards
The last property we need to consider is transform-origin, which defines where the animation is applied. For our animations, this property defines where the menu originates from physically. The default setting of transform-origin will scale the menu from the «center of the menu» not from the button. For example, animating the roateX transform property will look like this with the default transform-origin value.
Changing transform-origin to top center will make the animation rotate from the button.
1 . .dropdown_menu-62 . animation: growDown 300ms ease-in-out forwards3 . transform-origin: top center
We can choose from any of the 21 transform functions to animate our menu using a @keyframes rule. The only rule we need to follow is that the final state of the animation, the 100% property, must be the normal state for the menu being open. For example, if we animate the scaleY of the menu, we need to make sure that scaleY is set to 1 so the menu looks normal when the animation is finished.
You’ll notice that each animation «goes past» the intended end state around 80% or 70% then returns to the end state at 100% . This is a common technique in animation to create the illusion of momentum or «bounce» to give it more of a natural feel. Two examples are shown below, but check the Codepen above for more examples.
1 . @keyframes growDown2 . 0%3 . transform: scaleY(0)4 . >5 . 80%6 . transform: scaleY(1.1)7 . >8 . 100%9 . transform: scaleY(1)10 . >11 . >
1 . @keyframes rotateMenu2 . 0%3 . transform: rotateX(-90deg)4 . >5 . 70%6 . transform: rotateX(20deg)7 . >8 . 100%9 . transform: rotateX(0deg)10 . >11 . >
Animating Each Menu Item
The HTML structure is identical to animating the whole menu. Each menu item, however, needs to set opacity to 0 in addition to setting display: none . We do this is because we don’t want all menu items to be visible immediately, like we did when animating the whole menu. Instead, we will animate each into view individually by animating opacity with a transform.
1 . .dropdown_menu li2 . display: none3 . color: white4 . background-color: #34495e5 . padding: 10px 20px6 . font-size: 16px7 . opacity: 08 . &:hover9 . background-color: #2980b910 .11 . .dropdown:hover .dropdown_menu li12 . display: block
Animating the whole menu meant we only needed to add an animation for each menu, but animating each menu item individually means we need to add a separate animation property for each menu item. Fortunately, all menu items will share the same @keyframe rule, same duration, same timing function, same animation-fill-mode , and same transform-origin property. The only property that needs to be different is the animation-delay to stagger each item’s animation.
We could manually write a CSS selector for each dropdown menu item with a different animation-delay or we can take advantage of Stylus’s for loop to iterate over each and generate those selectors automatically. The end result will be the same so let’s use a for loop to make our lives easier.
There are five menu items for each dropdown, to iterate five times we can use the following syntax: for num in (1..5) . Each dropdown_item has a class with a sequential number: dropdown_item-1 , dropdown_item-2 , etc. Therefore, we can select each by using the num variable and selector interpolation: .dropdown_item- . Finally, we can use the num variable to delay each item by an even amount. If the animation duration is 300ms and there are 5 items overall, then we can delay each item by 60ms increments: (num * 60ms) . Putting this all together produces the following:
1 . .dropdown_menu-22 . for num in (1..5)3 . .dropdown_item-4 . animation: rotateX 300ms (num * 60ms) ease-in-out forwards5 . transform-origin: top center
The @keyframe rules are almost the exact same as the whole menu animations, with the exception of also animating opacity from 0 to 1 .
1 . @keyframes rotateX2 . 0%3 . opacity: 0;4 . transform: rotateX(-90deg);5 . >6 . 50%7 . transform: rotateX(-20deg);8 . >9 . 100%10 . opacity: 1;11 . transform: rotateX(0deg);12 . >13 . >