Многоуровневое дерево html css

Tree views in CSS

A tree view (collapsible list) can be created using only HTML and CSS , without the need for JavaScript. Accessibility software will see the tree view as lists nested inside disclosure widgets, and the standard keyboard interaction is supported automatically.

The HTML

We begin with the HTML for simple nested lists:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
ul>  li>  Giant planets  ul>  li>  Gas giants  ul>  li>Jupiterli>  li>Saturnli>  ul>  li>  li>  Ice giants  ul>  li>Uranusli>  li>Neptuneli>  ul>  li>  ul>  li> ul>

    element, and for each list item that contains a nested list, we put the contents of the list item inside and elements, using the open attribute to control which nested lists are initially expanded:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 
ul class="tree">  li>  details open>  summary>Giant planetssummary>  ul>  li>  details>  summary>Gas giantssummary>  ul>  li>Jupiterli>  li>Saturnli>  ul>  details>  li>  li>  details>  summary>Ice giantssummary>  ul>  li>Uranusli>  li>Neptuneli>  ul>  details>  li>  ul>  details>  li> ul>

Without any styling, this HTML produces:

The browser implements the element as a disclosure widget, giving the ability to expand and collapse the nested lists, but the combination of bullet points and disclosure arrows produces a confusing user interface.

Custom properties

There are two dimensions that affect the layout of the tree view: the spacing between lines (which equals the line height of the text) and the radius of the markers. We begin by creating CSS custom properties for these dimensions:

.tree  --spacing : 1.5rem;  --radius : 10px; >

While we would usually use relative units to scale user interface controls based on the text size, for the markers this can lead to controls that are too small or excessively large, so we instead use a reasonable fixed size.

Padding

We then style the list items and nested lists to make space for the lines and markers:

 6 7 8 9 10 11 12 13 14 15 
.tree li  display : block;  position : relative;  padding-left : calc(2 * var(--spacing) - var(--radius) - 2px); >  .tree ul  margin-left : calc(var(--radius) - var(--spacing));  padding-left : 0; >

Line 7 removes the bullet points from list items. Line 8 establishes a new stacking context and containing block that we will use to position the lines and markers.

Line 9 indents the list items. The indentation is equal to twice the spacing, minus the marker radius, minus the two-pixel line width. The result is that the text in a list item will align with the left side of the marker below it.

Line 13 uses a negative margin to compensate for the indentation introduced by line 9, ensuring nested lists are indented by only the desired spacing. Line 14 removes the default padding that browsers apply to lists.

On a tree view with all nested lists initially expanded, applying this styling produces:

Vertical lines

Next we add the vertical lines that form part of the lines joining the marker of each list item to the markers of its nested lists:

.tree ul li  border-left : 2px solid #ddd; >  .tree ul li:last-child  border-color : transparent; >

We use a border to create the line, and hide it on the final item in each list as the line shouldn’t continue past this item’s marker. Making the border transparent, rather than removing it completely, avoids the need to increase the padding to compensate.

Applying this styling produces:

Horizontal lines

We use generated content to add the horizontal lines that join the vertical lines to the markers of each list item:

25 26 27 28 29 30 31 32 33 34 35 
.tree ul li::before  content : '';  display : block;  position : absolute;  top : calc(var(--spacing) / -2);  left : -2px;  width : calc(var(--spacing) + 2px);  height : calc(var(--spacing) + 1px);  border : solid #ddd;  border-width : 0 0 2px 2px; >

This code also creates short vertical lines, as the vertical lines created previously don’t extend all the way to the markers at their top and bottom ends.

Lines 26 and 27 generate a block, and lines 28 to 30 position it to start at the midpoint of the preceding line of text, overlapping the vertical line to its left.

Lines 31 and 32 set the size of the block. It needs to be two pixels wider than the spacing as it overlaps the vertical line to its left, and one pixel taller than the spacing as half the width of the horizontal line lies below the midpoint of the line of text. Note that we are assuming the use of border box sizing, so these dimensions include the border.

Lines 33 and 34 create a border on the left and bottom sides of the block.

Applying this styling produces:

Summaries

Next we remove the default styling from summaries:

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 
.tree summary  display : block;  cursor : pointer; >  .tree summary::marker, .tree summary::-webkit-details-marker  display : none; >  .tree summary:focus  outline : none; >  .tree summary:focus-visible  outline : 1px dotted #000; >

Lines 38 and 44 remove the disclosure arrows. Line 44 is needed for Safari, with the two selectors on lines 42 and 43 covering different versions of the browser. Line 39 changes the cursor to indicate that the summary can be clicked to interact with it.

Safari shows a focus indicator around summaries, even when using a pointer rather than keyboard navigation, so we remove the focus styling on line 48 and then use the :focus-visible pseudo-class to add it back for visitors using keyboard navigation on line 52.

Applying this styling produces:

Markers

We use generated content again to create the markers:

55 56 57 58 59 60 61 62 63 64 65 66 
.tree li::after, .tree summary::before  content : '';  display : block;  position : absolute;  top : calc(var(--spacing) / 2 - var(--radius));  left : calc(var(--spacing) - var(--radius) - 1px);  width : calc(2 * var(--radius));  height : calc(2 * var(--radius));  border-radius : 50%;  background : #ddd; >

Lines 57 and 58 generate a block, and lines 59 to 61 center it over the corner where the horizontal and vertical lines meet. The top is positioned at the midpoint of the line of text, minus the radius. The left is positioned at the edge of the vertical line, minus the radius, minus the one pixel corresponding to half the line width.

Lines 62 and 63 set the size of the block, and lines 64 and 65 style it as a circle.

Applying this styling produces:

Expand and collapse buttons

Finally, we add the expand and collapse buttons:

.tree summary::before  z-index : 1;  background : #696 url('expand-collapse.svg') 0 0; >  .tree details[open] > summary::before  background-position : calc(-2 * var(--radius)) 0; >

Line 69 causes the button to be displayed on top of the marker created previously. As the marker was created using ::after it would otherwise be displayed on top of the button.

Lines 70 and 74 show plus and minus signs in the buttons. You can download expand-collapse.svg (199 bytes) for use on your own site.

Applying this styling produces the finished tree view:

The finished code

Combining all of the above leads to the finished code:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 
.tree  --spacing : 1.5rem;  --radius : 10px; >  .tree li  display : block;  position : relative;  padding-left : calc(2 * var(--spacing) - var(--radius) - 2px); >  .tree ul  margin-left : calc(var(--radius) - var(--spacing));  padding-left : 0; >  .tree ul li  border-left : 2px solid #ddd; >  .tree ul li:last-child  border-color : transparent; >  .tree ul li::before  content : '';  display : block;  position : absolute;  top : calc(var(--spacing) / -2);  left : -2px;  width : calc(var(--spacing) + 2px);  height : calc(var(--spacing) + 1px);  border : solid #ddd;  border-width : 0 0 2px 2px; >  .tree summary  display : block;  cursor : pointer; >  .tree summary::marker, .tree summary::-webkit-details-marker  display : none; >  .tree summary:focus  outline : none; >  .tree summary:focus-visible  outline : 1px dotted #000; >  .tree li::after, .tree summary::before  content : '';  display : block;  position : absolute;  top : calc(var(--spacing) / 2 - var(--radius));  left : calc(var(--spacing) - var(--radius) - 1px);  width : calc(2 * var(--radius));  height : calc(2 * var(--radius));  border-radius : 50%;  background : #ddd; >  .tree summary::before  z-index : 1;  background : #696 url('expand-collapse.svg') 0 0; >  .tree details[open] > summary::before  background-position : calc(-2 * var(--radius)) 0; >

Источник

Многоуровневое дерево с маркерами (HTML, CSS). Продолжение с jQuery

Посмотреть в работе многоуровневое дерево с маркерами.

В продолжение темы про дерево немного переделал код и подключил jQuery. Теперь дерево живое, узлы разворачиваются, как этого многие ожидают видя подобное дерево.
Теперь оформление дерева делает скрипт — сам расставляет маркеры для элементов с вложенными узлами.
Благодаря использованию скрипта HTML стал проще.

UPD 05.04.2009: обновлены скрипты, есть несколько вариантов скриптов.
UPD 09.04.2009: продолжение

Начальный HTML

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

По сравнению с предыдущим вариантом немного поменялся CSS. Предыдущий вариант полностью тут.

CSS

/* Дерево многоуровневое
——————————— */
#multi-derevo width: 220px; /* блок под дерево */
border: solid; /* границы блока */
border-color: silver gray gray silver;
border-width: 2px;
padding: 0 0 1em 0; /* нижний отступ */
font-size: 1.3em;
>
span < /* обертка пункта */
text-decoration: none;
display: block; /* растянем до правого края блока */
margin: 0 0 0 1.2em;
background-color: transparent;
border: solid silver; /* цвет линий */
border-width: 0 0 1px 1px; /* границы: низ и лево */
>
span a < /* тест элемента дерева */
display: block;
position: relative;
top: .95em; /* смещаем узел на середину линии */
background-color: #fff; /* закраска в цвет фона обязательна иначе будет видно линию */
margin: 0 0 .2em .7em; /* делаем промежуток между узлами, отодвигаем левее */
padding: 0 0.3em; /* небольшой отступ от линии */
>
h4 < /* заголовок дерева */
font-size: 1em;
font-weight: bold;
margin: 0;
padding: 0 .25em;
border-bottom: 1px solid silver;
>
h4 a display: block;
>
ul, li list-style-image:none;
list-style-position:outside;
list-style-type:none;
margin:0;
padding:0;
>
ul li line-height: 1.2em;
>
ul li ul display: none; /* узлы свернуты */
>
ul li ul li margin: 0 0 0 1.2em;
border-left: 1px solid silver; /* цвет вертикальной линии между узлами */
>
li.last < /* последний узел, соединительную линию к след. узлу убираем */
border: none;
>
.marker < /* маркер раскрытия списка в закрытом состоянии */
border-color: transparent transparent transparent gray;
border-style: solid;
border-width: .25em 0 .25em .5em;
margin: .35em .25em 0 0;
float : left;
width: 0px;
height: 0px;
line-height: 0px;
>
.marker.open < /* маркер раскрытия списка в открытом состоянии */
border-color: gray transparent transparent transparent;
border-width: .5em .25em 0 .25em;
>
/* IE 6 Fixup */
* html #multi-derevo * < height: 1%;>
* html .marker < border-style: dotted dotted dotted solid; >
* html .marker.open

JavaScript

Скрипт написан с использованием jQuery. Все пояснения по работе скрипта смотрите в комментариях кода.
Комментариев много — это мой первый скрипт с jQuery, потому писал подробно.

    ,
    выбираем прямых потомков ul > li, назначаем им класс ‘last’ */
    li.find( ‘ul:first > li’ ).addClass( ‘last’ );
    >
    // анимация раскрытия узла и изменение состояния маркера
    var ul=$( ‘ul:first’ , this .parentNode); // Находим поддерево
    if (ul.length) < // поддерево есть
    ul.slideToggle(300); //свернуть или развернуть
    // Меняем сосотояние маркера на закрыто/открыто
    var em=$( ’em:first’ , this .parentNode); // this = ‘li span’
    // было em.hasClass(‘open’)?em.removeClass(‘open’):em.addClass(‘open’);
    em.toggleClass( ‘open’ );
    >
    >);
    >)
    /*]]>*/

Приветсвую всяческие улучшения и оптимизации от знатоков jQuery.
Возможно есть пламенный нелюбитель jQuery, который сделает это на чистом JS — тоже интересно.

Пример

Проверено в FF3, IE6-8, Opera 9, Google Chrome.

P.S. leonard, спасибо за твой пример скрипта в прошлой теме.

Обновления
05.04.2009 Обновлен скрипт (замена hasClass, addClass, removeClass на toggleClass). Обновлен пример. Добавлены сноски на альтернативные скрипты для дерева.
09.04.2009: продолжение

Источник

Читайте также:  Основные цвета html документа
Оцените статью