Создаем выпадающее меню на чистом CSS

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

demosourse

Концепция

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

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

 

Разметка

Большинство выпадающих меню основано на использовании громоздкой разметки и Javascript. Наш вариант будет использовать простую структуру HTML кода и 19 строк CSS, с небольшим вкраплением CSS3 для придания внешнего лоска.

<ul id="nav">
	<li>
		<a href="#" title="Вернуться на главную страницу">Главная</a>
	</li>
	<li>
		<a href="#" title="Информация о компании">О нас</a>
		<ul>
			<li><a href="#">Продукты</a></li>
			<li><a href="#">Команда</a></li>
		</ul>
	</li>
	<li>
		<a href="#" title="Что мы можем для вас сделать">Услуги</a>
		<ul>
			<li><a href="#">Услуга один</a></li>
			<li><a href="#">Услуга два</a></li>
			<li><a href="#">Услуга три</a></li>
			<li><a href="#">Услуга четыре</a></li>
		</ul>
	</li>
	<li>
		<a href="#" title="Наша продуктовая линейка">Продукты</a>
		<ul>
			<li><a href="#">Маленький продукт (первый)</a></li>
			<li><a href="#">Маленький продукт (второй)</a></li>
			<li><a href="#">Маленький продукт (третий)</a></li>
			<li><a href="#">Маленький продукт (четвертый)</a></li>
			<li><a href="#">Большой продукт (пятый)</a></li>
			<li><a href="#">Большой продукт (шестой)</a></li>
			<li><a href="#">Большой продукт (седьмой)</a></li>
			<li><a href="#">Большой продукт (восьмой)</a></li>
			<li><a href="#">Невообразимый продукт (девятый)</a></li>
			<li><a href="#">Невообразимый продукт (десятый)</a></li>
			<li><a href="#">Невообразимый продукт (одиннадцатый)</a></li>
		</ul>
	</li>
	<li>
		<a href="#" title="Как с нами связаться">Контакт</a>
		<ul>
			<li><a href="#">Часы работы</a></li>
			<li><a href="#">Местоположение</a></li>
		</ul>
	</li>
</ul>

Разметка достаточно проста и представляет собой серию вложенных списков <ul>. Нет никаких ID, классов и элементов. Простой ясный код.

Элемент #nav <ul> содержит серию элементов <li>. Все пункты, которые нуждаются в выпадающих подпунктах, содержат другой элемент <ul>. Обратите внимание, что элемент <ul> выпадающих подпунктов не имеет класса. Мы используем каскадные стили, сохраняя разметку как можно более чистой.

 

CSS

Здесь происходит магия  превращения - мы используем CSS для трансформирования серии вложенных списков <ul> в отличное, простое в использовании и самодостаточное выпадающее меню.

/*------------------------------------*\
	НАВИГАЦИЯ
\*------------------------------------*/
#nav{
	float:left;
	width:100%;
	list-style:none;
	font-weight:bold;
	margin-bottom:10px;
}
#nav li{
	float:left;
	margin-right:10px;
	position:relative;
	display:block;
}
#nav li a{
	display:block;
	padding:5px;
	color:#fff;
	background:#333;
	text-decoration:none;
	
	text-shadow:1px 1px 1px rgba(0,0,0,0.75); /* Тень текста, чтобы приподнять его на немного */
	-moz-border-radius:2px;
	-webkit-border-radius:2px;
	border-radius:2px;
}
#nav li a:hover{
	color:#fff;
	background:#6b0c36;
	background:rgba(107,12,54,0.75); /* Выглядит полупрозрачным */
	text-decoration:underline;
}

/*--- ВЫПАДАЮЩИЕ ПУНКТЫ ---*/
#nav ul{
	list-style:none;
	position:absolute;
	left:-9999px; /* Скрываем за экраном, когда не нужно (данный метод лучше, чем display:none;) */
	opacity:0; /* Устанавливаем начальное состояние прозрачности */
	-webkit-transition:0.25s linear opacity; /* В Webkit выпадающие пункты будут проявляться */
}
#nav ul li{
	padding-top:1px; /* Вводим отступ между li чтобы создать иллюзию разделенных пунктов меню */
	float:none;
	background:url(dot.gif);
}
#nav ul a{
	white-space:nowrap; /* Останавливаем перенос текста и создаем многострочный выпадающий пункт */
	display:block;
}
#nav li:hover ul{ /* Выводим выпадающий пункт при наведении курсора */
	left:0; /* Приносим его обратно на экран, когда нужно */
	opacity:1; /* Делаем непрозрачным */
}
#nav li:hover a{ /* Устанавливаем стили для верхнего уровня, когда выводится выпадающий список */
	background:#6b0c36;
	background:rgba(107,12,54,0.75); /* Выглядит полупрозрачным */
	text-decoration:underline;
}
#nav li:hover ul a{ /* Изменяем некоторые стили верхнего уровня при выводе выпадающего пункта */
	text-decoration:none;
	-webkit-transition:-webkit-transform 0.075s linear;
}
#nav li:hover ul li a:hover{ /* Устанавливаем стили для выпадающих пунктов, когда курсор наводится на конкретный пункт */
	background:#333;
	background:rgba(51,51,51,0.75); /* Будет полупрозрачным */
	text-decoration:underline;
	-moz-transform:scale(1.05);
	-webkit-transform:scale(1.05);
}

Первый раздел кода весьма простой - мы устанавливаем обычное горизонтальное меню. Но, обратите внимание, что селекторы #nav li и #nav li a выделяют все элементы списка и ссылки в выпадающих пунктах тоже. Использование каскадов.

Следует отметить использование  position:relative; для элементов списка. Таким образом, мы сможем использовать  position:absolute; для вложенных элементов <ul>.

 

Вложенные списки

#nav ul{
	list-style:none;
	position:absolute;
	left:-9999px; /* Скрываем за экраном, когда не нужно (данный метод, лучше чем display:none;) */
	opacity:0; /* Устанавливаем начальное состояние прозрачности */
	-webkit-transition:0.25s linear opacity; /* В Webkit выпадающие пункты будут проявляться */
}

В данном коде устанавливаются стили для вложенных <ul> в пункт верхнего уровня. Очевидно, что нужно удалить метки пунктов списка с помощью  list-style:none;, и установить position:absolute; для позиционирования выпадающих подпунктов под пунктом списка, который их содержит.

Следующая строка гораздо более интересна. Обычно используется свойство display:none; для того, чтобы скрыть выпадающий пункт, когда он не используется.  Но так как большинство программ для чтения с экрана игнорируют все, что имеет свойство display:none;, то использование такого метода очень нежелательно. Вместо этого мы используем абсолютное позиционирование <ul> для помещения его в позицию -9999px за пределами экрана, когда он не используется.

Затем следует свойство opacity:0;, для скрытия <ul>, и декларация для браузеров Webkit, для плавного вывода элемента <ul> при наведении курсора мыши.

#nav ul li{
	padding-top:1px; /* Вводим отступ между li чтобы создать иллюзию разделенных пунктов меню */
	float:none;
	background:url(dot.gif);
}
#nav ul a{
	white-space:nowrap; /* Останавливаем перенос текста и создаем многострочный выпадающий пункт */
	display:block;
}
#nav li:hover ul{ /* Выводим выпадающий пункт при наведении курсора */
	left:0; /* Приносим его обратно на экран, когда нужно */
	opacity:1; /* Делаем непрозрачным */
}

Здесь мы устанавливаем стили по умолчанию для пунктов списка и ссылок. Обратите внимание на свойство padding-top:1px; для элемента <li>. Так как все цвета устанавливаются для элементов <a>, то установка отступа в 1px для элемента <li> сдвигает элемент <a>, и, следовательно, цветную область от границы пункта списка. Таким образом, создается иллюзия, что пункты списка разделены. Интересно, что IE не распознает шаблон <li> при наведении курсора мыши и закрывает выпадающий список. Для решения этой небольшой проблемы добавляется прозрачное изображение gif 1 х 1 px. 

Для элемента #nav ul a мы устанавливаем свойство white-space:nowrap; для предотвращения переноса строк на другую строку.

Последняя часть кода выводит выпадающие подпункты, когда курсор мыши оказывается над соответствующим пунктом меню. Так как псевдо класс :hover не работает в IE6, выпадающее меню не работает в данном браузере. Проблему можно  обойти множеством способов.

#nav li:hover a{ /* Устанавливаем стили для верхнего уровня, когда выводится выпадающий список */
	background:#6b0c36;
	background:rgba(107,12,54,0.75); /* Выглядит полупрозрачным */
	text-decoration:underline;
}

#nav li:hover a определяет, что произойдет со ссылкой верхнего уровня, когда наследник будет иметь состояние hover:

  • Выпадающий список <ul> расположен внутри элемента <li>.
  • Если навести курсор мыши на ссылку (<a>) в выпадающем списке (<ul>), то одновременно пункт списка верхнего уровня (<li>) тоже будет иметь состояние hover, так как выделен контент внутри него.
  • Так как технически используется состояние hover для элемента списка верхнего уровня, то #nav li:hover a действует, задавая стиля для ссылки.
#nav li:hover ul a{ /* Изменяем некоторые стили верхнего уровня при выводе выпадающего пункта */
	text-decoration:none;
	-webkit-transition:-webkit-transform 0.075s linear;
}

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

Также добавляется правило для браузеров Webkit  -webkit-transition:-webkit-transform 0.075s linear;, которое анимирует -webkit-transform с помощью затухания/появления в течение 0.075 секунды.

#nav li:hover ul li a:hover{ /* Устанавливаем стили для выпадающих пунктов, когда курсор наводится на конкретный пункт */
	background:#333;
	background:rgba(51,51,51,0.75); /* Будет полупрозрачным */
	text-decoration:underline;
	-moz-transform:scale(1.05);
	-webkit-transform:scale(1.05);
}

В последней части определяются стили для выделения определенного пункта в выпадающем списке при наведении курсора мыши.

Вначале мы определяем два свойства background:;. Определение background:rgba(51,51,51,0.75); устанавливает умеренно серый фон для пункта с прозрачностью  0.75. Те браузеры, которые не распознают такое определение цвета (например, IE) будут использовать определение цвета в старом стиле в предыдущей строке.

 

Готово!

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

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: csswizardry.com/2011/02/creating-a-pure-css-dropdown-menu/
Перевел: Сергей Фастунов
Урок создан: 23 Февраля 2011
Просмотров: 459988
Правила перепечатки


5 последних уроков рубрики "CSS"

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 23 Февраля 2011 22:12
    Vasek
    Спасибо!
  • 23 Февраля 2011 22:27
    Владислав Егоров
    Thank you!
  • 23 Февраля 2011 22:52
    BenLaden
    Кстати, интересное решение для ширины среднего блока.
  • 23 Февраля 2011 23:45
    MopuC
    Куча подобного здесь уже есть - опять повторы :)
    left:-9999px; /* Скрываем за экраном, когда не нужно (данный метод лучше, чем display:none;) */
    
    Можно пояснение, чем этот метод лучше? Лучше, если нужно гарантировано отрисовать элемент раньше, чем он будет отображён, а тут ни одной картинки => рендерится он почти мгновенно. Так что метод не лучше, а равносилен :)
  • 24 Февраля 2011 02:23
    Good
    Не видно ни фига ... прозрачность тут не к чему... самый хороший пример - ваш между прочим http://autokolpaki.ru/demo/123.html но это только демо сайт будет другим =) меню jquery + css3
  • 24 Февраля 2011 05:53
    altaistudent
    У меня только в Хроме работает, в Сафари не тестил, но в остальных... Есть у кого ссылки на уроки с подобным меню, но более универсальным?
  • 24 Февраля 2011 09:04
    notbot
    Круто!
  • 24 Февраля 2011 09:51
    Дмитрий Арефьев
    В ie не работает
  • 24 Февраля 2011 10:25
    Zedamin
    Во всех последних версия браузеров работает (Chrome, Safari, Mozilla, IE, Opera), CSS это хорошо.
  • 24 Февраля 2011 10:35
    Bandyy
    С ПРАЗДНИКОМ МУЖИКИ!!! Урок актуален.
  • 24 Февраля 2011 12:31
    Chehoff
    В названии темы.. "Созадем..."
  • 24 Февраля 2011 13:48
    kindofbear
    в ие6 не работает :hover с любыми элементами, кроме a. может, и в ие7. "Так как псевдо класс :hover не работает в IE6, выпадающее меню не работает в данном браузере. Проблему можно обойти множеством способов." это что? где эти способы? урок не понравился как то. css - хорошо, но уж делаете уроки, желательно чтобы кроссбраузерные были.я ие6 ненавижу, но в нем это меню будет не то чтобы криво работать, оно там вообще работать не будет. а это уже серьезно насчет вырождения ие: http://www.w3counter.com/globalstats.php
    • 24 Февраля 2011 14:14
      HitMax
      Достали вы с ИЕ6!!! Может быть хватит уже извращаться, что бы обеспечить его поддержку?! Иначе он так никогда и не уйдет в небытие! Internet Explorer 6 — 3.91% Вы стремитесь угодить менее чем 4 процентам юзеров... [лицопальма] По предоставленной вами ссылке так же есть статистика по разрешениям экранов. 800*600 почти 2%... Так может быть стоит и под это разрешение подстраиваться?
      • 24 Февраля 2011 15:02
        kindofbear
        сайт, рассчитанный на 1024 или 1280 можно сделать так, что и на 800 он будет выглядеть неплохо. одно дело например закругленные уголки или градиенты - я плюю тогда на ие6. те у кого стоит он пусть наслаждаются квадратами и сплошной заливкой цветом. это не влияет на функционал. а здесь - пользователь с ие6 (может, и ие7, я не помню, работает ли там ховер не на а) просто не сможет зайти на страницы сайта. нарушение функционала налицо неужели невозможно было в уроке описать те самые способы решения проблемы, а не отписку из двух предложений?
        • 24 Февраля 2011 15:28
          HitMax
          В ИЕ7 работает. Да и что мешает сделать так, что бы ссылки в основных пунктах меню вели на страницы где будут перечислены все подпункты? И там же можно сделать их описание? Например каталог продуктов для одноименного пункта.
          • 24 Февраля 2011 18:15
            kindofbear
            вот и надо было написать про "сделать так". Смысл был в том, что уроки надо писать более полно
            • 24 Февраля 2011 18:35
              HitMax
              Нет, уроки все же должны давать стимул, идею, ведь все же нужно самостоятельно мыслить, а не тупо копировать чужие наработки.
              • 24 Февраля 2011 19:02
                kindofbear
                я тебе про руку, а ты мне про ногу...
          • 6 Ноября 2013 14:39
            Сергей1
            Вопрос Евгению: "выпадающее меню не работает в IE6. Проблему можно обойти множеством способов." Напишите хотя бы один из них. Кроме, разумеется, отсылки к Карте сайта. Меню не работает и в других версиях IE.
  • 24 Февраля 2011 16:03
    rubyx
    Firefox и Chrome дружат по полной:) а "ие" осёл после первой на вторую всплывающую исчезает - билгей-цу работать усердно надо над Internet Explorer :)) я за расширение css всеми членами.
    • 25 Февраля 2011 15:14
      xakepmega
      IE вcегда будет тормозить развитие веба п.с. били не занимается разработкой осла
      • 27 Февраля 2011 15:41
        rubyx
        но этот осел поставляется вместе с виндом на диске, должно его это волновать всётки. есть "тупые" пользователи "дедульки-бабульки" которые привыкли к ослу...)) одному "ослу" установил виндовс и для прикола пометил вместо Internet Explorer на осел, так хозяин обиделся почитав что я его самого назвал ослом :)) пришлось доказывать ему как ослу))...
        • 27 Февраля 2011 17:16
          xakepmega
          кошмар... я вот благо сейчас сайт немцу делаю, а в германии лидирует ff
          • 28 Февраля 2011 14:34
            rubyx
            Firefox он и был лидером не только в германии:) Строй под него сайт немцу. Щас Ff потихоньку выжимает Chrome по своей "скорости" загрузки сайтов... бери с "фрица" за дешевый сайт минимум 200евро. Удачи в деле тебе!
            • 1 Марта 2011 15:03
              xakepmega
              300, он сам предложил, ну а выходит вроде качествено, этому сайту явно не хватает форума
              • 2 Марта 2011 14:49
                rubyx
                Если для немца форум нужен, то и 300 мало будет:) на моём счету самый дорогой был в 2000еу... (зная психику и вкус клиента всегда всё хорошо получается)
  • 12 Марта 2011 16:57
    gadenysh
    А как это меню вертикальным сделать?
  • 13 Марта 2011 18:49
    gadenysh
    Ой не вертикальным, а горизонтальным)
    • 30 Апреля 2011 11:07
      will_smeet
      #nav{
      05 float:left; - меню горизонтальное
      06 width:100%;
      07 list-style:none;
      08 font-weight:bold;
      09 margin-bottom:10px;
      10
      }
      11
      #nav li{
      12 float:left; - меню горизонтальное
      13 margin-right:10px;
      14 position:relative;
      15 display:block;
      
  • 2 Апреля 2011 12:37
    CronuS
    Хороший пример! Спасибо! Конечно, многое еще под себя подработал, но как основа, урок просто отличный! =)
  • 19 Мая 2012 02:22
    bulgakov_marik
    А зачем тут сброс??? в css файле?
  • 28 Февраля 2013 23:43
    Detsle
    Не выпадает меню, за полосу видимо выпадает не видно ни одного пункта, куда смотреть?
  • 13 Марта 2013 19:56
    kuduhin
    Кто-нибудь пробовал сделать это меню с несколькими уровнями вложенности? Я уже сутки бьюсь над этим и пока ничего...
  • 21 Марта 2013 20:43
    jewerly
    Может кто то помочь? Как сделать чтобы основное меню было совершенно в другом стиле. Обычный шрифт (но свой стиль). Не пойму как встроить в <li> чтобы не нарушить остальных подпунктов.Пример могу предоставить, если нужно.
  • 21 Марта 2013 21:11
    jewerly
    Может кто то помочь? Как сделать чтобы основное меню было совершенно в другом стиле. Обычный шрифт (но свой стиль). Не пойму как встроить в <li> чтобы не нарушить остальных подпунктов.Пример. От первого нужно меню. От второго подменю. http://fanfive.narod.ru/index16.html http://fanfive.narod.ru/index15.html
    • 7 Декабря 2013 13:59
      CHER84
      <li class="my_class">"какой-то текст"</li>
      в файле css:
      .my_class{ background: #fff; // для примера меняем фон, если противоречит другим стилям - выставляем приоритет, ниже то же самое, но с приоритетом background: #fff !important; // тот же самый фон, но с приоритетом, выбирайте либо-либо, два раза писать цвет фона в одном стиле - безумие
      }
  • 11 Мая 2013 16:57
    Абыр Валг
    Благодарю! :)
  • 15 Мая 2013 14:38
    reptil
    Архив недоступен нечего качать
  • 13 Июня 2013 07:12
    puniker
    а как сделать это меню с выравниванием по центру в таблице
  • 17 Июня 2013 12:57
    Павел_Т
    Здравствуйте.Скажите можно ли всплывающее меню центровать относительно самого меню?
  • 18 Августа 2013 23:33
    igorlach
    Большое спасибо!
  • 11 Октября 2013 19:56
    sensor_s
    а как это меню можно адаптировать для Joomla? очень хорошее меню - с описанием но вот чтоб всё через cms? может кто посоветует такое же грамотное если это нельзя не хочу модули >__<
  • 11 Октября 2013 22:46
    sensor_s
    у меня joomla 3.1 здесь дивы там классы и канешь приходится не просто встраивать - а брать переменные из джумлы тоесть при переносе шаблона - прийдётся всё поправлять или есть другие решения? суфиксы я так и не понял - как с ними жить? )
  • 12 Октября 2013 00:54
    sensor_s
    всё нашёл - спасибо в джумле можно добавить индификатор к меню парился )
  • 7 Декабря 2013 13:54
    CHER84
    #nav ul{	list-style:none;	position:absolute;	z-index: 100;	left:-9999px; /* Скрываем за экраном, когда не нужно (данный метод лучше, чем display:none;) */	opacity:0; /* Устнавливаем начальное состояние прозрачности */	-webkit-transition:0.25s linear opacity; /* В Webkit выпадающие пункты будут проявляться */
    }
    В таблице стилей желательно добавить z-index: "какая-то цифра"; В моем случае выпадающее меню выпадало на слой с z-index: 1; - в итоге как только курсор попадал на этот слой - выпадающее меню пропадало.
  • 7 Декабря 2013 14:25
    CHER84
    хотел отредактировать - не дает, хотел добавить другое сообщение, дополненное - тоже не дает... Почему сообщение можно редактировать только 20 минут? я пока наткнулся на другую проблему, решил ее с помощью того же стиля, что и в предыдущем сообщении, прошло более 20 минут. Продублировать предыдущее сообщение мне не дают, отредактировать тоже... Если честно, мне проще никому ничего не говорить об обнаруженных недоработках, но раз уж я решил потратить время и показать как можно решить некоторые проблемы - зачем создавать мне трудности?
  • 28 Апреля 2015 18:47
    wandering.shadow
    Спасибо огромное, единственный способ, работающий так, как мне нужно. Единственный минус - IE, но его довольно просто решить.
  • 14 Августа 2015 08:26
    MikeSeleznev
    Здравствуйте. У меня не получается работа php в списке <ul>
     <li><a href='profile.php?id=$id_user'>Мой профиль</a></li>
    Оно не выбирает из базы данных нужный профиль. БД подключена.
  • 4 Декабря 2015 21:22
    sanyok953
    Отлично! то что надо.
  • 9 Июня 2016 13:55
    raksefon
    При создании основного списка в 2 строчки, то при наведении на элемент списка в первой строчке всплывающее меню оказывается под элементом второй строчки. Как это можно исправить?
  • 8 Августа 2016 13:23
    skyline1
    Подскажите, пожалуйста, как изменить вишневый цвет в выпадающем меню? на любой свой
  • 6 Сентября 2016 13:14
    УченикCss
    Огромное спасибо!! Вы очень помогли.
^ Наверх ^