This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


This article assumes you're familiar with HTML.
Download the code (644KB)

Cascading Style Sheets:
Filters, Fonts, and a Few Old Friends

Bryan McCormick

Positioning, fonts, layering, filters, and crazed robots. Welcome to the world of Cascading Style Sheets!
Cascading Style Sheets have come a long way. With Microsoft® Internet Explorer 4.0, designers and developers finally have access to all the great features of CSS1 and DHTML (CSS plus scripting). Internet Explorer 4.0-specific features are media-rich, dynamic, and flexible. There is so much packed into it that I was surprised to discover a lot of new faces on old elements which I had heard little or nothing about. For example, you now have the ability to embed rich CSS and HTML content into button definitions. Another Internet Explorer-specific tag, <marquee>, has also been updated to let you embed anything you want, including whole pages.
      In this article, I'll focus on three new features in Internet Explorer 4.0. I'll concentrate on features that give designers and developers a little more flexibility and range—filters, font embedding (also called Open Type), and a DHTML trick for your old friend the <iframe> tag. I think you'll find that the creative possibilities inherent in these features make them well worth learning. Of course, I'm only scratching the surface with the examples I've put together here, but I hope that you'll get enough of a taste to want to venture further. For those of you familiar with the production values of CD-ROM graphics, I think you'll find the CSS filters rule extremely interesting. Along the way, I'll also touch on more broadly applicable features of CSS, particularly positioning and control over graphics.
      Compatibility and downstream issues are likely to be problem areas if you're trying to do more complex work with CSS. You are going to find plenty of bumps in the road, especially when spanning browser versions and platforms. Be aware of how each browser flavor and version handles CSS so that you can provide the best possible experience for your users. Reading the CSS1 specification won't give you a full grasp of what Internet Explorer 4.0 supports because many of its features, such as positioning and media-dependent style sheets, are outside of the specification. In fact, I suggest that you read some of the older drafts (which have now been rolled up into CSS2) to get a good sense of how they work. The most up-to-date and reliable sources for features supported by your browser and for bugs and workarounds are Eric Meyer's list at Web Review (http://style.webreview.com) and the CSS Pointers Group bug list and workarounds (http://home.att.net/%7Esjacct/bugs.html#Foot1).

Position is Everything in Life; Or, I Don't Do Tables
      Positioning, the ability to place elements specifically and (for the first time) absolutely where you want them down to the pixel level, is perhaps the best thing about CSS from a designer's perspective. The syntax for this rule is:


 {position: [absolute, relative, static]; [top;left;right;bottom]}
For my purposes, I was only concerned about exploiting the ability to place elements directly on the page in a specific space, so I expressed all of my values in absolute terms. Relative values are useful when you're using more complex nested boxes. For example, if you want to place several <DIV> elements within a parent <DIV>, you would likely use values relative to the enclosing parent element rather than the <BODY>. Relative values would also be used when you want a page to reflow to accommodate a change in window size or to move relative to other elements on the page.

Scrolling Without Bars
      Information design and interface problems that I often encounter in Web design include the inflexibility of elements and the confines of a small amount of screen real estate. In an attempt to solve this problem, I created a page that contains information about a metropolitan area, much like the city guides you can find on the Web (see Figure 1). One of the interface issues that has bothered me most about these services is the way that map information gets served. I'm sure you've used services where you zoom in and out of a map to change your view. Unfortunately, the page hardly zooms; instead you get a lot of refreshes as each new snippet of the map is loaded in and you lose the overall view of the area. Moreover, there is nothing else for you to look at while this is happening, so you don't even have the benefit of being able to read something at the same time.

Figure 1: Scrolling Tricks Demonstrated
Figure 1: Scrolling Tricks Demonstrated


      The map I wanted to use was quite large, but I didn't want to reduce it because it was also extremely detailed. Had I scaled it to fit, it would have become incomprehensible. I can imagine a situation where a graphic artist spends hours retouching a map just to overcome this sort of limitation.
      The only alternatives currently available to a Web designer are to divide the map into small pieces and fit it into the widest space possible on the page, or to place it in a scrollable frame, which is functional, but butt-ugly. The first choice requires a lot of hand labor, and the second choice excludes any other information that you might want to put on a page to give the map some context. There just has to be a better way.
      The scrolling technique creates a large virtual surface that a user can selectively drag into view. But how would you do it on a Web page? I'm going to come back to this in a moment. First, I'd like you to look at how the rest of the page is laid out and start familiarizing yourself with the style sheets I used to make it work (see Figure 2).
      Notice that what would normally be a graphic placed in a table structure is organized using columns, a label, and a call-out. I was able to create a series of classes (.mapBox, .bodyHeader, .mainBody, .mapLabelHead, .mapLabel and .callOut) and some <DIV> tags that I could place anywhere I wanted on the page. Creating these elements as classes gave me the flexibility of adding and subtracting them from the page as I played with the layout. If I had used table structures, the process would have been tedious and awkward. Tables are useful for repeating data elements of a consistent type, like financial information or catalog items. However, they were never intended as a design tool for layout.
      The style sheets in this example are extremely simple. Unlike my prior experience with placing elements arbitrarily on the page (through kludgy negative margin tricks), it was easy to plunk things down where I wanted them to go. No fuss, no muss. Through the mechanism of setting box properties such as width and height, I was able to control the dimensions of the regions I was creating without the usual overflow problems. The most difficult part of producing the page layout was deciding how I wanted it to look—not (for a change) how I was going to do it.
      Adding additional elements, for example the .mapLabel and .callout classes, is as simple as creating another <DIV> and giving it the proper class association. This is such a flexible means of producing the page that I didn't even have to worry about where I was placing the <DIV> elements in the HTML flow. Note that for downstream browser compatibility, it is probably a good idea to place the elements in the flow where they would look best if they were not going to be controlled by CSS. Of course, that can be difficult, and in some cases it may not be feasible to incorporate a reasonable backward-compatible alternative in a single page. If it's not feasible, it may be best to implement browser detection and serve the page according to the browser's capabilities.
      You may notice one oddity when looking through the sources (see Figure 3   test it ); namely, how I handled the placement of the <iframe> itself. The style sheet is for the <DIV> that encloses the <iframe>, with much of the style information for the <iframe> found inline within the tag. I chose to do this because the map area in question might not always contain a scrolling map—it might instead hold a still photograph or static map that would not require an <iframe> tag.
      The only part that didn't work as advertised was setting colors on the borders for the .callout class. I wanted to make these a color other than black, but when I did so the right-hand border took on a black value in addition to the previously set color. I didn't have time to figure out why that happened, but it's possible that other rendering anomalies of this sort are lurking, which is yet another good reason to check the compatibility lists.

To Scroll or Not to Scroll
      On to the scrolling itself. Just so you know straight off (and to make sure I don't get mail on scripting issues), what I don't know about JScript® and VBScript could fill a book. So instead of asking me, pick up Inside Dynamic HTML (Microsoft Press, 1997), by Scott Isaacs, which is a must read for DHTML and Internet Explorer 4.0 issues. Scott does a great job of explaining the core of DHTML's functionality and the book contains many examples. The JScript in Figure 2 depends entirely on Scott's samples.
      When I was thinking about how to do this sample, I had a different approach in mind. My first thought was to try using the new {clip} rule in CSS—in other words, mask off the picture and then move it underneath the mask so that only the portion under the clipped area would show through. The problem was that the scripting was going to be very complex and cumbersome and I wasn't even sure if this solution would work. I was concerned that the drag event wouldn't work properly with the picture, which would essentially lie underneath a <DIV> or other element that I was using as a mask. I was sure the element, not the picture, would get the event and I didn't know a way to send events outside of the event bubble hierarchy.
      It then occurred to me that the <iframe> would be a simpler way of accomplishing my goal. All I had to do was put the scrolling routine into the target page and the rest would be easy—no problem with guessing which element was getting what event, and the construction of the page would be neater and simpler. This would have been a less than ideal solution if I'd had to use a <frameset> instead. The fact that the <iframe> could be placed anywhere, just like any other element, made it the best solution.
      One other subtle but essential feature from CSS2 that Internet Explorer 4.0 provides is the ability to control the appearance of the cursor in response to a mouse event (the rule, logically enough, is cursor: "cursor name";). As the mouse passes over the target picture inside the <iframe>, it changes to the move cursor familiar to users of Windows®. True, it is hardly earth-shattering from a functional perspective, but I think the experience for the user is a more natural and intuitive one than having everything labeled to suggest whether it is active and scrollable.

Warhol's Flowers Lead to Layered Fun
      While on vacation in Toronto recently, I was inundated with Andy Warhol merchandise at the Art Gallery of Ontario. Warhol's flower images—a simple posterized effect in a quadrant—has stuck with me. I wondered whether I might be able to do something similar using the new CSS features that provide control over backgrounds (see Figure 4).
      At first I thought that I would have to do a lot of futzing to get this to work. It occurred to me that I should be able to prepare a single graphic and then apply it to four separate backgrounds. Truthfully, I could have achieved this effect to some degree by using a <table>. But I wanted to do more than just lay a graphic on top of a background. I was almost certain that there was something else in Internet Explorer that offered more creative latitude. I discovered that you can do some amazing things with filters that save time, allow for greater experimentation and creative play, and enable you to create truly amazing results with no impact on bandwidth.
Figure 4: CSS Flowers
Figure 4: CSS Flowers

      From my prior experience with positioning, I knew that doing an overlay of elements was going to be easy. With absolute positioning, you can force elements to occupy the same x,y coordinates (and even z through z-index: value;). But overlaying the picture onto a background meant making part of the image transparent so that the background image or color could be visible; otherwise the graphic would cover it.
      When I first started working on this sample I was using a JPEG file for my source image. Now, as you may know, JPEGs don't allow you to knock out a color the way GIFs do, but I was reluctant to convert the image because it had already been compressed.
      I remembered looking over some examples using filters in the Internet Client SDK and thought I'd have a closer look. Although filters lie outside the scope of both the CSS1 and CSS2 definitions, the mechanism through which they are called is now part of CSS. In Internet Explorer 3.x these were called through the <OBJECT> tag.

Filters Meet Flowers
      The solution to my color knockout problem was the Chroma filter (see Figure 5   test it ):


 filter: Chroma (color name or value);
It allows you to selectively eliminate a color from any image or element without having to modify the source file. It worked for the image I was using, but not as well as I would have liked. Why? As I was reminded by a savvy graphic artist, JPEG files may not always properly produce a given color evenly over the whole of the image, especially when they have been highly compressed. Although you may not be able to discern the differences between colors in a compressed image, the filter can. Also, compression exacerbates pixel boundaries, and the filter seems to catch those differences as well. The results looked quite speckled, and I decided I'd have to go the GIF route and knock out the color manually.
      I encountered one more bump in the road. I had to manually set the transparency color in a graphics application even after I switched to GIF because the color I wanted to use as the neutral transparency color was a mid-range gray. For some odd reason, the Chroma filter would not work on any shade of gray that I tried.
Figure 6: Flower Components
Figure 6: Flower Components
      Once I had the transparency problem in the GIF taken care of, I could apply the Chroma filter to the white in the flower's petals. Of course the flower wasn't uniformly white, so certain areas were less transparent than others. This was exactly the effect I was looking for, and the image came close to looking posterized without having to render the effect as a graphic—very cool. The only remaining problem was that the color showing through the flower belonged to the <BODY>. For my sample to work, I needed four separate colors under each of the four instances of the flower. The solution was quite simple. So simple, in fact, that I've included a chart for you to follow along with (see Figure 6).
      It occurred to me that the easiest way to put another color behind the flower was to nest the <DIV> containing the flower GIF within another <DIV> that would hold the background color. This way I didn't have to worry about positioning at all. The parent <DIV> (what I refer to as class .flowerback in the style sheet, numbered from 0 to 3) would contain the flower GIFs and their background color. Defining the coordinates of the parent <DIV> was all I needed to do to have them align correctly, so there was no need to make each element an independent layer.

 <DIV CLASS= "flowerBack0">
     <DIV CLASS= "wildflower0">
     <img src="Wflower4.gif" width=200 height=200 alt="" border="0">
     </DIV>
 </DIV>
      By setting a background color for the <DIV> in which I placed each instance of the flower, I was able to play with the color variations as much as I liked just by changing the RGB triplet. This saved a huge amount of time over manual methods of producing the same result in a graphics package. Another benefit of this method is that I could easily add or subtract flowers, just by cutting and pasting style sheets and <DIV> elements as appropriate. This can be an easy way to build up a flexible library of sheets and structures that can be used whenever the need arises without having to hire a graphic artist.
      One important note about using filters. You must always provide width and height parameters for the element or the filter call will have no effect.

Roboshop!
      My last sample was inspired to some degree by a lot of rainy day opportunities to play Forsaken and other games on the PC. The cool graphics, particularly the translucency effects, were something that I was interested in.
      After my experience with the Flowers sample, I was really having all the great fun you could have with filters. I stumbled upon a neat graphic by David Clarke of a battle robot and the rest, as they say, is history. I knew what I wanted to build visually—something reminiscent of a game screen—but I wondered how that was going to be feasible.
      It wasn't just the large-scale graphics I was thinking about either. Part of what makes the experience of a game complete is a unique typeface. But most of you know the trouble with making a Web site dependent on fonts. In the past this has meant that the user had to download and install the fonts before they could see the site in the way you intended. Let's face it, most users just aren't going to go to that kind of effort, and that means your well-crafted use of typography goes by the wayside, completely unappreciated.

Open Type Opens Possibilities
      I knew that Open Type™, a technology that allows for a font face to be downloaded for immediate use by the browser, was the perfect choice for solving this problem. The technology is still in a bit of a hardhat stage. The only way to create the .eot file, the file that is used to deliver the font to the user, is with a tool called WEFT. The Microsoft typography site documents the tool quite well, but be aware that you will have to do some tweaking to get it to work for you. At times, the tool seemed confused about which typefaces I was using in my page, and failed to properly render the fonts. Also, you should be aware that many typeface vendors will not allow their fonts to be embedded in this format. You should contact the foundry to make sure that you have the legal right to use the fonts in this manner (generally a vendor would turn off the embed bit, so WEFT wouldn't allow embedding anyway). One last proviso: the file you create will only run from the HTTP address that you provide to the tool, so you cannot just do this once and then transfer the .eot to different servers. This prevents font theft from Web pages. Still, the process is well worth it for situations where you want to provide the best possible experience for your users.
      With that out of the way, I can do a quick run through the style sheets that I used to create the Roboshop page (see Figure 7). The structure of the sheet is pretty straightforward and in some respects similar to the previous sheets I described. Notice the rule I use to call that file from the server:


 @font-face{font-family: fontname ;src:url(address);}
This is critical for linking the .eot file to your page. Once this is done, call the font family in your style sheet just as you normally would. (By the way, be sure to test out your site or page by making sure the machine you are using does not already have the font installed.) Actually, there is one little glitch when using the font-family style: you must use quotes around the name of the font, even if it does not contain white space. Normally this would not be necessary according to the CSS guidelines, but if you don't use the quotes, the font doesn't seem to get recognized.
Figure 7: Do the Funky Robot
Figure 7: Do the Funky Robot

      In this sample, I used two fonts that I thought matched the mood of the piece: Console Remix (for the title) and Flexure (for the information pane). All of the usual CSS features for font property adjustment were available to me, so I had total control of the look just by altering a few values. Although it could be argued that this isn't really a necessity, I think the fonts are more than just window dressing. The shape of the fonts really makes the program—a more common typeface would just not cut it. True, this could have been rendered as a graphic, but that would defeat the intent of making the page lightweight enough for anyone to be able to view, even on a slow connection. With all of these dependencies, the full page should only take nine seconds or less on a 28.8 Kbps connection, including the download of the fonts. Clearly in a larger-scale real-world situation where there would be many such pages to produce, executing this sort of design as straight graphics would not be feasible.

Making the Pane Painlessly
      Part of the effect that I was after in the video-game look was the use of translucent panes. You usually see these in areas where text instructions go, as in the setup for choosing a character to assume in a game. Normally, you would have to create a separate graphic by making a gradient and layering this onto whatever background graphic you need it to match.
      There are a few problems creating translucent panes on your Web page. You are going to have a tough time matching this gradient to the background without making the whole thing a single graphic. In fact, the only way I could make it work would still involve positioning. You would have to make up the gradient area and merge it on top of a graphic that matches the background pattern. You would then need to place this on your page and match the position of the gradient graphic and the background. This would create a much larger graphic file and lessen your flexibility, because any change in position for that graphic where it overlaps other elements would mean having to redo the whole shebang.
      The filter tricks I learned in the previous example helped me understand how to make this particular effect work. In addition to the Chroma filter, I learned how to use the Alpha, Glow, and Mask filters to create the effect I was after. The best part is that from a bandwidth standpoint, it's nearly free—just a few bytes.
      The Glow filter


 filter: glow (Color="color value", Strength="0-100");
creates a halo effect around any element you want, with intensity varying from 0 to 100. This effect can be extremely subtle, as in the low intensity glow I placed around the Roboshop! title. This helped further separate the type from the background. I used a much higher intensity glow around the figure of the robot itself to make it pop off the page. The great thing about doing this as a filter as opposed to a graphic was that I could tweak the values for the glow in relation to the page as a whole and not just the graphic of the robot in isolation. I could also alter the color of the glow to match the background. I made changes to the tile pattern I had originally chosen, so I didn't even have to go back in and recomposite the page manually.
      The translucent effect in the pane and color ramp were created by using the Alpha filter

 filter: Alpha(Opacity=n, FinishOpacity=n, Style=n StartX=n, StartY=n, FinishX=n,
 	    FinishY=n);
as you can see in the classes glowBack and glowBack2. I created two ramps so I could place a subtle one under the figure of the robot, and use a bolder one under the information pane. This helps make the robot appear to be part of the pane, without putting it into a box shape. Without this effect, the robot just seemed to be hanging in space.
      The only way to get that effect to work was to merge the two ramps (one was much wider than the other) by using positioning. The effect of the two <DIV> elements with filters was additive so that the greatest area of intensity ended up under the information pane.
      In addition to the glow around the robot itself, I used another filter, Mask

 filter:Mask (Color="color value");
to help extend the glow into the background of the figure (see class .robotMask). The mask created a negative image of the figure to which I could assign any color. I then used an Alpha filter with a differently shaped oval as opposed to the linear ramp I used previously (the choices are linear, oval, and rectangle, indicated by 1, 2, and 3 respectively in the style parameter). This created a subtle glow in the negative spaces of the figure that made it tie in visually with the ramps I had already created.
      The fact that all of this was accomplished without graphics meant that I had more time to tweak and tune the look of the page without having to go back and forth between packages. Working directly in the page allowed me to truly see the final product, which helped eliminate any second guessing I'd otherwise have done. You can see the code in Figure 8   test it.
      That's just a small sampling of the power that these great Internet Explorer 4.0 features can give you. I hope you enjoyed the examples and that you'll be inspired to see what you can do by playing with all of the combinations. Although there is a bit of a learning curve, in a very short period of time you will be doing things that you could not otherwise hope to do using conventional methods.

CSS2, Coming Soon to a Browser Near You
      Given that Internet Explorer 4.0 already includes many of the features outlined in the CSS2 specification and that Internet Explorer 5.0 is nearly with us, it's a good time to start looking at the specification, which is available at http://www.w3.org/TR/REC-CSS2. The most up-to-date sources on style sheet activity can be found at http://www.w3c.org/Style.
      As I mentioned earlier, Web Review maintains an excellent section on CSS. Another good source is the CSS Pointers group, http://home.att.net/%7Esjacct. There is a newsgroup dedicated to CSS, news:comp.infosystems.www.authoring.stylesheets, where you can share tips and problems. There is also a wealth of resources that you will find indispensable, especially Nadja Vol Ochs's articles, which have a strong design bent. For information on using WEFT, and for great sources on fonts, see the typography section of microsoft.com, http://www.microsoft.com/typography and http://www.microsoft.com/typography/web/embedding/weft/default.htm.

Special Thanks and Credits
Console remix font, BD Console by büro destruct, remixed by Cyclone Graphix Japan, http://www1.bermuda.ch/bureaudestruct/news.html. Flexure font by 1993 Stephen Farrell, T26, http://www.t26font.com. Robot graphic by David Clarke, represented by StockObjects.com, http://www.stockobjects.com. Map of New York, The Perry-Castañeda Library Map Collection, University of Texas Library, Austin, http://www.lib.utexas.edu/Libs/PCL/Map_collection/Map_collection.

From the September 1998 issue of Microsoft Interactive Developer.