Estrutura de árvore com CSS e HTML

Às vezes é conveniente representar dados em uma estrutura de árbore como a produzida pelo programa tree. O programa tree cria uma saída de árvore de diretórios como esta:


✔ /var/www/html/Repos/Freak-Spot/freak-theme [master|✔] $ tree
.
├── static
│   ├── css
│   │   └── style.css
│   ├── genericons
│   │   ├── COPYING.txt
│   │   ├── genericons.css
│   │   ├── Genericons.eot
│   │   ├── Genericons.svg
│   │   ├── Genericons.ttf
│   │   ├── Genericons.woff
│   │   ├── LICENSE.txt
│   │   └── README.md
│   ├── images
│   │   ├── creativecommons_public-domain_80x15.png
│   │   ├── gnu-head-mini.png
│   │   └── questioncopyright-favicon.png
│   └── js
│       ├── functions.js
│       └── jquery-3.1.1.js
└── templates
    ├── archives.html
    ├── article.html
    ├── article_info.html
    ├── author.html
    ├── authors.html
    ├── base.html
    ├── category.html
    ├── index.html
    ├── page.html
    ├── pagination.html
    ├── period_archives.html
    ├── tag.html
    ├── taglist.html
    └── tags.html

6 directories, 28 files

Para representar a instrução tal como aparece num terminal utilizei as etiquetas HTML <samp> e <pre> (<pre><samp>saído do tree</samp></pre>). Mas e se eu quiser incluir uma ligação ou utilizar outros elementos HTML, ou CSS? Então teremos de usar CSS para mostrar o aspecto de ramos.

Vamos usar a saída anterior como exemplo. Isso pode ser expresso assim em HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Lista de árvore</title>
  </head>
  <body>
    <div class="contenedor-arvore">
      <ul>
        <li>static
          <ul>
            <li>css
              <ul>
                <li>style.css</li>
              </ul>
            </li>
             <li>genericons
               <ul>
                 <li>COPYING.txt</li>
                 <li>genericons.css</li>
                 <li>Genericons.eot</li>
                 <li>Genericons.svg</li>
                 <li>Genericons.ttf</li>
                 <li>Genericons.woff</li>
                 <li>LICENSE.txt</li>
                 <li>README.md</li>
               </ul>
             </li>
            <li>images
              <ul>
                <li>creativecommons_public-domain_80x15.png</li>
                <li>gnu-head-mini.png</li>
                <li>questioncopyright-favicon.png</li>
              </ul>
            </li>
            <li>js
              <ul>
                <li>functions.js</li>
                <li>jquery-3.1.1.js</li>
              </ul>
              </li>
          </ul>
        </li>
        <li>templates
          <ul>
            <li>archives.html</li>
            <li>article.html</li>
            <li>article_info.html</li>
            <li>author.html</li>
            <li>authors.html</li>
            <li>base.html</li>
            <li>category.html</li>
            <li>index.html</li>
            <li>page.html</li>
            <li>pagination.html</li>
            <li>period_archives.html</li>
            <li>tag.html</li>
            <li>taglist.html</li>
            <li>tags.html</li>
          </ul>
        </li>
      </ul>
    </div>
  </body>
</html>

Primeiro, devemos definir as regras para a lista e o seu recipiente para não interferir com o desenho que mais tarde usaremos depois usando a regra border do CSS.

.contenedor-arvore, .contenedor-arvore ul, .contenedor-arvore li {
    position: relative;
}

.contenedor-arvore ul {
    list-style: none;
}

Agora vamos mudar a posição dos pseudoelementos para ter mais espaço para as árvores.

.contenedor-arvore li::before, .contenedor-arvore li::after {
    content: "";
    position: absolute;
    left: -12px;
}

Depois, usando pseudoelementos, desenhamos linhas horizontais (::before) e verticais (::after).

.contenedor-arvore li::before {
    border-top: 1px solid green;
    top: 9px;
    width: 8px;
    height: 0;
}

.contenedor-arvore li::after {
    border-left: 1px solid brown;
    height: 100%;
    width: 0px;
    top: 2px;
}

O último retoque é fazer o ramo não se espalhar mais no último elemento.

.clt ul > li:last-child::after {
    height: 8px;
}

Segue-se o resultado:

Abaixo deixo o código completo. Obviamente, podes fazer modificações e alterar muitas medidas para alcançar uma aparência e funcionalidade mais personalizadas.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Lista de árvore</title>
    <style>
      .contenedor-arvore .contenedor-arvore ul, .contenedor-arvore li {
          position: relative;
      }

      .contenedor-arvore ul {
          list-style: none;
      }

      .contenedor-arvore li::before, .contenedor-arvore li::after {
          content: "";
          position: absolute;
          left: -12px;
      }

      .contenedor-arvore li::before {
          border-top: 2px solid green;
          top: 9px;
          width: 8px;
          height: 0;
      }

      .contenedor-arvore li::after {
          border-left: 2px solid brown;
          height: 100%;
          width: 0px;
          top: 2px;
      }

      .contenedor-arvore ul > li:last-child::after {
          height: 8px;
      }
    </style>
  </head>
  <body>
    <div class="contenedor-arvore">
      <ul>
        <li>static
          <ul>
            <li>css
              <ul>
                <li>style.css</li>
              </ul>
            </li>
             <li>genericons
               <ul>
                 <li>COPYING.txt</li>
                 <li>genericons.css</li>
                 <li>Genericons.eot</li>
                 <li>Genericons.svg</li>
                 <li>Genericons.ttf</li>
                 <li>Genericons.woff</li>
                 <li>LICENSE.txt</li>
                 <li>README.md</li>
               </ul>
             </li>
            <li>images
              <ul>
                <li>creativecommons_public-domain_80x15.png</li>
                <li>gnu-head-mini.png</li>
                <li>questioncopyright-favicon.png</li>
              </ul>
            </li>
            <li>js
              <ul>
                <li>functions.js</li>
                <li>jquery-3.1.1.js</li>
              </ul>
              </li>
          </ul>
        </li>
        <li>templates
          <ul>
            <li>archives.html</li>
            <li>article.html</li>
            <li>article_info.html</li>
            <li>author.html</li>
            <li>authors.html</li>
            <li>base.html</li>
            <li>category.html</li>
            <li>index.html</li>
            <li>page.html</li>
            <li>pagination.html</li>
            <li>period_archives.html</li>
            <li>tag.html</li>
            <li>taglist.html</li>
            <li>tags.html</li>
          </ul>
        </li>
      </ul>
    </div>
  </body>
</html>

Comentários