homepage Welcome to WebmasterWorld Guest from 54.161.155.142
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / CSS
Forum Library, Charter, Moderators: not2easy

CSS Forum

    
Styling a nested list with CSS to look like a tree
ben searching and trying for about 6 months but no joy!
basenotes




msg:3193691
 8:10 pm on Dec 19, 2006 (gmt 0)

Here's what I would like to do.

Turn a nested list, such as:

<ul>
<li>Old-man Widget
<ul>
<li>Amy Widget</li>
<li>Gabby Widget
<ul>
<li>Pete Widget
<ul>
<li>John Widget</li>
<li>Raymond Widget</li>
<li>Nadia de Newname (née Widget)<ul>
<li>Patty de Newname </li> <li>Alex de Newname</li>
</ul></li>
</ul>
</li>
<li>Jack Widget
<ul>
<li>Mark Widget </li>
<li>Jo Widget
<ul>
<li>Paul Widget </li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

into a tree-like format like this:


.Old.Man.Widget................
........¦.......................
..---------------------.............
..¦...................¦..............
.Amy..................Gabby.............
........................¦.............
..............---------------
.............¦..............¦..............
...........Pete............Jack..........
.............¦..............¦..........
....---------------........----------.......
...¦.......¦......¦.......¦.........¦.......
.John....Raymond..Nadia..Mark......Jo.......
...................¦..................¦.....
...............---------..............¦.....
...............¦.......¦..............¦.....
..............Patty...Alex............Paul..

Sorry about the dots but wouldnt format properly otherwise.

Anything that works consistently in most browsers will do. If it isn't technically possible, is it a choice between rendering it with many nested tables or a image.?

thanks all

 

Fotiman




msg:3193771
 9:22 pm on Dec 19, 2006 (gmt 0)

Ooooh. Very interesting challenge.

I've never seen anything like this done (using CSS and/or JavaScript). If you think of it logically, each parent li is essentially a column, with all of it's children contained within that column. Take a small example:

<ul>
<li>Old-man Widget
<ul>
<li>Amy Widget</li>
<li>Gabby Widget
<ul>
</li>
</ul>

That might render like this:

+- Old-man Widget --------------------+
¦,+- Amy Widget -+,+- Gabby Widget -+,¦
¦,¦..............¦,¦................¦,¦
¦,+--------------+,+----------------+,¦
+-------------------------------------+

Now suppose you add more children to Amy Widget:

<ul>
<li>Old-man Widget
<ul>
<li>Amy Widget
<ul>
<li>Joe</li>
<li>Bob</li>
<li>Sue</li>
</ul>
</li>
<li>Gabby Widget
<ul>
</li>
</ul>

That might render like this:

+- Old-man Widget ------------------------------------+
¦,+- Amy Widget -----------------+,+- Gabby Widget -+,¦
¦,¦.+- Joe -+.+- Bob -+ +- Sue -+¦,¦................¦,¦
¦,¦.¦```````¦.¦```````¦.¦```````¦¦,¦................¦,¦
¦,¦.+-------+.+-------+.+-------+¦,¦................¦,¦
¦,+------------------------------+,+----------------+,¦
+-----------------------------------------------------+

Note, I made the Gabby Widget column as tall as the Amy Widget, since we can't have the nested children overlapping.

I'm not sure how you'd go about styling this.

bedlam




msg:3193836
 10:03 pm on Dec 19, 2006 (gmt 0)

You guys are right, this is tricky. I think it could be custom-done for individual cases, but I doubt that any very general solution is possible without javascript.

If you consider the requirements, the child lists will probably need to be absolutely positioned, since the floats would be likely to get out of control very quickly with a list this complex, and also because it will often be convenient to have a child list be wider than it's parent list item. For example, suppose the parent list item is one of three list items arranged horizontally, and suppose further that the list item in question has five children, but neither of its two siblings have any; in this case, it would be convenient if the combined width of the children of the original list item were not limited to the width of their parent, and I don't see how this could be achieved with floats.

But, as fotiman already alluded to, this raises the problem of lists overlapping one another. Some javascript could probably be developed that would prevent items overlapping each other, but it would likely be very tricky to build (e.g. in the script algorithm, how do you decide what to do when there is a collision?), and trickier still to integrate with the CSS (e.g. so your script nudges one list item out of the way of another, what happens to the border/background-image etc that's 'connecting' the two?).

There are two good options that I see here:

  1. Give up on the 'traditional' tree structure and use a series of nested lists that still describes the relationships (you might be able to come reasonably close to a horizontal version of what you're after for example),

  2. Use an image (or imagemap), with proper alt and longdesc attributes. The contents of the page at the longdesc url could be the list described in option 1...

-b

Fotiman




msg:3193882
 10:30 pm on Dec 19, 2006 (gmt 0)

Started messing around briefly. Here's what I came up with so far.

First, a template markup to work with:

<ul class="familyTree">
<li>
Node 1
<ul>
<li>Child 1.1</li>
<li>
Child 1.2
<ul>
<li>GC 1.2.1
<ul>
<li>GGC 1.2.1.1</li>
</ul>
</li>
<li>GC 1.2.2</li>
</ul>
</li>
</ul>
</li>
</ul>

Next, lets remove all padding and margins from list items and unordered lists, and remove the list-style so we're working with an blank slate.


ul.familyTree,
ul.familyTree ul
{
margin: 0;
padding: 0;
list-style: none;
}
ul.familyTree li
{
margin: 0;
padding: 0;
}

Next, each li needs to be floated so they sit next to each other instead of stacking on top of each other. And since that will take the list items out of the flow, we'll also float the ul so that it can "contain" the child nodes.


ul.familyTree,
ul.familyTree ul
{
margin: 0;
padding: 0;
list-style: none;
float: left;
}
ul.familyTree li
{
margin: 0;
padding: 0;
float: left;
}

Next, lets add some borders so we can see what we're working with:


ul.familyTree,
ul.familyTree ul
{
margin: 0;
padding: 0;
list-style: none;
float: left;
border: 2px solid blue;
}
ul.familyTree li
{
margin: 0;
padding: 0;
float: left;
border: 2px solid red;
}

Now if we could just center our text...


ul.familyTree,
ul.familyTree ul
{
margin: 0;
padding: 0;
list-style: none;
float: left;
border: 2px solid blue;
width: 100%;
}
ul.familyTree li
{
margin: 0;
padding: 0;
float: left;
border: 2px solid red;
text-align: center;
}

Unfortunately, that centering doesn't work in Firefox. I'm not sure why yet, and I haven't been able to delve too far into it yet. But perhaps that will give you a jump start.

[edited by: Fotiman at 10:33 pm (utc) on Dec. 19, 2006]

basenotes




msg:3194449
 11:33 am on Dec 20, 2006 (gmt 0)

Thanks for all the suggestions, certainly given me food for thought.

I'm coming to the conclusion that if it can be done, it would need to be in this format:

'''''''''¦--'Amy
'''''''''¦'''''''''''''''''''¦--John
'''''''''¦'''''''''''''''''''¦
old'man--¦''''''''''¦--Pete--¦---Raymond
'''''''''¦''''''''''¦''''''''¦
'''''''''¦''''''''''¦''''''''¦''''''''''''----'Patty
'''''''''¦--'Gabby--¦''''''''¦--Nadia----¦
''''''''''''''''''''¦'''''''''''''''''''''----'Alex
''''''''''''''''''''¦''''''''¦--Mark
''''''''''''''''''''¦''''''''¦
''''''''''''''''''''¦--Jack--¦'
'''''''''''''''''''''''''''''¦--Jo----Paul

Though It's still not too easy. I want to avoid using an image as ideally, I'd like to add a new 'decendent' without having to reproduce the image, imagemap and alt tags.

As I want something that can be produced 'on-the-fly', sadly, I think I'm going to have to give up on doing it with CSS and resort to using something like perl to generate a big bunch of nested tables. (I know, i know....!)

birdbrain




msg:3194512
 1:32 pm on Dec 20, 2006 (gmt 0)

Hi there basenotes,

here is something I did for someone, a little while ago...


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>family tree using 32 divs </title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<style type="text/css">
<!--
h1 {
width:580px;
font-family:verdana,arial,helvetica,sans-serif;
font-size:18px;
text-align:center;
margin:40px auto;
}
#container {
width:580px;
font-family:verdana,arial,helvetica,sans-serif;
font-size:11px;
text-align:center;
margin:auto;
}
#container a {
display:block;
color:#000;
text-decoration:none;
background-color:#f6f6ff;
}
#container a:hover {
color:#900;
background-color:#f6f6ff;
}
#no1 {
width:190px;
line-height:60px;
border:1px solid #000;
margin:auto;
}
#no1 a {
height:60px;
}
#line1 {
font-size:0;
width:1px;
height:20px;
color:#fff;
background-color:#000;
margin:auto;
}
#line2 {
font-size:0;
width:424px;
height:1px;
color:#fff;
background-color:#000;
margin:auto;
}
#line3 {
font-size:0;
display:inline;
width:1px;
height:20px;
color:#fff;
background-color:#000;
margin-left:78px;
float:left;
}
#line4,#line5,#line6 {
font-size:0;
display:inline;
width:1px;
height:20px;
color:#fff;
background-color:#000;
margin-left:140px;
float:left;
}
#no2 {
display:inline;
border:1px solid #000;
clear:both;
margin-left:35px;
float:left;
}
#no2 a,#no4 a,#no8 a {
width:84px;
height:50px;
padding-top:8px;
}
#no3 {
display:inline;
border:1px solid #000;
margin-left:58px;
float:left;
}
#no3 a,#no5 a,#no6 a,#no7 a,#no9 a {
width:84px;
height:42px;
padding-top:16px;
}
#no4 {
display:inline;
border:1px solid #000;
margin-left:53px;
float:left;
}
#no5 {
display:inline;
border:1px solid #000;
margin-left:55px;
float:left;
}
#line7,#line13 {
font-size:0;
display:inline;
width:1px;
height:38px;
color:#fff;
background-color:#000;
margin-left:219px;
float:left;
}
#line8,#line14 {
font-size:0;
display:inline;
width:1px;
height:38px;
color:#fff;
background-color:#000;
margin-left:281px;
float:left;
}
#no6,#no8 {
display:inline;
border:1px solid #000;
margin-left:107px;
float:left;
}
#line9,#line11,#line15,#line17 {
font-size:0;
display:inline;
width:26px;
height:1px;
color:#fff;
background-color:#000;
margin-top:29px;
float:left;
}
#line10,#line12,#line16,#line18 {
font-size:0;
display:inline;
width:1px;
height:60px;
color:#fff;
background-color:#000;
float:left;
}
#line16,#line18 {
height:30px;
}
#no7,#no9 {
display:inline;
border:1px solid #000;
margin-left:169px;
float:left;
}
.clear {
clear:both;
}
-->
</style>

</head>
<body>

<h1>A simple family tree using 32 divs</h1>

<div id="container">

<div id="no1"><a href="">Managing Director</a></div>
<div id="line1"></div>
<div id="line2"></div>
<div id="line3"></div>
<div id="line4"></div>
<div id="line5"></div>
<div id="line6"></div>
<div id="no2"><a href="#">Sales &amp; Marketing Director</a></div>
<div id="no3"><a href="#">Production Director</a></div>
<div id="no4"><a href="#">Human Resources Director</a></div>
<div id="no5"><a href="#">Finance Director</a></div>
<div id="line7"></div>
<div id="line8"></div>
<div class="clear"></div>
<div id="no6"><a href="#">Factory Manager</a></div>
<div id="line9"></div>
<div id="line10"></div>
<div id="no7"><a href="#">Management Accountant</a></div>
<div id="line11"></div>
<div id="line12"></div>
<div class="clear"></div>
<div id="line13"></div>
<div id="line14"></div>
<div class="clear"></div>
<div id="no8"><a href="#">Quality Control Manager</a></div>
<div id="line15"></div>
<div id="line16"></div>
<div id="no9"><a href="#">Financial Accountant</a></div>
<div id="line17"></div>
<div id="line18"></div>
<div class="clear"></div>

</div>

</body>
</html>

birdbrain

Fotiman




msg:3194615
 3:16 pm on Dec 20, 2006 (gmt 0)

Very neat Birdbrain.

One problem with this approach, though, is that someone with a screen reader won't be able to pick up on what the relationships are because it's not marked up in a semantic way. That is, there's nothing to tell the user that Factory Manager is in a heirarchy below production director. With nested lists, the heirarchy is preserved, even if it's not presented in the same way.

Basenotes, the same problem is going to exist if you try to do this with a bunch of nested tables.

With lists, at least the meaning of the content can still be perceived even if there is no additional styling, because the semantic relationship is obvious.

birdbrain




msg:3194716
 4:37 pm on Dec 20, 2006 (gmt 0)

Hi there Fotiman,

I did not originally make this as a semantic exercise. ;)

Would you find it more acceptable like this...


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>family tree using 9 headers and 23 divs </title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<style type="text/css">
#container {
width:580px;
font-family:verdana,arial,helvetica,sans-serif;
font-size:11px;
text-align:center;
margin:50px auto;
}
#container a {
display:block;
color:#000;
text-decoration:none;
background-color:#f6f6ff;
}
#container a:hover {
color:#900;
background-color:#f6f6ff;
}
#no1 {font-size:11px;font-weight:normal;
width:190px;
line-height:60px;
border:1px solid #000;
margin:0 auto;
}
#no1 a {
height:60px;
}
#line1 {
font-size:0;
width:1px;
height:20px;
color:#fff;
background-color:#000;
margin:auto;
}
#line2 {
font-size:0;
width:424px;
height:1px;
color:#fff;
background-color:#000;
margin:auto;
}
#line3 {
font-size:0;
display:inline;
width:1px;
height:20px;
color:#fff;
background-color:#000;
margin-left:78px;
float:left;
}
#line4,#line5,#line6 {
font-size:0;
display:inline;
width:1px;
height:20px;
color:#fff;
background-color:#000;
margin-left:140px;
float:left;
}
#no2 {
font-size:11px;
font-weight:normal;
display:inline;
border:1px solid #000;
clear:both;
margin:0;
margin-left:35px;
float:left;
}
#no2 a,#no4 a,#no8 a {
width:84px;
height:50px;
padding-top:8px;
}
#no3 {
font-size:11px;
font-weight:normal;
display:inline;
border:1px solid #000;
margin:0;
margin-left:58px;
float:left;
}
#no3 a,#no5 a,#no6 a,#no7 a,#no9 a {
width:84px;
height:42px;
padding-top:16px;
}
#no4 {
font-size:11px;
font-weight:normal;
display:inline;
border:1px solid #000;
margin:0;
margin-left:53px;
float:left;
}
#no5 {
font-size:11px;
font-weight:normal;
display:inline;
border:1px solid #000;
margin:0;
margin-left:55px;
float:left;
}
#line7,#line13 {
font-size:0;
display:inline;
width:1px;
height:38px;
color:#fff;
background-color:#000;
margin-left:219px;
float:left;
}
#line8,#line14 {
font-size:0;
display:inline;
width:1px;
height:38px;
color:#fff;
background-color:#000;
margin-left:281px;
float:left;
}
#no6,#no8 {
font-size:11px;
font-weight:normal;
display:inline;
border:1px solid #000;
margin:0;
margin-left:107px;
float:left;
}
#line9,#line11,#line15,#line17 {
font-size:0;
display:inline;
width:26px;
height:1px;
color:#fff;
background-color:#000;
margin-top:29px;
float:left;
}
#line10,#line12,#line16,#line18 {
font-size:0;
display:inline;
width:1px;
height:60px;
color:#fff;
background-color:#000;
float:left;
}
#line16,#line18 {
height:30px;
}
#no7,#no9 {
font-size:11px;
font-weight:normal;
display:inline;
border:1px solid #000;
margin:0;
margin-left:169px;
float:left;
}
.clear {
clear:both;
}
</style>

</head>
<body>

<div id="container">

<h1 id="no1"><a href="">Managing Director. 1</a></h1>
<div id="line1"></div>
<div id="line2"></div>
<div id="line3"></div>
<div id="line4"></div>
<div id="line5"></div>
<div id="line6"></div>
<h2 id="no2"><a href="#">Sales &amp; Marketing Director. 2</a></h2>
<h2 id="no3"><a href="#">Production Director. 2</a></h2>
<h2 id="no4"><a href="#">Human Resources Director. 2</a></h2>
<h2 id="no5"><a href="#">Finance Director. 2</a></h2>
<div id="line7"></div>
<div id="line8"></div>
<div class="clear"></div>
<h3 id="no6"><a href="#">Factory Manager. 3</a></h3>
<div id="line9"></div>
<div id="line10"></div>
<h3 id="no7"><a href="#">Management Accountant. 3</a></h3>
<div id="line11"></div>
<div id="line12"></div>
<div class="clear"></div>
<div id="line13"></div>
<div id="line14"></div>
<div class="clear"></div>
<h3 id="no8"><a href="#">Quality Control Manager. 3</a></h3>
<div id="line15"></div>
<div id="line16"></div>
<h3 id="no9"><a href="#">Financial Accountant. 3</a></h3>
<div id="line17"></div>
<div id="line18"></div>
<div class="clear"></div>

</div>

</body>
</html>

birdbrain

Fotiman




msg:3194736
 4:48 pm on Dec 20, 2006 (gmt 0)


Would you find it more acceptable like this...

From a semantic point of view... no. Are they really headings? I would argue probably not. There is some degree of semantics associated with using the different levels of heading, though the encapsulation still isn't represented. For example, this would look to me as though Factory Manager. 3, Management Accountant. 3, Quality Control Manager. 3, and Financial Accountant. 3 were all contained under Finance Director 2. (view it with no CSS applied to see what I mean).

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / CSS
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved