Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, PHP, and whatever else I happen to feel like hacking at.

Style Sheets and HTML, Part Two

Jerry Stratton, April 2, 2005

So, the first part of this tutorial covered the basics of style sheets:

  1. how to add a style sheet to an HTML page
  2. how to apply style properties to HTML elements
  3. how to apply the same properties to multiple elements at the same time
  4. how to add a class to an element
  5. how to apply properties only to elements that are part of other elements

Here, we’re going to get into some more advanced features of CSS. We’ll learn how to look at adjacent elements, how to detach elements so that other elements wrap around them, and how to use special “pseudo-elements”, among a few other special features that make CSS even more useful.

Adjacent elements

Besides singling out elements that are children of other elements, such as table cells inside of tables, we can also single out elements that follow other elements.

For example, our review includes a quote from the book immediately following our level one headline. If all of our book quotes do the same, we can give that quote a unique appearance without going through each review and giving that blockquote element a special class. (Note, thought, that in this case a special class might well be more appropriate.)

Specify adjacent elements with the plus sign. The selector “h1+blockquote” means any blockquote element that follows an h1 element.

[toggle code]

  • h1+blockquote {
    • font-family: VTypewriter RoyalDeLuxe, American Typewriter, Courier, sans-serif;
    • margin-right: 0;
    • margin-left: 10%;
  • }

Here, we’ve specified a special font for that blockquote, as well as reduced its right margin from the default to zero, and set its left margin to 10% of the body’s width.

We might also want to give paragraphs an indent, but this is commonly only done for paragraphs that follow other paragraphs. Paragraphs that follow a headline or a quote don’t necessarily get indented. By selecting for “p+p”, we can apply our style properties only to paragraphs that follow a paragraph.

[toggle code]

  • p+p {
    • text-indent: 1em;
  • }

Sidebars and floating blocks

Some information is best presented, visually, as a sidebar. Rather than presented sequentially, items can be “detached” from their location on the web page and “floated off” elsewhere. The easiest way to do this is with the float property. Elements can be floated off to the right or the left with the float property.

The table of information about our book would make a great sidebar. Let’s float that off to the right and let text wrap around it on its left. The table of book information already has a special class, “bookinfo”, so that we can apply styles to this kind of table without accidentally applying it to other tables that might show up in our book reviews.

[toggle code]

  • table.bookinfo {
    • float: right;
    • border-style: solid;
    • border-width: .15em;
    • border-color: orange;
    • margin: 0;
    • margin-left: 1em;
    • margin-bottom: .1em;
  • }

We told the web browser to float any table with the class “bookinfo” off to the right, give it a solid orange border, and a margin only on its left and bottom.

Before and after

Our sidebar of book information really would look a whole lot better if we had put some colons in the row headers. We can use style sheets to add them. There is a special kind of selector called a “pseudo-element”. This is an element that sort of exists, and we can modify it. Two of these are the before and after pseudo-elements. The “before” pseudo-element is a fake element that appears inside of the element and just before any of the true content of that element. The same for “after” except that it appears just after any of the true content.

We can use the after pseudo-element to put text, such as a colon, into our th elements.

[toggle code]

  • table.bookinfo th:after {
    • content: ":";
  • }

We no longer need the vertical orange bars to separate our row headers from our row content, so remove the border properties from our th element’s style so that it reads:

[toggle code]

  • table.bookinfo th {
    • text-align: right;
  • }

Note that the colon is bold, just as all of the real content in the “th” element is. Pseudo-elements inherit the styles of the elements they are part of.

Pseudo-elements are specified with a colon between the element name and the pseudo name.

Links

If we want to change the properties of linked text, we can apply our changes directly to the “a” element:

[toggle code]

  • a {
    • color: orange;
  • }

However, doing that will make linked text always orange. Applying styles to the “a” element does not distinguish between visited and unvisited links. For that, we have the pseudo-elements “link” and “visited”.

Replace the “a” style we just made with:

[toggle code]

  • a:link {
    • color: rgb(74, 36, 199);
    • font-weight: bold;
  • }
  • a:visited {
    • color: orange;
  • }

Now, here we have specified an orange for visited links, but color “rgb(74, 36, 199)” for unvisited links. Besides named colors, we can also set our colors with a specific amount of red, green, and blue. Color numbers go from 0 to 255. You can also use 0% to 100%, but most color pickers will give you the 0-255 range rather than the percentages. Here, we’ve specified a red of 74, a green of 36, and a blue of 199.

Mouse feedback

We can provide feedback to the reader by using the hover and active pseudo-elements. Active usually makes sense only for elements that do something when clicked, but hover can be used for any element.

[toggle code]

  • a:hover {
    • border-style: outset;
    • border-width: .15em;
    • border-color: orange;
    • background-color: rgb(90%, 90%, 90%);
  • }
  • a:active {
    • border-style: inset;
    • border-width: .15em;
    • border-color: orange;
    • background-color: rgb(40%, 40%, 40%);
  • }

Here, we’ve told the browser to turn any link into an outset button when the mouse moves over it. When the mouse clicks on the link, the browser will then “inset” the button, so that it looks like it is being depressed.

Display types

There are three basic kinds of elements, as far as style sheets are concerned: block, inline, and list-item. Block elements are elements such as paragraphs, headlines, and div. Elements that are what in a word processor we’d call character-level styles, are inline elements.

You can use the display property to change an element from one to another. You can also use the display property to hide an element, by settings its display to “none”.

When used in conjunction with hover or active pseudo-elements, this can be used to create pull-down or pop-down menus or other information. When used with printing, it can be used to show or hide certain information when the document is printed.

For example, the following style sheet properties will cause the definition portion of the definition lists at the bottom of the page to disappear:

[toggle code]

  • dd {
    • display: none;
  • }

And this code will cause it to re-appear, but only when the mouse hovers over the list:

[toggle code]

  • dl:hover dd {
    • display: block;
  • }

That’s not very useful for this page, so once you have it working, remove it.

Printing styles

Often, you’ll want different styles for printing than for display on a computer screen. In fact, there are many different places your web page can “display”, and you may want different styles for each of them.

At the top of this page, in the head section of the HTML, we have:

  • <link rel="StyleSheet" href="reviews.css" type="text/css" media="all" />

Add a new line immediately after this and change the “all” to “print”, and the “reviews.css” to “print.css”:

  • <link rel="StyleSheet" href="print.css" type="text/css" media="print" />

You can use this to hide (display: none) items that are pointless to print. For example, navigation menus are often set to not print. They waste space on the paper.

In our case, we have a wide left margin. We can reduce that margin on printing by putting the following as our print.css file:

[toggle code]

  • body {
    • margin-left: 0;
    • width: 90%;
    • border-style: none;
  • }

This will also remove the border on the left side of the page.

Now, when printing our page out, people cannot click on the links: there isn’t anything to click on paper. But we can display the URL of links when printing. To your print.css, add:

[toggle code]

  • dt a:after {
    • content: " (" attr(href) ")";
  • }

This takes the text of the href attribute of the link in question, and places that as the content after the link. You will now see, on printing, the URL in parentheses after each link that is in a definition term. You will also notice that the definition terms are horribly justified! This is because the URL is generally quite long, and we earlier specified that all text on our page is justified. Add the following snippet to de-justify dt text:

[toggle code]

  • dt {
    • text-align: left;
  • }

More about precedence

We added the print style sheet after the general style sheet above because order in style sheets matters. Style definitions that take place last will take precedence over earlier ones. This allows us to have otherwise-conflicting styles. The last one takes effect. When not printing, only the “all” style sheet is used. When printing, the “print” style sheet is used in addition to the “all” sheet. Any conflicting styles are resolved in favor of the “print” sheet, because we put it second.

More important than order, however, is specificity. The more specific a style definition is, the higher its precedence. A style definition for “table.bookinfo” will always take precedence over one for “table”, because “table.bookinfo” is more specific than “table”.

Watch your changes

Be careful, when making changes, that you are not relying on some settings that are not CSS dependent. For example, when setting a foreground or background color, you should also set the other. Otherwise you run the risk that the user has a foreground color that matches your background color, or vice-versa.

Another example is setting block text to some character-level formatting. If you make blockquotes italic, for example, what happens to emphasized text inside the blockquote? It will also be italic, rendering it indistinguishable from the blockquoted text. If that’s a problem, you should fix it. For example:

[toggle code]

  • blockquote {
    • font-style: italic;
  • }
  • blockquote em {
    • font-style: normal;
  • }

This turns any emphasized text inside of a blockquote to normal instead of italic. Since it also sets blockquoted text to italic, the emphasized text once again stands out.

Good design helps

Much of this is useful even with poorly designed web pages. But well-designed web pages make it much easier to take advantage of style sheets later on. Because we know that a blockquote following a level 1 headline is always a special quote, we can change the special quote’s appearance in all reviews, without making any changes to our HTML files at all. Only a small change in the single CSS file is required. But if we don’t know that, we need to add a class to each blockquote that is our “special” headlining quote. It is easier to add such classes from the start than it is to go through later and change all files.

Always close your tags. Many tags have assumed endings, such as list item tags and various of the inner table tags. But you will get much more reliable results if you expressly close all of your tags. This also makes it easier for you to find some of the more annoying errors.

  1. <- Style Sheets
  2. MySQL Tutorial ->