Trees, Elements, and Selectors

Trees and Elements

Markup languages such as SGML (of which HTML 4.0 is an application) and XML (of which HTML 5.0 will be an application) describe a tree structure containing the content of the document. (See Arjun Ray's article [alternate link] for a good explanation of trees.) The following HTML document is indented to show the tree structure. Each element in the document tree contains other elements, content, or a combination thereof. HTML is designed so that markup describes the content, that is, an h1 element represents a top-level header, a blockquote element represents a quotation, etc. If HTML is used in other ways (using h1 to specify large text, using blockquote to indent, etc.), then stylesheets may cause unwanted consequences.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
   "http://www.w3.org/TR/REC-html40/strict.dtd">
<html lang="en-US">
  <head>
    <title>
      A Document
    </title>
  </head>
  <body>
    
    <h1>
      About Document Trees
    </h1>

    <p>
      Document trees are wonderful, because they allow:
    </p>

    <ul>
      <li>
        styling of elements
      </li>
      <li>
        scripting of behaviors on elements
      </li>
      <li>
        machines to understand the structure of documents
      </li>
    </ul>

  </body>
</html> 

The vocabulary of markup languages is relevant to CSS, and necessary for understanding how CSS works. Thus I will define the following terms:

Document tree
The document tree is the tree structure representing the document. It consists of the root element and all of its children.
Element
An element is a node in the document tree. In the markup, it is delimited by tags, usually a start tag (such as <h1>) and an end tag (such as </h1>. It can contain elements or data content.
Parent
The parent of an element is the element in which it is contained. In the example above, the body element is the parent of the h1 element, and the ul element is the parent of all of the li elements.
Child
A child element is an element directly contained within another element. In the above example, the body element has three children, an h1 element, a p element, and a ul element.
Root element
The root element is the element at the top of the document tree. In the above example, the html element is the root element.

Selectors

This section (as is the section on non-CSS presentational hints) is based partially on an article I wrote on comp.infosystems.www.authoring.html.

Every CSS rule (or ruleset) has selectors and declarations, for example, in:

h1 { 
  font-family: Tahoma, Verdana, Arial, sans-serif;
  }

The (one) selector is h1 and the (one) declaration is font-family: Tahoma, Verdana, Arial, sans-serif;. Each declaration has a property and a value (and possibly a weight). In this case, the property is font-family and the value is Tahoma, Verdana, Arial, sans-serif. CSS selectors match elements in the document tree. This means that the CSS selector h1 doesn't match anything inside an h1 element. It only matches the h1 element. Many properties, by default, inherit from the parent element. Thus if is no declaration for a property that inherits (such as font-family), an element will have the same value as its parent did. However, if another declaration for that property has a selector matches an element inside the h1 element, the properties declared in the rule with that selector will not be inherited from the h1 element. This has nothing to do with specificity or cascading. Specificity and cascading only resolve which value is used when multiple declarations of a property have selectors that match a given element. If there is only one declaration that matches, it is used. This means that if a UA style sheet has:

h1 { font-size: 24px; } /* UA stylesheet, specificity 1 */

and an author style sheet has:

div#id1 { font-size: 16px ! important; }  /* author -important, specificity 101 */

you will still get

<div id="d1"><h1>This header is 24px</h1></div>

even though the div selector is more important than the h1 selector in three ways (weight, origin, and specificity). This happens because the h1 selector still matches the h1. The only way to override that is to use another selector that actually matches the h1, for example "div#d1 h1", "h1", or "div#d1 *" (using the universal selector, which causes problems in some browsers).


Valid HTML 4.0!

(Up to User Stylesheets Guide, CSS, David Baron)

LDB, dbaron@dbaron.org, 1999-06-15