Древовидный список на CSS
Как-то мне потребовалось сделать иерархическое представление структуры проекта, для реализации был выбран CSS.
Вот что получилось:
Это можно сделать за несколько простых шагов.
Для начала создаем желаемую структуру из вложенных списков и заголовков для них:
Узлы уровней создаются с помощью заголовков H1 — H6. То есть перед каждым новым ветвлением должен быть заголовок. Чтобы они все вели себя одинаково c точки зрения древовидного списка, добавляем им общий класс .header
.
Добавляем отступы и рамки, чтобы видеть структуру.
И вот теперь самое интересное: добавляем полоски, начнем с горизонтальных.
Они сделаны абсолютно позиционированными псевдоэлементами. Здесь можно было бы обойтись и inline-block
с вертикальным выравниванием, но position: absolute;
в сочетании с bottom
позволит нам сделать вертикальные линии, направленные вверх.
Чтобы полоски не выпадали из контекста, пунктам списка и заголовкам нужно задать относительное позиционирование, а чтобы они не заезжали на текст — паддинг слева тем же элементам.
Пока выглядит странно. Большинство полосок встало на места, но некоторые болтаются где попало, потому, что все горизонтальные линии спозиционированны относительно нижнего края элементов.
Теперь добавим вертикальные линии:
Получится лес вертикальных линий, от которого легко избавиться, задав всем спискам overflow: hidden;
, вот результат:
И теперь в структуре хорошо видно дублирование некоторых линий.
Оно происходит из-за того, что заголовки (.header
) находятся внутри элементов списка (LI
), таким образом они получают две направляющих.
Добавим спискам с заголовками класс .p-has-headers
и покрасим разные направляющие разными цветами, чтобы увидеть что происходит.
Направляющие обычных пунктов списка остались черными, направляющие списков с заголовками стали красными, направляющие заголовков — зелеными.
По красным хорошо видно, что некоторые из них находятся не там. Например, на крайней слева вертикали горизонтальные линии совсем мимо, потому, что линии спозиционированы от нижнего края LI
.
Это отлично работает в простом списке, но совсем не подходит для списка с заголовком, потому что в этом случае ветка должна начинаться на уровне заголовка, как это делают зеленые.
Именно поэтому стили прописывались и для LI
, и для .header
. Если есть заголовок — ветка вверх должна вести от него, а не от конца списка. Таким образом, в списках, пункты которого содержат заголовки и которые мы пометили классом .p-has-headers
, можно выключить направляющие для непосредственных наследников кодом вроде UL > LI
.
Код:
Результат:
Получилась довольно простая конструкция, главное — не запутаться в тегах списков, и каждую новую ветку начинать с заголовка.
- Метки:
- эксперименты