Выпадающее меню на CSS без javascript

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

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

Вертикальное выпадающее меню на CSS без применения Javascript.

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

<div class="cssmenu">
<ul>
   <li><a href="#">Уровень 1 п 1</a></li>
   <li><a href="#">Уровень 1 п 2</a>
      <ul>
         <li><a href="#">Уровень 2 п 1</a></li>
         <li><a href="#">Уровень 2 п 2</a>
           <ul>
              <li><a href="#">Уровень 3 п 1</a></li>
              <li><a href="#">Уровень 3 п 2</a>
                 <ul>
                    <li><a href="#">Уровень 4 п 1</a></li>
                    <li><a href="#">Уровень 4 п 2</a>
                       <ul>
                          <li><a href="#">Уровень 5 п 1</a></li>
                          <li><a href="#">Уровень 5 п 2</a></li>
                          <li><a href="#">Уровень 5 п 3</a></li>
                       </ul>
                    </li>
                    <li><a href="#">Уровень 4 п 3</a></li>
                 </ul>
              </li>
              <li><a href="#">Уровень 3 п 3</a></li>
           </ul>
         </li>
         <li><a href="#">Уровень 2 п 3</a></li>
      </ul>
   </li>
   <li><a href="#">Уровень 1 п 3</a></li>
</ul>
</div>

Чтобы было проще работать со списками, я поместил наше меню в контейнер DIV.

Теперь нам нужно обнулить стили для списков, навести красоту, чтобы пункты были похожи на кнопки и скрыть вложенные пункты меню. Для этого напишем стиль:

<style type="text/css">
.cssmenu ul {
/* убираем отступы */
   padding: 0;
   margin: 0;
/* убираем точки */
   list-style: none;
/* задаем ширину */
   width: 150px;
/* присвоим относительное позиционирование*/
   position:relative;
}
/* зададим стиль для элементов списка */
/* Чтобы меню корректно отображалось в IE */
.cssmenu li {
   float: left;
}
/* зададим стиль для анкора в списке */
.cssmenu li a, .cssmenu li a:visited {
/* обязательно блочное отображение */
   display: block;
/* ширина строки на 1 пиксель меньше */
   width: 149px;
/* зададим высоту строки */
   height:25px;
   line-height:25px;
/* сделаем отступ в 5 пикселей */
   text-indent:5px;
/* сделаем рамку в 1 пиксель */
   border: 1px solid #ffffff;
/* уберем одну горизонтальную рамку, чтобы не удваивались */
   border-width:0 1px 1px 1px;
/* цвета фона и текста */
   color: #FAFAD2;
   background-color: #4682B4;
}
/* меняем цвета при наведении */
.cssmenu li a:hover {
   color: #4682B4;
   background-color: #FAFAD2;
}
/* скрываем вложенные пункты меню */
.cssmenu li ul {
   visibility: hidden;
   position: absolute;
   left: 149px;
   top: 0px;
}
</style>

Если Вы читали мою статью о том как сделать простое CSS меню, Вы наверняка заметили некоторые отличия. Во-первых рамку я сделал с помощью свойства border, для чего оно и предназначено; Во-вторых, чтобы сделать отступ, я не стал пользоваться свойством padding, а указал высоту строки и отступ справа сделал с помощью свойства text-indent. Почему именно так? Да только для того, чтобы ширина пункта меню была одинаковой во всех браузерах.

Давайте взглянем, что у нас получилось:

 

Теперь наша задача заключается в том, чтобы при наведении мышки на пункт меню, выпадал дочерний список. Для Firefox, Opera, Safari b IE7 эта задача решается предельно просто. Добавляем в стиль следущее:

/* отображаем вложенное меню при наведении мыши */
.cssmenu li:hover {
   position: relative;
}
.cssmenu li:hover > ul {
   visibility: visible;
}
/* выделяем родительские пункты, при наведении на дочерние */
.cssmenu li:hover > a {
   color:#4682B4;
   background:#FAFAD2;
}

Поясню, что сделано. Я воспользовался псевдо-классом hover для элемента LI и указал для него относительное позиционирование, а для дочернего списка visibility:visible, что собственно и отображает выпадающее меню. Надо заметить, что если написать .cssmenu li:hover ul (без знака >), то будут отображены все вложенные уровни меню, что нам совершенно не нужно. Также я выделил все родительские ссылки, чтобы было видно весь путь до текущего пункта меню.

Вот что получилось в итоге (должно работать в браузерах Firefox, Opera, Safari и IE7):

 

Internet Explorer младше 7-ой версии не понимает псевдокласс hover для элемента LI, поэтому меню и не работает. Заставить меню работать в этих браузерах можно с помощью javascript, но я обещал, что javascript не будет использоваться вообще. Поэтому придется прописать отображение и скрытие вложенных пунктов вручную:

/* Для IE младше 7-ой версии вручную обработаем каждый уровень */
/* скрываем третий и последующие уровни, когда курсор наведен на первый уровень */
.cssmenu ul a:hover ul ul {
   visibility:hidden;
}
/* скрываем четвертый и последующие уровни, когда курсор наведен на второй уровень */
.cssmenu ul a:hover ul a:hover ul ul {
   visibility:hidden;
}
/* скрываем пятый уровень, когда курсор наведен на третий уровень */
.cssmenu ul a:hover ul a:hover ul a:hover ul ul{
   visibility:hidden;
}
/* показываем второй уровень, при наведении на первый */
.cssmenu ul a:hover ul {
   visibility:visible;
}
/* показываем третий уровень, при наведении на второй */
.cssmenu ul a:hover ul a:hover ul{
   visibility:visible;
}
/* показываем четвертый уровень, при наведении на третий */
.cssmenu ul a:hover ul a:hover ul a:hover ul {
   visibility:visible;
}
/* показываем пятый уровень, при наведении на четвертый */
.cssmenu ul a:hover ul a:hover ul a:hover ul a:hover ul {
   visibility:visible;
}

Но ведь вложенные пункты меню у нас находятся не внутри тега <a>, а после него, а значит дочерние пункты меню отображены не будут. Значит нам нужно поместить дочерние списки внутрь тега <a>. Чтобы решить эту задачу с отображением выпадающего меню в браузерах Internet Explorer младше 7-ой версии, нам придется прибегнуть к условным коментариям и таблицам. Там где должно быть дочернее меню, вместо закрывающего тега </a> мы напишем вот что:

<!--[if IE 7]><!--></a><!--<![endif]--><!--[if lte IE 6]><table><tr><td><![endif]-->

А после дочернего списка добавим следующий код:

<!--[if lte IE 6]></td></tr></table></a><![endif]-->

У нас должен получиться следующий HTML код:

<div class="cssmenu">
<ul>
   <li><a href="#">Уровень 1 п 1</a></li>
   <li><a href="#">Уровень 1 п 2<!--[if IE 7]><!--></a><!--<![endif]--><!--[if lte IE 6]><table><tr><td><![endif]-->
      <ul>
         <li><a href="#">Уровень 2 п 1</a></li>
         <li><a href="#">Уровень 2 п 2<!--[if IE 7]><!--></a><!--<![endif]--><!--[if lte IE 6]><table><tr><td><![endif]-->
            <ul>
               <li><a href="#">Уровень 3 п 1</a></li>
               <li><a href="#">Уровень 3 п 2<!--[if IE 7]><!--></a><!--<![endif]--><!--[if lte IE 6]><table><tr><td><![endif]-->
                  <ul>
                     <li><a href="#">Уровень 4 п 1</a></li>
                     <li><a href="#">Уровень 4 п 2<!--[if IE 7]><!--></a><!--<![endif]--><!--[if lte IE 6]><table><tr><td><![endif]-->
                        <ul>
                           <li><a href="#">Уровень 5 п 1</a></li>
                           <li><a href="#">Уровень 5 п 2</a></li>
                           <li><a href="#">Уровень 5 п 3</a></li>
                        </ul>
                        <!--[if lte IE 6]></td></tr></table></a><![endif]-->
                     </li>
                     <li><a href="#">Уровень 4 п 3</a></li>
                  </ul>
                  <!--[if lte IE 6]></td></tr></table></a><![endif]-->
               </li>
               <li><a href="#">Уровень 3 п 3</a></li>
            </ul>
            <!--[if lte IE 6]></td></tr></table></a><![endif]-->
         </li>
         <li><a href="#">Уровень 2 п 3</a></li>
      </ul>
      <!--[if lte IE 6]></td></tr></table></a><![endif]-->
   </li>
   <li><a href="#">Уровень 1 п 3</a></li>
</ul>
</div>

Остается только добавить стиль для таблицы и для ссылок при наведении:

.cssmenu table {
   position:absolute;
   border-collapse:collapse;
   top:0;
   left:0;
   z-index:100;
   font-size:1em;
}
/* напишем стиль ссылок при наведении для IE младше 7-ого */
* html .cssmenu a:hover {
   color:#4682B4;
   background:#FAFAD2;
/* обязательно нужно указать относительное позиционирование */
   position:relative;
}

К сожалению визуальный редактор моего сайта не позволяет написать код такой конструкции и дописывает в него ненужные теги. Поэтому я выложил страничку с реализованным выпадающем меню отдельно. Смотрим пример вертикального меню на CSS, который работает во всех браузерах без применения javascript: Вертикальное меню на CSS без Javascript.

Это меню работает и абсолютно одинаково отображается в браузерах FF, Opera, IE7, IE6, Safari. Для эксплорера младше 6-ого, возможно придется по-химичить со стилем, чтобы правильно отобразить ширину пункта. Я специально не стал исправлять отображение в IE 5.5, в надежде на то, что им уже мало кто пользуется.