Complex Lists

I recently had to take a pretty complex nested list and style it in a way that easy to understand with semantic markup.

Note:In this post I will only be showing the styling and markup, not the implementation of showing/hiding the branches.

The structure of the list sounds fairy simple, a list who’s children can be grouped into distinct categories. It sounds alright until you realise that these children can have children of themselves and that these can have children and so on and on and on…..

The logic is pretty straightforward, use an unordered list (ul), or an ordered list if you prefer (ol). For each list item (li) that needs children, we put in another list- first of the number of categories, and secondlyfor the children proper in each category.

A simplification for one branch of this would be

<ul>
  <li>Item
    <ul>
      <li> Category
        <ul>
          <li>Item

Repeat this properly with closing tags, anchors for link and what we end up with is something like this in markup…
(I have chosen to write the category names as h4s and the items as h3)

<ul>
  <li>
    <h4><a href="#">Level 1.A</a></h4>
    <ul>

      <li>
        <h3>Category 1</h3>
        <ul>
          <li>
            <h4><a href="#">Level 2.A</a></h4>
          </li>
          <li>
            <h4><a href="#">Level 2.B</a></h4>

          </li>
          <li>
            <h4><a href="#">Level 2.C</a></h4>
            <ul>
              <li>
                <h3>Category 1</h3>
                <ul>
                  <li>

                    <h4><a href="#">Level 3.A</a></h4>
                    <ul>
                      <li>
                        <h3>Category 1</h3>
                        <ul>
                          <li>
                            <h4><a href="#">Level 4.A</a></h4>

                          </li>
                          <li>
                            <h4><a href="#">Level 4.B</a></h4>
                          </li>
                        </ul>
                      </li>
                    </ul>
                  </li>

                  <li>
                    <h4><a href="#">Level 3.B</a></h4>
                  </li>
                </ul>
              </li>
              <li>
                <h3>Category 2</h3>
                <ul>

                  <li>
                    <h4><a href="#">Level 3.C</a></h4>
                  </li>
                  <li>
                    <h4><a href="#">Level 3.D</a></h4>
                  </li>
                </ul>
              </li>

            </ul>
          </li>
        </ul>
      </li>
      <li>
        <h3>Category 2</h3>
        <ul>
          <li>

            <h4><a href="#">Level 2.D</a></h4>
          </li>
          <li>
            <h4><a href="#">Level 2.E</a></h4>
          </li>
          <li>
            <h4><a href="#">Level 2.F</a></h4>

          </li>
          <li>
            <h4><a href="#">Level 2.G</a></h4>
          </li>
        </ul>
      </li>
    </ul>
  </li>

  <li>
    <h4><a href="#">Level 1.B</a></h4>
  </li>
  <li>
    <h4><a href="#">Level 1.C</a></h4>
  </li>
  <li>
    <h4><a href="#">Level 1.D</a></h4>

  </li>
</ul>

A bit of a nightmare eh? And this is only a few levels deep, and only 1 branch populated! The html view isn’t much better either.

Although I could go ahead and style this up as a standard top down tree, I knew that it wouldn’t really be much better to understand. Taking some cues from the ‘Column View’ of OS X’s Finder, I decided it might be worth trying to grow this thing sideways. I would sacrifice the ability to view more than one branch at a time though, but looking at the example above, this might not be a bad thing!

After a general reset, the first thing to do is to set the width of a level, I’ve chosen 200px in this case

ul{
  width:200px
}

To position each nested list to the right of it’s parent, we tell each nested list to position itself to the right of it’s parent.

ul ul{
  position: absolute;
  left: 100%
  top: 0
}

The selector (ul ul) selects every unordered list inside an unordered list. Absolute positioning allows us to do a few things. The first is that we can move the whole list relative to it’s parent, so in our case, left:100% positions the list 100% of its parents width away from the left edge of its parent (right:-100% would also do the same thing). The top: 0places the list to the top of its parent. And because position: absolute take the element out of document flow, and preceeding elements jump back up to where they should be. For this all work though we need to tell the very first list to have position: relative, otherwise, the first nested list willl take its position from the document window.

ul{
  position: relative
}

If we take a look at the progress so far, we can see that there is a problem. Each list belonging to a category is positioned to the right of the category name and overlapping with its cousins. This is due to our ul ul rule being applied where we don’t want it. To rectify this we need to remove absolute positioning for all lists that immediately follow a category name (an h3 in our case). We do this using the adjacent sibling selector (+) and return the element to position static.

h3+ul{
  position:static
}

If we place this style block after the ul ul block, then it should override the position:absolute. This selector is not supported by IE6 and below, but you could probably achieve the same thing with some creative class name usage. So as if by magic, we have our lists appearing pretty much as we want them.

With a minor bit of styling, and adding an “active” class to the ‘active’ anchors, we have a reasonable looking complex nested list that is certainly easier to understand that the tree we started with.

No Comments

RSS feed for comments on this post. TrackBack URL

No comments yet.

Leave a comment

Preview: