jongrieve.net
 Home > FAQs, Tips & Tricks > 'Dynamic' CSS

While Cascading Style Sheets (CSS) are a major step towards allowing Web developers to finely control the look and feel of their HTML creations, one fundamental problem exists: Fonts.  More specifically, font sizes.  A sample CSS might look like this:
 
  .heading
    {
      font-size: 14pt;
      font-weight: bold;
    }

  .bluetext
    {
      font-size: 9pt;
      color: blue;
    }

 
While it is possible to explicitly specify the desired font size using CSS, the size specified does not render identically on all combinations of browsers and target platforms.  A 9pt font, for example, is a very different size on PCs vs. Macs.  As far as I can tell, Linux doesn't even have a 9pt font by default (based on my limited exposure to Linux: Redhat 5.2 through 7.0 using KDE & Gnome window managers).  In this situation, Linux attempts to render fonts by the usual trick of shrinking or enlarging the next nearest size, however, it does a terrible job...
 
 
How the problem manifests itself...
Consider the table of point sizes below.  The left column is made up of images, so show exact point sizes as rendered on my PC.  The right column allows the browser to render the same text using its 'interpretation' of the point size specified.
 
ImageBrowser
8pt8pt
9pt9pt
10pt10pt
11pt11pt
12pt12pt
14pt14pt

 
I 'hope' the two columns look identical.  However, depending on the browser and platform you're running, they possibly won't because different browsers on different platforms render differently.  Add to that a further twist; different versions of browsers on the same platform often render differently.  For example, Microsoft Internet Explorer (MSIE) on the Mac renders point sizes the same as their PC equivalent, as does Netscape Navigator (NN) 6.x, however, NN 4.7 on the Mac does not.  The same is true on Linux; NN 4.7 renders incorrectly, whereas NN 6.x looks right.
 
Below are screenshots of the table above taken on various platform & browser combinations.  The screenshot that is the closest match to what you're probably seeing above has been indicated.

 
How it should look Netscape Navigator 4.7 on Macintosh Netscape Navigator 4.75 on Linux Netscape Navigator 6.01 on PC, Mac & Linux
Internet Explorer
on PC and Mac
Netscape Navigator 4.7
on Macintosh
Netscape Navigator 4.75
on Linux
Netscape Navigator 6.01
on PC, Mac & Linux

 
Above, I've stated that different combinations yield "right" or "wrong" results, however, there is no right or wrong.  The ultimate goal is that whatever the Web developer creates looks the same regardless of what platform or browser (or browser version) the man-on-the-street is using.  All too often, we see sites that just don't look right or, worse still, have the unacceptable "Best viewed with..." problem.
 
(Be warned though, for the rest of this 'article', I'm still going to refer to the browsers and platforms that don't look how I want them to look as having "the problem"... Smiley)

 
 
How a Dynamic CSS works
It was this goal that got me wondering how I could make the content I was creating look the same (or as similar as possible) for all possible visitors.  For me, the aim was to have page that I create using a PC look right on the other two platforms.
 
What struck me was that, if you look at the table of screenshots above, you can see that the 9pt font image is pretty similar in size to the 12pt Mac and Linux font.  So, I design my content using a 9pt font, but 'display' it using different point sizes.
 
This is where the concept of 'Dynamic' Cascading Style Sheets comes in.  Using CSS, I can influence how the HTML is rendered by producing a CSS with different point sizes depending on the browser that's used to request each page.  This principal is being used to serve up the page you're viewing right now; the entire jongrieve.net site is made up of pages whose fonts are being altered each time a page is served up.
 
If you look at the source of this page (and if you don't know how to do that, it's my guess that you're probably not interested in this 'article'.  Leave now; it's about to get pretty messy Smiley) you'll see the CSS near to top.  That defines the various point sizes used for the content, the most important ones being the BODY, P, TD & LI and .default styles.  These set out the defaut point size of the majority of the content (for example, this paragraph).

 
 
Building a Dynamic CSS
There are two main ways in which I've implemented the technique...
 
Server-side
This is where I originally developed the concept.  Most of the Web development work I've done over the past couple of years has been using a product called Tango, which is a server-side CGI.  Tango is very similar to the more popular products ASP, PHP and Cold Fusion.
 
Because these pages are being served up by a CGI, code can be executed between the process of a client browser requesting a page and the content being returned by the Web server.  The code that's executed examines the HTTP USER_AGENT header, determines which browser is being used to request the page and generates a CSS with the appropriate values for the font sizes.
 
The (psudo-)code looks something like this:
  IF (user_agent CONTAINS "MSIE") or (user_agent CONTAINS "Netscape6") or (user_agent CONTAINS "OmniWeb")
    'IE, Netscape 6 and OmniWeb render correctly, regarless of platform
    LET 8pt = 8
    LET 9pt = 9
    LET 10pt = 10
    LET 11pt = 11

  ELSE
    'This browser potentially has the problem, however, we know some fixes
    IF (user_agent CONTAINS "Macintosh") or (user_agent CONTAINS "Linux")
      'Mac or Linux
      LET 8pt = 10
      LET 9pt = 12
      LET 10pt = 12
      LET 11pt = 14
    ELSE
	  'Unknown; assume defaults
      LET 8pt = 8
      LET 9pt = 9
      LET 10pt = 10
      LET 11pt = 11

	END IF

  END IF  

  PRINT "<style>"
  PRINT "BODY { font-size: " + 9pt + "pt; }"
  PRINT "</style>"

 
Client-side
Having got the principal working server-side, I wished I could apply it to the existing 'static' content I had published around the place.  These pages were totally 'flat' .htm files published on ISPs Web servers, usually where no CGIs were available (although some allowed Perl).
 
Generally, this content was using style sheets in the more 'traditional' way, either directly coded into the .htm file...
  <head>
  <style>
    BODY { font-size: 9pt; }
    .bigtext { font-size: 14pt; font-weight: bold; }
  </style>
  <head>
  ..
  ..
...or, more commonly, using the...
  <head>
    <LINK REL="StyleSheet" HREF="/style.css" TYPE="text/css" MEDIA="screen">
  <head>
...meta tag.
 
It was these pages that in fact had originally brought the issue to my attention, as they were hard-coded to 'incompatible' point sizes.
 
The solution I came up with was to use Javascript to allow similar code to run at the browser. The code is as follows:
  if ( navigator.userAgent.indexOf("MSIE") != -1 || 
       navigator.userAgent.indexOf("Netscape6") != -1 || 
       navigator.userAgent.indexOf("OmniWeb") != -1)
    {
      // Microsoft Internet Explorer, Netscape 6 and OmniWeb all render
      // correctly, regarless of platform.
      var fnt8 = "8pt";
      var fnt9 = "9pt";
      var fnt10 = "10pt";
      var fnt11 = "11pt";
      var fnt12 = "12pt";
      var fnt14 = "14pt";
      var fnt16 = "16pt";
    }
  else
    {
      if ( navigator.userAgent.indexOf("Macintosh") != -1 || 
           navigator.userAgent.indexOf("PowerPC") != -1 || 
           navigator.userAgent.indexOf("Linux") != -1)
        {
          // Mac and Linux
          var fnt8 = "10pt";
          var fnt9 = "12pt";
          var fnt10 = "12pt";
          var fnt11 = "14pt";
          var fnt12 = "14pt";
          var fnt14 = "18pt";
          var fnt16 = "22pt";
        }
       else
        {
          // Unknown - assume defaults.
          var fnt8 = "8pt";
          var fnt9 = "9pt";
          var fnt10 = "10pt";
          var fnt11 = "11pt";
          var fnt12 = "12pt";
          var fnt14 = "14pt";
          var fnt16 = "16pt";
       }
    }

  document.write("<style>\n");
  document.write("BODY { font-size: " + fnt9 + "; }\n");
  document.write(".bigtext { font-size: " + fnt14 + "; font-weight: bold; }\n");
  document.write("</style>\n");
The Javascript is saved to a separate file called css.js and is added to each document like this:
  <head>
    <script src="/css.js"></script>
  <head>

 
Synopsis
This code works for the majority of browsers and platforms I'm expecting as 'visitors' to my site.  It's not perfect, I'll admit.
 
For example, the code assumes that Netscape 6 will render correctly on all platforms, which is something I've never verified beyond my various PCs, Mac OS 9.x & OSX and RedHat Linux 6 & 7.
 
If a known browser is not detected, the code specifically looks for Mac and Linux and assumes it's a PC if neither are found, which means that other Unix platforms - I've certainly seen vists from SunOS, HP-UX and AIX - probably look different.
 
If you have access to additional platforms, I'd appreciate any feedback, so please feel free to Contact me.





Copyright © Jon Grieve
Visitor Number 903,852
Home   Contact   Top
This site is optimised for Internet Explorer, Netscape Navigator and Mozilla on Windows, Macintosh & Linux.



 
 
If your browser does not fully support HTML Style Sheets, these pages may not appear correctly formatted.