jasonkarldavis.com

seize the trees

CSS Trees, part 2

Our last attempt at CSS-based trees was less than successful. They only rendered in one browser, and were functional in none. However, that doesn't mean the task is impossible, and in part 2, we're going to try another approach.

Concept

The concept remains the same as it did in part 1, however we're changing our definition of what makes the tree expand. Instead of a user giving focus to a branch, let's pretend the user targets a branch to expand. This paves the way for using another pseudo-class.

Implementation

Once again, we will use unsorted lists as the markup construction block, as they are the most semantically fit for the job. But to power this effect, we need anchors to target trees, and the :target pseudo-class from CSS3. This means we are going to have to litter our list with id attributes (litter may be a little harsh, as it is perfectly fine to do so, but we're still adding markup nonetheless).

Other than that, there's nothing else to it. Our CSS is going to look strikingly similar to the CSS found in attempt #1 of CSS Trees, but with :target instead of :focus.

Here is the CSS we will use to style and implement the tree:

ul.tree > li {
	color: #000;
	cursor: default;
	font: 0.8em Arial,Helvetica,sans-serif;
}
ul.tree > li > a {
	text-decoration: none;
}
ul.tree > li > a:hover {
	text-decoration: underline;
}
ul.tree > li[id] > a {
	color: #000;
	cursor: default;
}
ul.tree > li[id] > ul.tree {
	display: none;

	margin-left: 1%;
	padding-left: 1%;
}
ul.tree > li:target > ul.tree {
	display: block;
}

The fourth selector distinguishes branches with content from nodes with no content, the fifth hides child nodes, and the last selector makes them reappear again.

Example

(Gecko[1.4+]/KHTML-only):

The markup:

<ul class="tree">
	<li id="section1">
		<a href="#section1">Section 1</a>
		<ul class="tree">
			<li><a href="subsection1.html">Subsection 1</a></li>
			<li><a href="subsection2.html">Subsection 2</a></li>
			<li><a href="subsection3.html">Subsection 3</a></li>
			<li><a href="subsection4.html">Subsection 4</a></li>
		</ul>
	</li>
	<li><a href="section2.html">Section 2</a></li>
	<li id="section3">
		<a href="#section3">Section 3</a>
		<ul class="tree">
			<li><a href="subsection1.html">Subsection 1</a></li>
			<li><a href="subsection2.html">Subsection 2</a></li>
			<li><a href="subsection3.html">Subsection 3</a></li>
			<li><a href="subsection4.html">Subsection 4</a></li>
		</ul>
	</li>
</ul>

Drawbacks and Limitations

The :target implementation seems to correct several of the :focus implementation's flaws, including actually allowing the children links to be clicked.

However, one still cannot toggle the expansion, nor indicate content to be expanded. And trees still cannot be more than one level deep, since an element is not targetted if a child of its is. Once again, a ::parent pseudo-element would be able to correct this, if it only existed.

However, by using targets, we automatically incorporate persistence. The page can be bookmarked with a menu open. You can also redirect menu expansion by having a link anywhere on a page target the particular branch. Keep in mind that targetting may cause scrolling of the page though, which probably isn't desired.

Browser support is better this time though! Well, kind of. The :target pseudo-class was implemented in 1.4 trunk builds of Mozilla, so anything less than Netscape 7.1 or other Mozilla 1.4-based browsers will only see the top-level links, making the menu unusable. However, newcomer Safari supports :target and the menu works in that browser! So, newer Konqueror builds probably render it correctly as well. Once again though, it downgrades nicely in Internet Explorer for Windows, but Opera and IE5/Mac may end up just seeing the top-level elements and nothing else.

Conclusion

The :target approach to CSS-based trees seems to be a little more successful than the previous :focus approach. However, there are still fatal shortcomings in the final result, keeping pure CSS trees out of the realm of conventional web design.