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

Вертикальное выпадающее меню по клику HTML CSS

Выпадающее меню раскрывающееся по клику не такая уж и редкость. Javascript позволяет делать более сложные вещи, а уж подобные фишки с меню делаются на раз. А что если сделать такое же меню но без применения JS. Зачем нам лишние скрипты если подобное можно сделать через CSS и HTML? Однозначно ответить на этот вопрос не получиться и вот почему. На WebOnLife есть статья как сделать выпадающее меню на CSS и HTML. Там описан способ как сделать меню раскрывающееся при наведении. Чтобы сделать такое меню достаточно добавить стили в  css файл вашего сайта. То о чём пойдёт речь дальше требует изменений HTML. Если вы пользуетесь CMS, а вы скорее всего пользуетесь, то вам нужно как-то изменить код меню который генерирует ваш движок. Если вас это не пугает, или вам просто интересно узнать как сделать то, что сделать нельзя(в css нет возможности обрабатывать клик) предлагаю продолжить чтение.

Как я уже говорил в css нет возможности обработать клик. Решать проблему будем с помощью псевдокласса :checked. В отличии от :hover, который можно повесить почти на всё, :checked срабатывает только для radio и checkbox когда они отмечены. Берём обычное многоуровневое меню и вставляем checkbox и <label>. <label> будет содержать пункт меню у которого есть дочерние элементы. Чтобы клик по такому пункту меню срабатывал как клик по чекбоксу, нужно добавить одинаковые атрибуты id у checkbox и for у <label>. В итоге получим такую разметку.

 <ul class="nav">
    <li>
      <input type="checkbox" id="p1">
      <label for="p1">пункт1</label>
      <ul>
	<li><a href="#">пункт 1.1</a></li>
        <li><a href="#">пункт 1.2</a></li>
      </ul>
    </li>
    <li>
      <input type="checkbox" id="p2">
      <label for="p2">пункт2</label>
      <ul>
        <li><a href="#">пункт 2.1 многа букаф</a></li>
        <li>
          <input type="checkbox" id="p22">
          <label for="p22">пункт2.2</label>
          <ul>
            <li><a href="#">пункт 2.2.1</a></li>
            <li><a href="#">пункт 2.2.2</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="#">пункт 3</a></li>
  </ul>

Скрываем чекбокс и вложенные пункты меню

ul.nav li ul, input {
  display: none;
}

Чтобы по клику на пункте меню открывались вложенные пункты нужно добавить

ul.nav li input:checked + label + ul {
  display: block;
}

Меню работает как надо. Теперь нужно как-то выделить пункты меню которые содержат подпункты. Самый простой способ это нарисовать рядом с ними треугольник. Треугольник будем именно рисовать, а не вставлять картинку. Для этого используем псевдокласс :before но сначала зададим

ul.nav li {
  position: relative;
}

и сделаем отступ для элемента <label>

ul.nav label {
  padding: 0.5em 0.5em 0.5em 1.5em;
}

Нарисовать треугольник перед элементом <label> можно следующим образом. Создаём пустой элемент с помощью псевдо элемента :before и задаём для него border. Для левой границы задаём чёрный цвет. Остальные прозрачные. Размер треугольника определяется шириной границы. Используя абсолютное позиционирование разместим треугольник слева, там где у <label> отступ в 1.5em. Для li мы задали position: relative поэтому треугольник будет позиционироваться относительно родительского элемента списка.

ul.nav label:before {
  content: "";
  border-width: 0.5em;
  border-style: solid;
  border-color: transparent transparent transparent black;
  position: absolute;
  top: 0.5em;
  left: 0.25em;
}

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

ul.nav li input:checked + label:before{
  transform: rotate(90deg);
}

Посмотреть что получилось можно здесь. Окончательно файл стилей будет выглядеть так.

ul {
  padding: 0;
}
ul.nav {
  margin: 0;
  padding: 0;
  width: 150px;
}
ul.nav li {
  background: #B3B3FF;
  border-top: 1px solid #FFFFFF;
  border-bottom: 1px solid #FFFFFF;
  list-style: none;
  position: relative;
}
ul.nav li a {
    text-decoration: none;
    display: block;
    padding: 0.5em 0.5em 0.5em 1.5em;
}
ul.nav label {
  background: #B3B3FF;
  padding: 0.5em 0.5em 0.5em 1.5em;
  display: block;
}

/*скрываем вложенные пункты и чекбокс*/
ul.nav li ul, ul.nav input {
  display: none;
}

/*при клике на чекбокс раскроются вложенные пункты*/
ul.nav li input:checked + label + ul {
  display: block;
}
ul.nav li input:checked + label + ul li {
  background: yellow;
}
ul.nav li input:checked + label {
  background: #d3da56;
}

/*рисуем треугольник рядом с пунктами содержащими подпункты*/
ul.nav label:before {
  content: "";
  border-width: 0.5em;
  border-style: solid;
  border-color: transparent transparent transparent black;
  position: absolute;
  top: 0.5em;
  left: 0.25em;
}
ul.nav li input:checked + label:before{
  transform: rotate(90deg);
}

Этот пример сделан полностью на чекбоксах, поэтому можно открыть все вложенные пункты сразу. Чтобы такого не произошло замените checkbox на radio и не забудьте указать одинаковые атрибуты name для каждого уровня демка.

Добавлено пользователемВикторon пн, 02/22/2016 - 00:01

Очень полезная статейка. Не знаю, позволит ли мой конструктор проделать такое, но HTML-вставки в нем есть и CSS я могу править. Обязательно попробую.