Debugging HTML structure using CSS
Update
This article was written in November 2003. I wrote another article about the actual implementation of this technique: QA with stylesheets
A visual tool for editors
Any browser can handle a lot of coding errors.
If you put a P tag and a LINK tag in a document, give it the html extension and it will display the file. No problem. You might think this is an advantage and it certainly helped webmasters that didn’t want to learn HTML or CSS, but when you try to maintain a large corporate website, you’re in trouble.
Especially if the standard tools are FrontPage / IE and editors don’t know anything about HTML. They just need to know how to edit pages in FrontPage. This means that a lot of coding errors come up, structural errors, editors adding tags, attributes etc. To avoid all this, I needed a way to display all the tags that weren’t allowed in the pages. That way the webmaster (=me) and the editors could quickly spot errors and maintain a consistent look across all parts of the website.
Debugging the tree
For the first part, IE6 (or Moz1.6/NS7 or Opera) will do the job. These versions can all handle CSS1 and part of CSS2 and we will need a bit of both to create a debug-stylesheet.
User stylesheets
In most browsers you can define a personal stylesheet. For example if you wanted all links underlined on a webpage and the webdesigner of your favorite site specified not to underline the links, you can add a user stylesheet and change the styling of the links.
Define a rule for the A tag and add the important statement to the text-decoration property and put it in a CSS file. Note that the important declaration is actually important. When specifying a user stylesheet all the properties with the ! important flag will be rendered and override any other rule specified in the page.
A{ text-decoration: underline ! important; }
In IE you can override the stylesheet by selecting an accessibility option: User style sheet > Format documents using my stylesheet. Browse to the stylesheet and select the document. Now all links will be underlined.

If you are using another browser and want to learn more about userstylesheets check out the css-discuss wicki. They have a section on Userstylesheets
Allthough IE doesn’t support the advanced CSS2 selectors (only the descendant), there is more we can do with IE. When you’ve read the article by Eric Meyer you know that IE cannot handle his css tools cause they use CSS2. These tools work great for detecting the absence of attributes or their value and I use the technique very often to check websites. But at this point they cannot detect structures or bad markup code. Besides that, looking for something else than IE in a corporate environment is a desperate act. (Update 14/11/2007: Firefox is coming up even in corporate settings, but 4 years ago that wasn’t possible.)
Structural markup
But what is bad markup? If the code validates and it displays all the info in the right place everything should be ok, or not?
When you are working with simple html files and the editors have full control over the documents some tags might get lost. In the beginning this is nothing to worry about (you’d think) but after 5 editors editing 1 document a lot can go wrong. Bad markup is markup that isn’t needed or isn’t at the right place in the tree.
Assume this scenario. You have a document with a header, a content section and a footer defined in 3 DIV-blocks with an id. This is the template all editors need to use. The template is divided into 3 sections which all have an id attribute.
<div id="heading"></div> <div id="content"></div> <div id="footer"></div>
Inside the heading you put a list of navigational links, a logo and a search bar. The content holds a header with some links, and the footer contains the webmasters email and the copyright notice. (For now we will skip the header and the footer and focus on the content DIV.) After the document has been edited a few times, you get a lot off empty span elements (Frontpage), empty P tags as line breaks, forgotten tags, redefined headers (with the style attribute), etc..
That is not what I wanted!
The code gets cluttered and all you had in the beginning was a simple structure with divs, headers and links.
The basic assumption is that your website uses a template with a specific tree of elements to organize the content. For example the header div cannot contain a H2 and the content div cannot contain a H1, all text inside cells should be in P tags, only a table header cell can contain headings etc … When an editor places a tag outside the allowed tree it should be visible and displayed as an error!
This were the debugging stylesheet comes in
CSS selectors and universal selector
The descendant selector can provide a powerful mechanism for styling elements in a tree of HTML elements. When you need to reach an element without an ID or Class attribute deep in the document a descendant selector can match the element like this:
<div id="content"> <h1 id="someId" /> <div> <a /> <a /> </div> </div>
BODY DIV#content DIV A{
/*descendant selector with color rule*/
color:red;
}
This means that every A element inside a DIV tag that has a parent DIV with the value “content” as ID will display according to the rules specified. Any element is within reach at this moment. But that is not exactly what we need. If we want to debug the html file for errors in the template we need to track all the elements that are NOT allowed inside the tree of the template. If a link appeared outside a DIV it should be displayed as an error. The universal selector can do just this:
*{ color:red }
This means that the content inside any tag will be displayed as red colored text.
Now all we need to do is add the rules from the original stylesheet but fill the selectors up to the top element with their parents. With complex templates, the stylesheet can grow really big.
In the above example this is quite easy because only 2 elements contain text, the heading level 1 and the link element. Anything else is not allowed. Please check the example file with a correct div and a div with errors.
BODY DIV#content DIV A{
/*descendant selector with color rule*/
color:black;
font-size:1em;
}
BODY DIV#content H1{
/*descendant selector with color rule*/
color:black;
font-size:1em;
}
To make sure all styles are applied and to override style rules defined inside the style attribute, add the ! important flag to override the rule. That way editors cannot bypass the stylesheet using the attribute.
Empty elements
If you checked the source for the first example you’ve noticed some empty elements in the tree which weren’t displayed as errors. To make these element visible we should promote them to block level. That way it is possible to apply a border to the element.
*{
color:red;
display:block;
border:1px dashed red;
}
The concequence of this rule is that all elements become block level surrounded by a border. This disrupts the normal flow of the page. Add a “display:inline” rule to all inline elements like link tags and a “border:none” rule to all the allowed elements. Now only the elements dat shouldn’t be in there are displayed with red colored text and a dashed border. The example file shows two sections: one with and one without errors
BODY DIV#content A{
display:inline;
border:none;
}
Debugging
Now that we’ve created a stylesheet for our template we do not want to display all these errors to the visitor but check the pages before they are published. You can do this in 2 ways. The first method is already listed at the beginning of this article: specify a user stylesheet in the internet options of IE. If you don’t want to switch the stylesheet every time you access an internet page add an id to the BODY tag. This is an accessibility feature and makes it possible for other people to create some style rules in their user-stylesheet for your webpage. We might as well take advantage of this trick. The stylesheet looks like this for a “mySite” id on the BODY
*{
color:red
display:block;
border:1px dashed red;
}
BODY#mySite DIV#content DIV A{
/*descendant selector with color property*/
color:black ! important;
font-size:1em;
display:inline;
border:none;
}
BODY#mySite DIV#content H1{
/*descendant selector with color property*/
/* no need for display property*/
color:black ! important;
font-size:1em;
border:none
}
The second option is to create a bookmarklet that refers to the debug stylesheet on your server. Use the bookmarklet tool on squarefree.com , add an import rule like the one below and drag the link to your links-toolbar.
@import http://www.yoursite.be/debug.css
Just use the link to expose all the structural errors when reviewing pages.
What’s next
When you think about using such a tool, create a debug stylesheet next to your template. When the template is done just create an XML file of the tree. This is easier to check the parent child relation ship. Because the stylesheet can grow really large when you’re using a lot of different tag, you should only use it to debug not for live viewing. The descendant selector is very heavy and can slow down the rendering of your pages.
At this point I’m recoding a stylesheeet to expose accessibility features, so stay tuned for more articles