Верстка сайта

Как создать древовидное меню при помощи CSS

Классическое древовидное меню, всем нам хорошо известное, часто используется во всем мире, и оно определенно может быть полезно при правильном использовании

Как создать древовидное меню при помощи CSS
Поделиться в соцсетях:

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

Данный пример создан с использованием упорядоченного списка (ol) с вложенными упорядоченными списками, которые и создают основную структуру папок.

<ol>
	<li class="file">
		<a href="document.pdf">File 1</a>
	</li>
	<li>
		<label for="subfolder1">Subfolder 1</label>
		<input type="checkbox" id="subfolder1" />
		<ol>
			<li class="file">
				<a href="">File 2</a>
			</li>
			<li class="file">
				<a href="">File 2</a>
			</li>
			<li class="file">
				<a href="">File 2</a>
			</li>
		</ol>
	</li>
</ol>

Как вы можете видеть структура представляет собой список, с вложенным label и чекбоксом, по клику на который меню будет раскрываться.

li input {
	position: absolute;
	left: 0;
	margin-left: 0;
	opacity: 0;
	z-index: 2;
	cursor: pointer;
	height: 1em;
	width: 1em;
	top: 0;
}
li label {
	background: url(img) 15px 1px no-repeat;
	cursor: pointer;
	display: block;
	padding-left: 37px;
}

Чтобы установить input и label в правильном визуальном порядке, я задал абсолютное позиционирование для input и задал отступ слева для label

li input + ol {
	background: url(toggle-small-expand.png) 40px 0 no-repeat;
	margin: -0.938em 0 0 -44px; /* 15px */
	display: block;
	height: 1em;
}

Чтобы правильно расположить ol, я использую отрицательный отступ(margin-left: -0.938em 0 0 -44px), чтобы разместить его таким образом, что он будет находиться рядом с label и под невидимым чекбоксом.

li input + ol > li {
	display: none;
	margin-left: -14px !important;
	padding-left: 1px;
}

Чтобы скрыть подпапки, чтобы они не появлялись, когда родительская папка свернута, я использовал display: none, это также не позволяет перемещению с помощью клавиатуры по свернутым пунктам меню.

li label {
	background: url(folder.png) 15px 1px no-repeat;
}
li.file a {
	background: url(document.png) 0 -1px no-repeat;
	color: #fff;
	padding-left: 21px;
	text-decoration: none;
	display: block;
}

Чтобы было различие между папками и файлами, я применил разные фоновые изображения к label и к ссылкам в списке файлов (li.file a).

li {
	position: relative;
	margin-left: -15px;
	list-style: none;
}
li.file {
	margin-left: -1px !important;
}

К элементам со списком папок я применяю большее отрицательное поле, таким образом папки выстраиваются в линию с любым из пунктов-файлов, а для пунктов-файлов я сбрасываю левое поле.

Изменение иконки в зависимости от расширения

С помощью некоторых CSS3 атрибутов селекторов мы можем определить, какое расширение имеет файл, и изменить значок соответственно.

li.file a[href $= '.pdf']  { background-position: -16px -1px; }
li.file a[href $= '.html'] { background-position: -32px -1px; }
li.file a[href $= '.css']  { background-position: -48px -1px; }
li.file a[href $= '.js']   { background-position: -64px -1px; }

Используя $ = CSS селектор атрибута позволяет нам проверить, какое расширение у файла - .pdf, .html и т.д.

li.file a[href *= '.pdf']  { background-position: -16px -1px; }
li.file a[href *= '.html'] { background-position: -32px -1px; }

* = будет соответствовать подстроке, которая содержит .pdf или .html где угодно в пределах атрибута, и если у ссылки есть соответствующая строка, мы можем установить соответствующее изображение расширению файла. У способа есть небольшой недостаток, он будет искать соответствие по всей строке и если, например, Ваш файл называется file.html.pdf, то он будет соответствовать обоим типам файлов, и к пункту в этом случае будет применено правило, которое будет иметь более высокую специфику CSS.

Атрибуты чекбоксов

В демонстрационном примере по умолчанию первая папка открыта, это сделано благодаря добавлению атрибут checked к чекбоксу. Мы также можем добавить disabled атрибут к чекбоксу, чтобы не позволять пользователю открыть папку, поскольку input ни не может быть отмечен. Наконец, использование комбинации checked и disabled позволит нам показывать под папки и файлы, но при этом не позволяет пользователю закрывать папку верхнего уровня.

Кроссбраузерность

Данное меню будет работать в любом браузере, который поддерживает CSS3-селекторы. Оно было успешно протестировано в следующих браузерах:

  • Firefox 1+
  • Opera 9.6+
  • Safari 4+
  • Safari iPhone/iPod
  • Chrome 1+
  • Android
  • IE9+

Новый комментарий

Имя:
Для редактирования комментария осталось 10 минут
Комментарии отсутствуют