HowTo: Dynamic Content Creation with CSS2

I'm a big fan of using CSS to control layout. Not just for its ease of maintainability, but for the separation of layout from content.

When Firefox 1.5 was released, I found out that dynamic content creation via CSS was including within the codebase. So the below works in Firefox 1.5, Opera 8, but not Internet Explorer 6.


Markup

Here is the setup that I use in order to do automatic line numbering for code excerpts that I've posted here:

  • Each code-block is encapsulated within it's own div tag with a class called code.
  • In order to maintain semantic markup, the source code is placed within a code tag.
  • Each line of the source code is wrapped within a span tag with a class called line. code tags don't validate if each line is wrapped within a p tag.
  • Each line of the source code is followed by <br class="hide" />. This is to preserve the ability to copy/paste the code since we are using inline elements.

Hide & NoPrint Styles

              <style type="text/css" media="screen">
              .hide, .noprint {
                  display: none;
              }
              </style>
              <style type="text/css" media="print">
              .hide, .noprint {
                  display: none;
              }
              </style>
          

Code Block Style

First of all, let's style the code block so it is aesthetically pleasing.

              div.code {
                  background-color: #DDD;
                  padding: 5px;
                  border: 1px solid black;
                  counter-reset: line;
              }
          

Lines 2-4 are fairly obvious. I set a gray background color, 5px worth of padding, and a nice black border. Line 5 is something new. That line resets a counter called line. The CSS2 standard says it resets to a value of 1, which is what we want. The reset means for every div.code the counter is reset to 0. Other starting values can be specified by counter-reset: line, x which would reset line to x.


Styling a Line of Code

Now we will style each individual line of code.

              div.code code span.line {
                  display: block;
                  line-height: 1.2em;
                  margin: 0; padding: 0;
                  counter-increment: line;
              }
          

Recall that my code excerpts are wrapped within a div tag and then a code tag.

On line 2, we specify display: block; so that each line displays as a line rather than all the text running into each other without line-breaks.

On line 5, we increment our counter (line). The CSS2 standard specifies that increments are done by a value of 1, which is exactly what we want. Other increments can be done by using counter-increment: line, x which would increment line by x each time.

In the event that you are incrementing and displaying a counter, the counter is first incremented and then rendered. Also, elements with display:none; do not cause the counter to increment, but visibility:hidden; will cause a counter to increment.


Display and Formatting

And the final bit of CSS we need is to actually display our counter value.

              div.code code span.line:before {
                  content: counter(line, decimal-leading-zero) ': ';
              }
          

Before each line (span.line:before), we finally specify our dynamic content. I want the line number (padded with zero's) followed by a colon and a space before each line. counter(line, decimal-leading-zero) gives me the line number with padded zeros. Counters can be formated using values from list-style-type.


Indentation

CSS can be used to control indentation (via the padding-right), but this does not degrade gracefully to text-based browsers. I used non-breaking spaces (&nbsp;) to control indentation.


Wrap-Up

And there you have it. Dynamic content creation with CSS2! The entire CSS file can be downloaded.

You can find examples of this in use within any of my articles that involve code (jSettlers Bash Script, Really Simple Syndication at Last!, Akregator & Podcasting, Cisco Aironet 350, WEP, and Linux, Using OpenSSL for AES/Rijndael Encryption, Website Reporting with Webalizer).


References



Tags

  • Cascading Style Sheets

Revisions

  • 12/24/2005 - Article published.