Андрей @BaNru read-only
Пользователь
19 июня 2013 в 12:47

Разработка → Красивое меню на CSS3 из песочницы

Чуть меньше года назад Snickersmix публиковал статью "Меню с плавной инверсией цвета". В данной статье описывается меню, сделанное на JavaScript. Днём ранее он мне показывал сайт, на котором он делал это меню, и я, как поклонник NoScript, возмутился: «Это меню можно сделать на CSS!»

Красивое меню на CSS3

Я, конечно, погорячился, ибо сделать можно похожее меню, а не именно такое. Однако, обычный пользователь, особенно тот, который не в курсе дел, не заметит разницы. В том числе и я сразу не понял фишки этого меню. Хотя я поклонник всяких мелких деталей и нюансов при создании чего-либо, ибо из этих мелких деталей и нюансов строится общее впечатление о проекте.

Итак, предлагаю реализацию похожего меню на CSS3.

Чтобы сразу ты, уважаемый читатель, увидел отличия приведу финальную демку меню на CSS3 и демку меню от Snickersmix на JS

Теперь постараюсь вкратце рассказать про процесс создания


HTML
<nav id="a">
	<ul><li><a href="#">Главная</a></li><li><a href="#">О компании и услугах</a></li><li class="active"><a href="#">Контактная информация</a></li><li><a href="#">Вакансии</a></li><li class="slide"></li></ul>
</nav>

1) У меню display inline-block, поэтому между тегов не должно быть пробелов и переносов строк
2) Последний элемент меню с классом slide будет двигающейся плашкой. Я искал способ сделать через псевдоэлемент before/after, но так и не нашел.

Вариант 1
Данный вариант я написал достаточно быстро — тут фиксированная ширина элементов.

В этом и остальных меню используется CSS3 анимация перехода transition
transition: all 0.5s ease-in-out;

Данную анимацию я назначил на любые (all) действия/изменения над элементами списка (li, a).

Теперь надо было заставить двигаться элемент с классом slide. Для этого я задал этому элементу position: absolute, не забыв его родителю (ul) задать position: relative, чтобы slide позиционировался относительно меню, а не страницы. Таким образом, мы с помощью left или right можем двигать его по меню.

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

.active:nth-child(1) ~ li.slide, /* тут для АКТИВНОГО пункта позиция */
li:hover:nth-child(1) ~ li.slide { /* тут при наведение позиция */
	left: 0;
	width: 147px;
}
.active:nth-child(2) ~ li.slide,
li:hover:nth-child(2) ~ li.slide {
	left: 147px;
	width: 241px;
}
.active:nth-child(3) ~ li.slide,
li:hover:nth-child(3) ~ li.slide {
	left: 388px;
	width: 257px;
}
.active:nth-child(4) ~ li.slide,
li:hover:nth-child(4) ~ li.slide {
	left: 645px;
	width: 156px;
}


Вроде работает, но ужасно неудобно:
— Необходимо постоянно просчитывать элементы, если они меняются
— Имеется баг — если шрифты не проходят, то всё меню рушится

Вариант 2
Вариант с анимацией фона

Меню было сделано и показано Snickersmix. И после мне были «открыты глаза». Оказывается, у него фишка в «плавной инверсии цвета». Тут я начал искать варианты решения, но на данный момент не нашел, зато было сделано само меню.

Вариант 1a
Начались поиски, и родился вариант «один с половиной». Получилось небольшое украшательство

Я надеялся, что можно попробовать как-то реализовать через фильтры svg матриц, но к сожалению ничего не получилось (Вариант 3)

И попытка сделать через псевдоэлементы before/after, вместо дополнительного элемента slide, но тоже не удачно. Ждём CSS4 и возможность обращаться к родителю. (Вариант 4)

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

Прошел с тех пор почти год и я решил пофиксить меню, а заодно и написать статью.
И так, встречайте, финальный пятый вариант данного меню

В общем, ничего кардинально нового не появилось. Отличие лишь в том, что размеры указаны в процентах, что избавляет нас от проблемы со шрифтами, а заодно даёт возможно вставить меню в резиновую или адаптивную верстку.

Так же в пятый вариант были добавлены фиксы для IE6-9. Конечно, в них не будет анимации, но меню вполне съедобно.

В общем вот и всё. Всё достаточно легко и просто.
Если кто придумает другой вариант реализации — буду рад увидеть и, думаю, не только я.

Спасибо, что дочитали до конца!
Андрей @BaNru
карма
3,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (8)

  • +2
    Мне кажется такие меню это немного пережиток, ибо для сайтов с «контентом» это не актуально! и даже губительно…
    Но как фича ради фича неплохо… для клиентов любящих «свистелки» само-то!
    • +1
      Ну это сделано for fun и может кто-то что-то интересно подчеркнёт, может кто обучится по ней чему нибудь интересному…
  • 0
    А ещё с разной шириной элементов можно[?] :)
    • 0
      Да. Первый пример показывает как это сделать в пикселях, а пятый — в процентах. Я привёл в статье кусок кода, который за это отвечает. Только высчитывать надо, что не очень удобно.
  • 0
    В Google Chrome последний (правый) пункт меню с автоматическим переводом текста — глючит.
    • 0
      Проверял в Google Chrome Canary (29) и Google Chrome 16 — полет нормальный. Можно поподробнее и желательно со скринами?

      Знаю, что в Хроме есть небольшой глюк (не во всех, через раз) с анимацией при загрузке страницы — анимация срабатывает. Правится такое только указанием более конкретной анимацией, вместо all.
  • 0
    В FireFox 21 под Ubuntu 12.04 во всех примерах все перекошено.
  • 0
    to Radik_Wind
    В том числе и последняя версия? Можно скрин в студию?

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