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.
|
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 rangefilters, 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
|
{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.
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 looknot (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 mapit 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 CSSin 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 easyno 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 imagesa simple posterized effect in a quadranthas 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 |
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
|
|
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.
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. |
|
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!
Open Type Opens Possibilities
|
|
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 |
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 programa 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
|
|
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 |
|
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 |
|
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
|
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.