• Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

Chapter 2. Speech Bubbles > Graphic Effects Sans Graphics

Graphic Effects Sans Graphics

You can create very graphic-looking speech bubbles without using any actual graphics. Avoiding graphics has many benefits beyond just being able to amaze your designer friends. You benefit by saving all the time and effort spent creating, slicing, and optimizing graphics, and then redoing them when your client inevitably wants to make one small change. Your visitors benefit from the increase in page speed that comes from having less data to download and fewer HTTP requests to the server.

Note

There’s more in-depth information on the benefits of reducing images in Chapter 1, as well as a real-world case study.


Rounding the Corners

Those sharp, rectangular-cornered comments don’t look very bubble-y, do they? Let’s round the corners to start getting more of a speech-bubble look.

Rounded corners are a simple, common visual effect that used to be surprisingly hard to create in an actual web page. Creating the rounded-corner images in a graphics program was time-consuming, as was creating the actual HTML and CSS. You’d often have to add a bunch of extra nested divs to place each corner image separately, since CSS 2.1 allows only one background image per box, and the CSS used to actually control the placement of the images could get complicated. The images, along with the bloated markup and CSS, bulked up the amount that each visitor had to download, slowing down page-loading speeds. Even if you used a script to dynamically create the rounded corners instead of manually creating and applying images, you were still adding to the number of files that users had to download and decreasing your pages’ performance. All this trouble for some simple-looking little rounded corners!

Creating Ovals and Circles with border-radius

If you want your speech bubbles to be complete ovals instead of rounded rectangles, you’ll need to use elliptical-shaped corners instead of perfectly round ones. Elliptical just means that the curve of each corner is somewhat flattened out—just like an oval. To specify an elliptical corner, you write two measurements, separated by a slash, such as this: border-radius: 50px/20px. (Safari 3 and 4 use the non-standard syntax of no slash, just a space.) This means that the curve will extend horizontally 50 pixels but vertically only 20 pixels, making a flattened, elliptical curve. You can make each corner have different angles; find out how at http://css-tricks.com/snippets/css/rounded-corners.

To create circles, first give your box the same width and height; use ems as the unit of measurement instead of pixels to ensure it can grow with its text. Then set each corner’s border-radius to one-half the width/height value. For instance, if you have a box that is 10 ems wide and tall, use border-radius: 5em. See http://blog.creativityden.com/the-hidden-power-of-border-radius-2 for more examples.


In CSS3, creating rounded corners can be as simple as border-radius: 10px on a single div. No extra markup, no images, no JavaScript.

Of course, while CSS3 continues to be developed and gain browser support, it’s a little more complicated in real-world usage. But it’s still really, really easy.

In your page, modify the blockquote rule to match the following:

blockquote {
   margin: 0 0 0 112px;
   padding: 10px 15px 5px 15px;
   -moz-border-radius: 20px;
   -webkit-border-radius: 20px;
   border-radius: 20px;
   border-top: 1px solid #fff;
   background-color: #A6DADC;
   word-wrap: break-word;
}

The border-radius: 20px; declaration is the W3C standard syntax for rounded corners, specifying that all four corners should be rounded by 20 pixels. This syntax is currently supported by Opera, Chrome, Safari 5, and IE 9. Firefox and Safari 4 and earlier use the -moz-border-radius and -webkit-border-radius properties, respectively. As explained in Chapter 1, browser vendors use these browser-specific prefixes when the specification is still being worked out and they think it may change. The non-prefixed version of the property (in this case, plain border-radius) should always come last, so that when browsers do support the non-prefixed property, it overrides the earlier rules, which may use non-standard behavior from an older version of the spec.

Note

You don’t have to actually declare a border when using border-radius. If there is no border, the browser just rounds the background area.


The Lowdown on the border-radius Property

The border-radius property is part of the Backgrounds and Borders module found at www.w3.org/TR/css3-background. It’s shorthand for the properties specifying the rounding amount of each of the four corners, in this order: border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius. Mozilla’s properties for individual corners have the non-standard syntax of -moz-border-radius-topleft and so forth.

You can write out all four values, with spaces in between, in one border-radius property, or just use one value to round all four corners the same amount. Safari 4 and Safari on iOS 3 and earlier don’t allow you to specify multiple corners in the shorthand border-radius property, other than writing one value to specify all four at once.

See the “Creating ovals and circles with border-radius” sidebar for the syntax for elliptical curves on corners. Also see www.owlfolio.org/htmletc/border-radius and http://muddledramblings.com/table-of-css3-border-radius-compliance for more border-radius syntax details and examples.

Other than speech bubbles, you might want to use border-radius for:


Table 2.2. border-radius browser support
IEFirefoxOperaSafariChrome
Yes, 9+Yes with -moz-YesYes, 5+; 4+ with -webkit-Yes


With these three lines added, the corners are now rounded in all browsers except IE 8 and earlier (Figure 2.4). These versions of IE simply ignore the properties and keep the corners straight—no harm done. This is a great example of progressive enhancement, as explained in Chapter 1. Since this is a purely decorative effect, I see no harm in IE users missing it. If you do, read on.

Figure 2.4. The border-radius property applied


Note

See how I keep referring back to Chapter 1? If you skipped it, please go back and read it now. There’s some important stuff there.


Workarounds for IE

If you really must have rounded corners in IE 8 and earlier, you can use one of these scripts:

  • “PIE,” by Jason Johnston (http://css3pie.com), reads the border-radius properties that are already present in your CSS and makes them work in IE 6 and later. It also adds several other CSS3 effects to IE.

  • “curved-corner,” by Remiz Rahnas (http://code.google.com/p/curved-corner), also reads the border-radius properties out of your CSS, but works only when all four corners have the same border-radius.

  • “IE-CSS3,” by Nick Fetchak (http://fetchak.com/ie-css3), is based off of curved-corner but also adds drop shadows in IE.

  • “DD_roundies,” by Drew Diller (http://dillerdesign.com/experiment/DD_roundies), lets you round corners individually, but it doesn’t read the values from your CSS; you have to manually set the IE values separately.

Besides these IE-specific scripts, there are a number of rounded-corner scripts and image-based techniques out there that were developed before the border-radius property gained support, so you could always go back to one of these older techniques for IE. You can choose between dozens of options at www.smileycat.com/miaow/archives/000044.php and http://css-discuss.incutio.com/wiki/Rounded_Corners.

If you do use a script or images for IE, make sure to hide them from other browsers by placing the script references or IE styles within conditional comments, or by using Modernizr, both of which are explained in Chapter 1. That way, only IE users get the performance hit of using an old-school rounded-corner method, and non-IE users get the faster, pure CSS version. You’ll have to decide if the extra work and performance hit is worth having IE users see rounded instead of straight corners.

Adding the Bubble’s Tail

With rounded corners, each comment box now looks more like a bubble, but a speech bubble isn’t complete without a pointer or arrow, commonly called a “tail,” pointing to the speaker. We can add that tail without using any graphics. In fact, we can add it without using any CSS3—the technique only uses properties and selectors from CSS 2.

Creating Triangles out of Borders

All we need to create a tail is a triangle, and you can create triangles with pure CSS by using regular old borders. When two borders of a box meet at a corner, the browser draws their meeting point at an angle (Figure 2.5). If you reduce that box’s width and height to zero, and give every border a thick width and a different color, you’ll end up with the appearance of four triangles pushed together, each pointing in a different direction (Figure 2.6).

Figure 2.5. By making the top border a different color, you can see that borders meet at corners at an angle.


Figure 2.6. When a box has no width or height, each border creates the appearance of a triangle.


Here’s what the HTML and CSS used to create Figure 2.6 look like:

<div class="triangles"></div>

.triangles {
   border-color: red green blue orange;
   border-style: solid;
   border-width: 20px;
   width: 0;
   height: 0;
}

Tip

Remember, in CSS, when you have four values in a single property, like in the border-color property shown in the code here, the first value is for the top, the second for the right, the third for the bottom, and the fourth for the left. Think of going around a clock clockwise.


What would happen if you made the top, left, and bottom borders transparent instead of colored? Only the right border would show, leaving the appearance of a left-pointing triangle (Figure 2.7):

<div class="triangle-left"></div>

.triangle-left {
   border-color: transparent green transparent transparent;
   border-style: solid;
   border-width: 20px;
   width: 0;
   height: 0;
}

Figure 2.7. Making all but one of the borders transparent creates the appearance of a single triangle.


So, to sum that up, all you need to do to create a triangle using CSS is give an element zero width and height, give it thick borders, and make all but one of those borders transparent. You can vary the angle of the triangle by making the widths of the borders different on different sides.

Generating the Tail

Now that you know how to make an image-free triangle, let’s add a left-pointing triangle to the left side of each comment, pointing to the commenter’s avatar. To do this, we could nest a span or div inside each comment, and then transform this element into our triangle, but let’s leave the HTML pristine and use CSS-generated content to make the element we need appear.

Generated content is a CSS 2.1 technique where you place content into your CSS to have it appear in your HTML. It’s useful for adding things that you don’t want to manually hard-code into the HTML, like numbers before headings or icons after links. It shouldn’t be used for essential content that would be missed if the user couldn’t access the CSS file.

To create generated content, you need to specify where the content is to be inserted, using either the ::before or ::after pseudo-elements (also written as :before and :after), and specify what content to insert, using the content property.

What’s with the Double Colons?

You may have noticed that I wrote the ::before and ::after pseudo-elements with double colons instead of the single colons you may be used to seeing. No, it’s not a typo. CSS3 changed the syntax for pseudo-elements to use double colons, while pseudo-classes retain the single colons.

You can continue to use the single colon versions if you wish; they still work just fine. In fact, since IE 8 and earlier don’t support the double-colon versions, we’ll stick with the single colon versions in this book. You could also use both as a grouped selector, such as .caption:before, .caption::before { content: "Figure: ";}.


For instance, to insert the word “Figure” before every image caption on your page, you could use the following CSS:

.caption:before {
   content: "Figure: ";
}

This CSS would turn the HTML <p class="caption">Isn't my cat cute?</p> into this text when seen on the page:

Figure: Isn’t my cat cute?

In the case of the speech-bubble tail we want to generate, all we want to see are the borders of the generated content, not the content itself. So, let’s generate a piece of invisible content: a non-breaking space.

Tip

Another useful tool is the Unicode Code Converter at http://rishida.net/tools/conversion, where you can put in the character or its HTML entity name and convert it into a bunch of different formats, including its hexadecimal code point.


The HTML entity for a non-breaking space is &nbsp;, but you can’t use HTML entities within the content property. Instead, you need to use the hexadecimal part of the character’s Unicode code point (or reference). That may sound really confusing and difficult and science-y, but don’t be scared—there are lots of handy charts online that allow you to look up this kind of stuff.

For instance, at www.digitalmediaminute.com/reference/entity you can see 252 little boxes, each showing one of the allowed entities in (X)HTML. In the “Filter entities by keyword” box, type “non-breaking space.” 251 of the boxes will disappear, leaving you with one box showing &nbsp;, the HTML entity name. Position your cursor over the box (Figure 2.8). Two other codes will appear: its numerical code (in this case, &#160;) and its Unicode code (u00A0). You just want the hexadecimal part of the Unicode code, which is the part after the “u.” Copy the text “00A0” onto your clipboard.

Figure 2.8. Use the XHTML Character Entity Reference to look up the Unicode code points of various entities.
www.digitalmediaminute.com/reference/entity


Now we’re almost there; but even though we now have the Unicode code we need, we can’t put it straight into the content property, like so:

blockquote:after {
   content:"00A0";
}

Note

Unicode code points are often written with a prefix of “U+” instead of just “u.” In either of these cases, the part you want to include in the content property is just the four-digit hexadecimal part that comes after the prefix.


If we did this, the browser would quite logically make the text “00A0” show up, instead of the non-breaking space. To tell the browser that we’re putting in a special character code, we need to escape the code. If you’re a programmer, you’ll be familiar with this term, but for the rest of us, all it means is that you have to put a backslash in front of the code. This alerts the browser that what follows the slash is not to be taken as literal text, but is instead a code for something else.

With the backslash, we finally have all the correct characters and punctuation needed to insert a simple non-breaking space:

blockquote:after {
   content:"\00A0";
}

Once you do this, the page will look exactly the same; the non-breaking space is invisible, of course. Let’s add the borders around it to make it show up. We also need to set its width and height to zero and make it display as a block element so we can move it around to place the tail against the side of the speech bubble:

blockquote:after {
   content: "\00a0";
   display: block;
   width: 0;
   height: 0;
   border-width: 10px 20px 10px 0;
   border-style: solid;
   border-color: transparent #000 transparent transparent;
}

Note

The :before pseudo-element would have worked just as well as :after in this case. We’re going to be moving it from its default position regardless, as you’ll soon see.


If we had made all four borders the same width, we’d end up with a rather fat triangle, like the one shown in Figure 2.7. To make the triangle a little longer and thinner, we’ve set the top and bottom borders to only 10 pixels, and the left border is nonexistent at zero pixels. The right border—the one we use to create the appearance of a left-pointing triangle—is a nice, wide 20 pixels. All the borders except the right one are transparent; here I’ve set the right border’s color to black temporarily just so we can see it in order to place it correctly (Figure 2.9).

Figure 2.9. The black right border creates the appearance of a left-pointing triangle.


The triangle is currently placed right after the blockquote’s content—not the right spot for a speech bubble’s tail. You can correct this by moving it with absolute positioning. First, add position: relative; to the blockquote rule; this establishes it as the reference point for the absolute element’s positioning:

blockquote {
   position: relative;
   margin: 0 0 0 112px;
   padding: 10px 15px 5px 15px;
   -moz-border-radius: 20px;
   -webkit-border-radius: 20px;
   border-radius: 20px;
   border-top: 1px solid #fff;
   background-color: #A6DADC;
   word-wrap: break-word;
}

Then, add the absolute positioning to the generated content, along with top and left values:

blockquote:after {
   content: "\00a0";
   display: block;
   position: absolute;
   top: 20px;
   left: -20px;
   width: 0;
   height: 0;
   border-width: 10px 20px 10px 0;
   border-style: solid;
   border-color: transparent #000 transparent transparent;
}

You can set the top value to whatever you want; just make sure it’s equal to or greater than the border-radius value so it lands on the straight edge of the box, below the corner curve. The left value should be a negative value in order to pull the triangle to the left, and it should match the width of the triangle. In this case, the width of the triangle is 20 pixels, because that’s the width of the right border, so we’re using a left value of –20px. This places the triangle right up against the left edge of the comment box (Figure 2.10).

Figure 2.10. Absolute positioning places the triangle where we want it.


It’s possible that a comment might be so short that the tail hangs off the bottom, as seen in the second comment in Figure 2.10. To fix this, add min-height: 42px; to the blockquote rule.

blockquote {
   position: relative;
   min-height: 42px;
   margin: 0 0 0 112px;
   padding: 10px 15px 5px 15px;
   -moz-border-radius: 20px;
   -webkit-border-radius: 20px;
   border-radius: 20px;
   border-top: 1px solid #fff;
   background-color: #A6DADC;
   word-wrap: break-word;
}

Now that the triangle isn’t layered over the blockquote, we can change its color to match the blockquote:

blockquote:after {
   content: "\00a0";
   display: block;
   position: absolute;
   top: 20px;
   left: -20px;
   width: 0;
   height: 0;
   border-1width: 10px 20px 10px 0;
   border-style: solid;
   border-color: transparent #A6DADC transparent
                 transparent;
}

Note

The page with all the changes to this point is named speech-bubble_1.html in the exercise files that you downloaded for this chapter.


This creates a seamless appearance between the bubble and the tail parts of each speech bubble (Figure 2.11).

Figure 2.11. Each tail is now colored and placed correctly.


Workarounds for IE

Our tail shows up fine in IE 8 and later versions, but IE 7 and earlier versions don’t support generated content, so they don’t see the tail. I think this is fine in this case, as there’s no reason users of those browsers would see the plain rectangles and think, “Hey wait a second! Why isn’t there a little triangle sticking out of each comment block?”

To add tails in IE 7 and earlier, you’d need to manually add another element to the HTML of each comment, such as an empty span, and turn this element into the triangle.

Semitransparent Backgrounds with RGBA or HSLA

There’s nothing more that we have to do to create the appearance of a speech bubble—we’ve got the rounded corners and the tail—but it would be nice to add a little more depth and visual richness with some extra graphic details.

One great way to add depth is to make backgrounds semitransparent (also called alpha transparency). By letting a little bit of the page background show through, you create more of a layered appearance, as if the semitransparent element is floating over the background. I think this look is especially well-suited to speech bubbles, because, well, they’re bubbles—light and airy.

Before CSS3, you could create semitransparent backgrounds using an alpha-transparent PNG as a tiling background image. Using a background image has the disadvantage of adding another hit to your server, making pages load a little slower for your users. Performance is impacted even more if you need to support IE 6, since it needs a script to be able to understand alpha-transparent PNGs. Plus, you can’t use a background image on a border, so you wouldn’t be able to make the speech bubble’s tail semitransparent. It would look pretty weird for the body of the bubble to be semitransparent and the tail to be totally opaque.

CSS3’S RGBA and HSLA Syntax

Luckily, in CSS3 we have both RGBA and HSLA to turn to. Both are methods for specifying a color and its level of transparency at the same time. RGBA stands for red-green-blue-alpha (for alpha transparency) and HSLA stands for hue-saturation-lightness-alpha.

We could specify the shade of blue that we’re using as the speech bubble’s background using any of these syntaxes:

  • Hexadecimal: #A6DADC

  • RGB: 166, 218, 220

  • RGBA: 166, 218, 220, 1

  • HSL: 182, 44%, 76%

  • HSLA: 182, 44%, 76%, 1

They all get us to the same exact color, just through different routes. It’s a “you say toe-may-toe, I say toe-mah-toe” sort of thing.

In the RGBA syntax, the first three values are the amounts of red, green, and blue, either from 0–255 or 0%–100%. (You’ll most often see the 0–255 values, not the percentages.) In the HSLA syntax, the first three values are the hue value, from 0 to 360; the percentage level of saturation; and the percentage level of lightness. In both RGBA and HSLA, the fourth value is the opacity level, from 0 (completely transparent) to 1 (completely opaque).

Note

CSS3 also has an opacity property, but it makes the entire element semitransparent, including its content, instead of just the background.


You can use most graphic editors to determine the correct red, green, and blue values needed to create your chosen color. Use the color picker to choose a color, and in the color dialog box or picker window, most graphic editors will tell you that color’s hexadecimal code as well as RGB values (Figure 2.12). Finding HSL values can be a little trickier, as not all image-editing software uses HSL; for instance, Photoshop uses HSB (also called HSV), which is similar, but not quite the same. If you’re on a Mac running Snow Leopard, check out the free app Colors by Matt Patenaude (http://mattpatenaude.com), which lets you pick colors from anywhere on your screen and can display values in HSLA as well as other syntaxes. If you’re not on a Mac, I recommend you use one of the online HSL color picker or converter tools (see the “Online color tools” sidebar).

Figure 2.12. Photoshop’s Color Picker dialog box shows the equivalent RGB values for the chosen hex color.


Online Color Tools

There are many free web-based color picker and converter tools that you can find through Googling, but here are a couple that are particularly handy for working with RGB and HSL values:


Some browser-based color pickers make finding HSL or RGB values even easier and faster. I’m a big fan of the Rainbow extension for Firefox (https://addons.mozilla.org/en-US/firefox/addon/14328). After you install the extension, you can tell it which syntax to use to display color values (Figure 2.13). Then, when you use its Inspector tool to choose colors from a web page, it gives you the option to automatically copy those values to your clipboard (Figure 2.14), and you can then easily paste them into your CSS. Note that, as of this writing, the extension doesn’t include the “A” part of either RGBA or HSLA, so you’ll have to add that part in by hand. But I think you can handle all that typing.

Figure 2.13. In the options for the Rainbow extension, set the “Display color values in” option to “Hsl.”


Figure 2.14. Using Rainbow’s Inspector tool, you can click on a color to display and copy its color code.


RGBA versus HSLA

The main reason I recommend the Rainbow Firefox extension over some other color picker extensions is that many others don’t include HSL values, while Rainbow does, and I prefer HSLA over RGBA.

I’m in the minority here. Many more people use RGBA than HSLA, but I think that’s mainly because most people haven’t heard of HSLA. It’s a shame, because the majority of people who use HSLA find it more intuitive.

With RGB and RGBA values, it’s hard to tell at a glance what the color is going to be. If you take a minute to study a whole RGB or RGBA value, such as rgb(166,218,220), you can get a fair idea of the resulting color, based on which of the three component color values (red, green, or blue) are highest. But I’m not a big fan of taking that minute to parse it out while I’m trolling through my style sheet trying to track down where some mysterious color is coming from. And even after I determine that an RGB value is producing a greenish-blue hue, for instance, it’s hard to tell how muted or dark that greenish-blue is by looking at only its red, green, and blue values.

HSL and HSLA Hue Values Cheat Sheet

If you’re going to use HSLA, it’s helpful to memorize the hue values of a few key colors (or at least approximately where they are between 0 and 360, so you can tweak your way to the shade you want).

  • 0 or 360 = red

  • 30 = orange

  • 60 = yellow

  • 120 = green

  • 180 = cyan

  • 240 = blue

  • 270 = purple

  • 300 = magenta

To get black in HSL and HSLA, just set the lightness value to zero percent. For white, set the lightness value to 100 percent. In both cases, the hue and saturation values can be whatever you want.

To get gray in HSL and HSLA, just set the saturation value to zero percent. The lightness value will control the shade of the gray, and the hue value is irrelevant.


Another problem with RGB and RGBA is that if you want to tweak a color—make it a little darker or brighter or greener—you have to guess at how to change each of the values to get to the hue you want. In web design, it’s common to use multiple shades of the same hue in different places in the page, such as a brightened version of a color on the current tab in a nav bar. But with RGB, different shades of the same hue don’t necessarily have very similar color values. For instance, a just slightly darker version of the shade of blue we’ve been working with would have an RGB value of 155, 209, 211 instead of the original 166, 218, 220. All three numbers have to change to produce a very slight shift in darkness.

With HSL and HSLA, you don’t have to add amounts of red, green, and blue to get a specific hue, but instead set that hue as one specific number. All you have to do is remember that both 0 and 360 equal the same shade of pure red. As you increase the hue value from 0, you simply move through the rainbow from red to purple and then back around to red again, as if you were going around a color wheel (Figure 2.15).

Figure 2.15. The 360 hue values in the HSL color syntax


The Lowdown on RGBA and HSLA

RGBA and HSLA are part of the Color module found at www.w3.org/TR/css3-color. Both allow you to set a color and its level of transparency at the same time.

In the RGBA syntax, the first three values are the amounts of red, green, and blue, either from 0–255 or 0%–100%. In the HSLA syntax, the first three values are the hue value from 0 to 360, the percentage level of saturation, and the percentage level of lightness. In both RGBA and HSLA, the fourth value is the opacity level from 0 (completely transparent) to 1 (completely opaque).

Other than ghostly bubble backgrounds, you might want to use RGBA or HSLA for:


Table 2.3. RGBA and HSLA browser support
IEFirefoxOperaSafariChrome
Yes, 9+YesYesYesYes


Once you have the hue you want, you can then adjust its saturation if you want it duller or brighter, or adjust its lightness if you want it darker or lighter. It’s easy to get multiple shades of the same color, or to tweak the color’s hue just a little bit in one direction. Once you’ve worked with HSLA for a while and are more familiar with what each hue value computes out to, it’s easier to tell at a glance what color you’re going to get when you’re glancing through the HSLA values in your style sheets.

The bottom line is this: RGBA and HSLA both have the same browser support and produce the same colors. I’m using HSLA throughout this book because it’s more intuitive to me, but if you find RGBA easier, it’s perfectly fine to use it instead.

Creating Semitransparent Speech Bubbles

Now that we’ve gotten all that syntax out of the way, we can switch the speech bubbles’ background color from hexadecimal to HSLA notation and make them semitransparent.

The speech bubbles’ background color is currently set to #A6DADC. We can figure out the HSLA equivalent using the Rainbow extension. Just open your speech-bubble page in Firefox, and use the Rainbow Inspector to click on the speech bubble background color. It will show you that the HSL value is hsl(182, 44%, 76%). Copy this value, go back to your code editor, and paste it over the current hexadecimal background color:

blockquote {
   position: relative;
   min-height: 40px;
   margin: 0 0 0 112px;
   padding: 10px 15px 5px 15px;
   -moz-border-radius: 20px;
   -webkit-border-radius: 20px;
   border-radius: 20px;
   border-top: 1px solid #fff;
   background-color: hsl(182,44%,76%);
   word-wrap: break-word;
}

Note

Having spaces after the commas between the three HSL values is completely optional—it works the same way with or without spaces. (I took them out.)


If you save and refresh the page after this change, it will look exactly the same. You haven’t changed the color yet—just changed the syntax for specifying it.

Now we’ll modify this new syntax to make the speech bubbles semitransparent. Change background-color: hsl(182,44%,76%); to background-color: hsla(182, 44%,76%,.5); . Make sure to add the “a” of “hsla”!

Note

I’ve written the alpha value as “.5,” but “0.5” is also perfectly fine.


You also want to change the tail to match. Copy and paste the HSLA value over the hexadecimal value in the border-color declaration:

blockquote:after {
   content: "\00a0";
   display: block;
   position: absolute;
   top: 20px;
   left: -20px;
   width: 0;
   height: 0;
   border-width: 10px 20px 10px 0;
   border-style: solid;
   border-color: transparent hsla(182,44%,76%,.5)
                 transparent transparent;
}

Save and refresh the page in your browser. You can now see the page background pattern showing through the speech bubbles slightly, as well as each commenter’s avatar showing through the little bit of the tail that overlaps each picture (Figure 2.16).

Figure 2.16. Each speech bubble’s background is the same shade of blue, but now semitransparent.


Workarounds for IE

You have a few options for working around the lack of HSLA/RGBA support in IE 8 and earlier.

  • Provide a replacement solid background color (in hexadecimal, RGB, or HSL syntax). If you declare the solid background color before the HSLA/RGBA version, using the background shorthand property on either both the colors or just the HSLA/RGBA one, IE 8 and earlier will use it and correctly ignore the HSLA/RGBA one. But if you use the background-color property instead of background to declare the HSLA/RGBA color, IE 7 and 6 won’t use the solid color; they try to apply the HSLA/RGBA color and can’t, so they display no color at all. In some pages, where the text is still readable even without a background color behind it, this would be acceptable. In those cases where it’s not, and where you can’t use the background shorthand property, you would need to feed IE 7 and earlier the solid background color in a rule that only IE can read. See Chapter 1 for your IE-feeding options.

    Tip

    You can use server-side programming to generate the PNGs for you. See http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds for a PHP script that generates them based on the RGBA values in your CSS.


  • Tile a tiny semitransparent PNG image as the background image. This has the advantage over the first option of actually making the background semitransparent, instead of opaque. It works in IE 8 and 7, but not IE 6 and earlier, since those versions don’t support alpha-transparent PNGs. To work around this, you could use IE’s AlphaImageLoader filter (or one of the many IE transparency scripts that makes use of the filter), feed IE 6 a solid background color, or feed IE 6 a GIF or PNG8 image. But all of this is a lot of extra work and could have a big impact on the performance of your pages—the AlphaImageLoader filter is horribly slow and an image is another HTTP request. (Plus, in our case, we couldn’t use it on the speech bubbles’ tails, since they are just borders and don’t have background images.) I don’t recommend using a PNG background image unless you don’t need to worry about IE 6 and thus won’t be providing any workarounds for its lack of alpha-transparent PNG support.

    Note

    The PIE script mentioned earlier can also be used to make RGBA work in IE, but only in limited contexts. See http://css3pie.com/documentation/supported-css3-features for more information.


  • Use IE’s Gradient filter, which works since version 5.5, and allows semitransparent colors (using its own proprietary syntax, of course). Just set both the starting and ending colors to the same color so you don’t create the appearance of a gradient.

I recommend either the first or third option. The third more closely resembles the appearance we’re going for, since the background will be semitransparent instead of solid. However, it’s worth noting that the Gradient filter can do strange things to the anti-aliasing of the element’s text and make it look a little uneven (peek ahead at Figure 2.17). You’ll have to decide if the less pretty text is worth the more pretty background. Also, adding the filter will make the generated content tail disappear in IE 8 (it never appeared in 7 and 6 to begin with). I can’t give you any explanation for this—it’s just one of those weird IE bugs.

Figure 2.17. Before (top) and after (bottom) the Gradient filter is applied in IE 8. With the filter, the background color is semitransparent, but the anti-aliasing of the text is now a little uneven-looking.


In this case, I say let’s go for the semitransparent background using the filter. Since we don’t have rounded corners in IE to create the speech-bubble appearance, I don’t mind losing the speech bubble’s tail.

We could add the filter right inside the blockquote rule—non-IE browsers will just ignore it—but as discussed in Chapter 1, it’s always nice to keep hacks and workaround separate from the standard rules. To keep the filters separate, we should either create a separate IE sheet, or use the conditional comments html tag trick described in Chapter 1. Let’s use the html tag trick.

Go to the opening html tag of the page, and change it to the following HTML:

<!--[if lt IE 7]><html lang="en" class="ie6"><![endif]-->
<!--[if IE 7]><html lang="en" class="ie7"><![endif]-->
<!--[if IE 8]><html lang="en" class="ie8"><![endif]-->
<!--[if IE 9]><html lang="en" class="ie9"><![endif]-->
<!--[if gt IE 9]><html lang="en"><![endif]-->
<!--[if !IE]>--><html lang="en"><!--<![endif]-->

Tip

If you don’t want to type all this by hand (I don’t blame you), open speech-bubble_final.html from this chapter’s exercise files, and copy and paste it from there.


Now we can create one rule for IE 5.5, 6 and 7, and another rule for IE 8, since its filter syntax is a little different than that used in earlier versions of IE. Add the IE 7 and earlier rule first:

.ie6 blockquote, .ie7 blockquote {
   background: none;
   filter: progid:DXImageTransform.Microsoft.gradient
      (startColorstr=#99A6DADC, endColorstr=#99A6DADC);
   zoom: 1;
}

Note

The line breaks in the filter value are there just to make it easier to read. You can add or remove line breaks within it without affecting how the code functions.


The Gradient filter simply declares a starting and ending color, both the same. The color values look strange, though, don’t they? They’re not your standard six-digit hexadecimal codes. The first two digits are the alpha transparency value. You can use any hexadecimal value between 00 and FF, with 00 being transparent and FF being opaque. The last six digits are the standard hexadecimal code for a color. So, the color #99A6DADC sets the alpha transparency to 99, the hexadecimal equivalent of the .6 level of transparency we’re using in HSLA, and the color to A6DADC, the same blue we’ve been using all along.

In addition to applying the filter, this IE 7 and earlier rule removes the background color, which would override the filter. Also, IE 6 and earlier need to have hasLayout triggered on the blockquotes to make the filter work, which zoom: 1; accomplishes.

Note

Understanding hasLayout is important when working with IE. If you need a refresher on this strange “property,” see Ingo Chao’s article “On having layout” at www.satzansatz.de/cssd/onhavinglayout.html.


Converting HSLA and RGBA to IE’s Gradient Filter

To use the exact same level of transparency in the IE filter as the HSLA notation, you need to multiply the level of HSLA transparency value, .6 in this case, with 255, and then convert this into hex. Robert Nyman explains how to do this at http://robertnyman.com/2010/01/11/css-background-transparency-without-affecting-child-elements-through-rgba-and-filters.

A much easier way to do this is to use Michael Bester’s “RGBa & HSLa CSS Generator for Internet Explorer” at http://kimili.com/journal/rgba-hsla-css-generator-for-internet-explorer. Put in an RGBA or HSLA value and it will automatically convert it to the Gradient filter equivalent.


IE 8 doesn’t need the background color removed, as it correctly ignores the HSLA background color on the main blockquote rule. It also doesn’t need hasLayout triggered. But, it does have a slightly different syntax for filter properties. Add the following rule for IE 8:

.ie8 blockquote {
   -ms-filter: "progid:DXImageTransform.Microsoft.gradient
   (startColorstr=#99A6DADC, endColorstr=#99A6DADC)";
}

The differences in the filter syntax are that it’s called -ms-filter instead of filter, and the value of the -ms-filter property is put in quotation marks. This syntax is more in line with the CSS specifications and how other browsers designate their proprietary properties.

Image-free Gradients

We can enhance the speech bubbles’ backgrounds even further by giving each a subtle gradient to make them appear more rounded and three-dimensional. CSS3 allows you to create gradients without images, speeding up your development time and decreasing page-loading times, just as our image-free rounded corners can do. CSS-generated gradients also have the advantage of being able to scale with their containers in ways that image gradients can’t, making them more versatile.

Unfortunately, CSS3 gradients are still very much in development at the time of this writing; their syntax is laid out only in a W3C editor’s draft, not a more finalized working draft or candidate recommendation. Thus, be aware that the syntax for gradients is more likely to change than most of the CSS I’ll describe in this book. Still, I think it’s fine to add CSS that is a little experimental if you’re using it in a very limited manner; non-supporting browsers won’t be harmed by its lack, and supporting browsers won’t be harmed if the syntax later changes. The (unlikely) worst-case scenario is that the syntax will totally change, making the gradients fail to appear in all browsers. I think I can live with this.

You can create both linear (straight) gradients and radial (circular or elliptical) gradients; we’re just going to focus on linear gradients here. There is no gradient property; you specify a gradient using the linear-gradient or radial-gradient function as the value for any property that allows an image value, such as background-image and list-style image (though Firefox currently supports it only on background-image). When you specify a linear gradient, you tell the browser its starting point, angle, and starting and ending colors. You can also add extra colors in between the starting and ending colors and specify the exact position of each color along the line of the gradient.

This sounds simple enough, but unfortunately, Firefox and Webkit (the only browsers that currently support gradients) differ on the syntax required to feed the browser this information; Firefox matches the official W3C syntax, and Webkit uses a very different (and more complicated) syntax that they developed first. Not only that, but even within each single syntax there are many variations on how you can specify the same gradient. It can get pretty confusing. To start off simply, let’s first apply a simple linear gradient to the speech bubbles to see a real example, before diving into the details of the full syntax.

The Firefox and W3C Syntax

Firefox’s syntax matches the official syntax being developed by the W3C and is generally easier to understand and use, so we’ll start with the gradient for Firefox.

First, add a linear gradient for Firefox in the background-image property of the blockquote rule, using the -moz-linear-gradient function:

blockquote {
   position: relative;
   min-height: 40px;
   margin: 0 0 0 112px;
   padding: 10px 15px 5px 15px;
   -moz-border-radius: 20px;
   -webkit-border-radius: 20px;
   border-radius: 20px;
   border-top: 1px solid #fff;
   background-color: hsla(182,44%,76%,.5);
   background-image: -moz-linear-gradient(
            hsla(0,0%,100%,.6),
            hsla(0,0%,100%,0) 30px
            );
            word-wrap: break-word;
}

Note

The line breaks in this gradient function are there just to make it easier to read. Just like with any piece of CSS, you can add or remove line breaks within it without affecting code functionality.


This specifies a starting color (hsla(0,0%,100%,.6)), ending color (hsla(0,0%,100%,0)), and the position of the ending color (30px). Because we haven’t specified any starting point for the gradient or its angle, Firefox will simply use the default values, which makes the gradient start at the top of the box and run straight down. (If we did want to specify a starting point and/or angle, we’d do it at the start of the function. See “The lowdown on linear gradients” for the exact syntax.)

The starting color is white at 60 percent opacity, and the ending color is white at zero percent opacity (completely transparent). Laying semitransparent white over the background color creates a tint of whatever that background color is. In this case, it makes the gradient appear to be very light blue at the top and then fade away to nothing (Figure 2.18). We could have used an actual shade of light blue, but using semitransparent white in HSLA or RGBA is much more flexible. If we were to later change the color of the speech bubbles’ backgrounds to orange, for instance, we’d have to also change the light blue gradient to light orange. But since it’s white, it will always be a tint of whatever the background color is. Sticking with semitransparent white and black is the smartest way to create tints and shades of colors.

Figure 2.18. A gradient over the background makes the speech bubbles look more three-dimensional.


Right after the ending color value, there’s a space and then a value of 30px. This tells Firefox that you want it to place the ending color 30 pixels down the gradient. The gradient will run from the top of the box down 30 pixels, and then the ending color of the gradient will fill the rest of the vertical space. Since the ending color is completely transparent, it creates the appearance that the gradient covers only the top 30 pixels of the speech bubble.

That’s all you need to create the gradient in Firefox. Normally, I would tell you to copy and paste the background-image declaration and remove the -moz- bit from the second declaration to add the non-browser-specific version at the end. But in this case, the official syntax is still so early in its development that I think it’s best to leave it off and wait for it to become more finalized. We’ll stick with just the Firefox syntax, and add the Webkit syntax now.

The Webkit Syntax

For Webkit-based browsers, add another background-image declaration to the blockquote rule, this time containing the -webkit-gradient function:

blockquote {
   position: relative;
   min-height: 40px;
   margin: 0 0 0 112px;
   padding: 10px 15px 5px 15px;
   -moz-border-radius: 20px;
   -webkit-border-radius: 20px;
   border-radius: 20px;
   border-top: 1px solid #fff;
   background-color: hsla(169,41%,76%,.5);
   background-image: -moz-linear-gradient(hsla(0,0%, 100%,.6), hsla(0,0%,100%,0) 30px);
   background-image: -webkit-gradient(linear,
                     0 0, 0 30,
                     from(hsla(0,0%,100%,.6)),
                     to(hsla(0,0%,100%,0))
                     );
   word-wrap: break-word;
}

					  

As you can see, the Webkit syntax is very different—and more complicated.

Radial Gradients

We’re not covering radial gradients here, but you can learn more about them in these articles:


The Lowdown on Linear Gradients

The gradient functions are part of a draft of the Image Values module; this draft is found at http://dev.w3.org/csswg/css3-images/#gradients-, but ultimately the finalized module can be found at www.w3.org/TR/css3-images.

You specify a gradient using the linear-gradient or radial-gradient function as the value for any property that allows an image value. Figure 2.19 shows a diagram of a linear-gradient function with every possible piece of the gradient syntax included.

Figure 2.19. All the possible pieces of a linear gradient function, shown over the gradient it would produce.


You don’t need to include all of the pieces shown in Figure 2.19. The important points to remember are:

  • All you need for a gradient to work are the two colors (in any syntax). The rest of the pieces shown in Figure 2.19 are optional and just uses the default values if you leave them out.

  • If you don’t specify any positions for the colors or the gradient’s angle, the gradient will run from top to bottom.

  • You can specify the starting point for the gradient at the beginning of the function, using either keywords (like center) or numbers (like 20px or 60% or 1em), which can be negative. If you use numbers, the first value is how far across the box the gradient starts (the x-axis or horizontal starting point position) and the second value is how far down the box the gradient starts (the y-axis or vertical starting point position).

  • After the starting point (if present), you can specify the angle at which the gradient will run. The angle is measured between a horizontal line and the gradient line, going counterclockwise. For instance, 0deg produces a left-to-right gradient, 90deg goes bottom to top, 180deg goes right to left, and 270deg goes top to bottom. You can also use negative values.

  • Each color-stop includes a color (in any syntax) and, optionally, a point where that color should be placed along the gradient’s line. The value is measured from the starting point of the gradient, which may not necessarily be the edge of the box (as is the case in Figure 2.19, where the gradient starts 40 pixels down from the top edge of the box).

Since gradients placed in the background-image property are essentially browser-generated images, you can use other CSS background properties to further control them, just like you would any other background image. For instance, you can use the new CSS3 background-size property to control the gradient’s size and background-repeat to control its tiling.

Other than adding a highlight, you may want to use CSS3 gradients for:


Table 2.4. Gradients browser support
IEFirefoxOperaSafariChrome
NoYes, 3.6+, with -moz-NoYes, with -webkit-Yes, with -webkit-


First, you specify the type of gradient—linear or radial—within the -webkit-gradient function itself, instead of having separate linear-gradient and radial-gradient functions.

Next, you specify the horizontal and vertical positions of the starting point (here, 0 0), followed by the horizontal and vertical positions of the ending point (here, 0 30). You can do this using keywords (such as top and left), percentages, or pixels, but strangely, Webkit requires you to leave off the “px” if you want to use pixels. So, in this case, we’re telling Webkit that we want the gradient to start at a point zero pixels across and zero pixels down the box (the top left corner) and end at zero pixels across and 30 pixels down the box. This makes the gradient run from the top to 30 pixels down the box, and then fill the rest of the box with the ending color, just like in Firefox.

After the starting and ending points, we have the starting color and the ending color. Just like with Firefox, you can use whatever color syntax you wish, but note that you must include from and to before each color.

The result of this -webkit-gradient CSS should look the same as Figure 2.18.

The CSS syntax differences between Firefox and Webkit can be hard to remember. Luckily, you don’t have to memorize them if you don’t want to. There are some great gradient-generator tools online that allow you to use a visual editor to create the gradient, and then they write the corresponding CSS you need to use. Just copy and paste! Find these gradient generators at http://gradients.glrzad.com, http://westciv.com/tools/gradients, http://westciv.com/tools/radialgradients, and www.display-inline.fr/projects/css-gradient.

Workarounds for Non-supporting Browsers

The CSS we’ve used so far works only in Safari, Chrome, and Firefox 3.6 and later, making gradients one of the less-supported features of CSS3. However, it’s one of the easiest features to provide workarounds for non-supporting browsers. (If you even choose to provide a workaround, that is—letting non-supporting browsers see the solid background color is an acceptable fallback in most cases.)

Picture it. The most obvious workaround for non-supporting browsers is to just go back to the good old-fashioned way of creating gradients: create an actual image gradient as an alpha-transparent PNG, set it as the background image on the blockquote, and tile it horizontally. Just make sure to declare this image before the two background-image declarations that contain the -moz-linear-gradient and -webkit-gradient functions. This allows browsers that do support gradients to override the first background-image property that uses an image with the later background-image property that creates a CSS3 gradient.

Of course, creating and using an image negates the efficiency benefits of using CSS3 to generate gradients for you. Firefox 3.6 won’t load the image that it doesn’t need, but Safari and Chrome will, even though they use the CSS3 gradient and never show the image. So, you keep the performance advantage of CSS3 gradients in Firefox 3.6, but lose it in Safari. Granted, you still get the other advantages of CSS3 gradients over image gradients, but the performance benefit is one of the most important.

More Details on the Webkit Linear Gradient Syntax

In a Webkit linear gradient, if you want to include any extra colors between the starting and ending colors, you’d use syntax like color-stop(50%, #333). In this example, 50% specifies how far along the gradient you want the color to appear; it can also be written as a number between 0 and 1. #333 is the color value, written in any syntax you like. The color-stop can be written between the starting and ending colors or after them, with each color-stop separated by commas.

For even more details on the Webkit syntax, see these articles:


Because of this performance hit in Webkit-based browsers, I recommend you either forgo the background image fallback, letting non-supporting browsers just miss out on the gradient, or hide the background image fallback from gradient-supporting browsers by using Modernizr (explained in Chapter 1). Of course, if you’re going to go to all the trouble of creating and applying a gradient image, you may decide it’s best to just use the image for all browsers and not use CSS3 gradients at all. There’s no right answer here, but my recommendation is to either use CSS3 gradients exclusively, or don’t use them at all and stick with images.

Tip

Another way to fake a gradient is to use an inset box-shadow, which has more browser support than CSS3 gradients (but not as much as plain old background images, of course). I’ll go over the box-shadow property further down in this chapter.


Use a script. For IE 6 through 8, you can use PIE (http://css3pie.com/documentation/supported-css3-features). For other browsers, check out Weston Ruter’s css-gradients-via-canvas script (http://weston.ruter.net/projects/css-gradients-via-canvas). It works in browsers that support the HTML5 canvas element, so it makes gradients possible in Firefox 2 and 3 as well as Opera 9.64 and later. It doesn’t work in IE, but you could use it in combination with IE’s Gradient filter. Which leads us nicely to the next workaround...

Change color values for a different effect. We’re already using IE’s Gradient filter to create single-color semitransparent backgrounds on the blockquotes. We can modify the starting color values to be a lighter shade of blue to simulate the CSS3 gradient that we’re using.

In both IE rules, change the starting color in the Gradient filter from #99A6DADC to #99E3F4EE:

.ie6 blockquote, .ie7 blockquote {
   background: none;
   filter: progid:DXImageTransform.Microsoft.gradient
      (startColorstr=#99E3F4EE, endColorstr=#99A6DADC);
      zoom: 1;
}
.ie8 blockquote {
   -ms-filter: "progid:DXImageTransform.Microsoft.gradient
      (startColorstr=#99E3F4EE, endColorstr=#99A6DADC)";
}

By default, IE gradients run from top to bottom, so the resulting gradients in IE look reasonably similar to the ones in Firefox and Webkit-based browsers (Figure 2.20). We can’t control the placement of the color stops in IE like we can with CSS3 gradients, but the filter works well for simple, two-color, linear gradients. It works only in IE 8 and earlier, though; IE 9 doesn’t support Microsoft filters. Thus, no gradient shows in IE 9, but at least IE 9 shows the semitransparent background color.

Figure 2.20. IE’s Gradient filter can simulate simple CSS3 gradients (shown here in IE 8).


Tip

Find out more about IE’s Gradient filter at http://msdn.microsoft.com/en-us/library/ms532997(VS.85).aspx.


Note that if you have a fallback background image declared for other browsers, IE will let it override the Gradient filter. The IE 7 and earlier rule already removes any background that might be present, but the IE 8 rule doesn’t. Remember to add background: none; to the IE 8 rule if you add a background image to the main blockquote rule (because you’re adding a gradient image fallback, for instance).

Note

The page with all the changes to this point is named speech-bubble_2.html in the exercise files that you downloaded for this chapter.


Image-free Drop Shadows

In our continuing quest for three-dimensionality, we can add a drop shadow behind each speech bubble. Once again, we’ll do it without images.

Drop shadows on boxes are created in CSS3 using the box-shadow property. In the property, you set the shadow’s horizontal and vertical offsets from the box, its color, and you can optionally set blur radius as well as spread radius.

Add the following three lines of CSS to the blockquote rule:

-moz-box-shadow: 1px 1px 2px hsla(0,0%,0%,.3);
-webkit-box-shadow: 1px 1px 2px hsla(0,0%,0%,.3);
box-shadow: 1px 1px 2px hsla(0,0%,0%,.3);

Just as with border-radius, all three lines accomplish the same thing, but are read by different browsers; the non-prefixed box-shadow property will work only in IE 9 and Opera at the time of this writing.

The first value in each property, 1px, is the horizontal offset from the box, and it tells the browser to move the shadow one pixel to the right of the box’s edge. The second value, 1px, is the vertical offset, moving the shadow one pixel down. You can use negative values to move the shadow to the left and up instead.

The third value, 2px, is the blur radius, which specifies over how many pixels the shadow should stretch. A larger value makes the shadow blurrier and softer; a value of zero would make it completely sharp-edged.

Note

The number values in the box-shadow property have to be specified in the exact order shown, but you don’t have to put the color value at the end. You can put the color value first if you want.


The fourth value is the color—in this case, black at 30 percent opacity. You can use any syntax for declaring the color in box-shadow, but HSLA or RGBA—the only syntaxes that can make a color semitransparent—are your best bets. Semitransparency is very handy for drop shadows, since you want to be able to see the background of whatever is behind the shadow peeking through a bit. If you made the shadow solid light gray, for instance, and then changed the page’s background to dark navy blue, you’d end up with a light gray shadow on top of a navy blue background. What you really want is an even darker navy blue shadow, as that’s how a shadow on something navy blue would look in real life. Using HSLA or RGBA for your drop shadows, and keeping the colors either black (for a shadow) or white (for a glow effect) allows you to switch the background color or image under the drop shadow and not have to make a corresponding change to the color of the shadow itself. It will appear to adjust its color to whatever is beneath it.

With box-shadow added to the blockquote rule, save the page, and check it out in an up-to-date browser to see the subtle greenish-gray shadow to the right and bottom of each speech bubble (Figure 2.21). You’ll notice that the shadow pays attention to the border-radius and is also rounded to match the corners.

Figure 2.21. The box-shadow property adds a shadow beneath each speech bubble.


Our drop shadow does add that extra little hint of three-dimensionality, but we can increase that 3D appearance by making the speech bubbles appear to move forward a bit when each is hovered over. The farther away the speech bubble is from the background, the larger its shadow should appear. You increase the offset of the shadow on hover by adding this rule:

blockquote:hover {
   top: -2px;
   left: -2px;
   -moz-box-shadow: 3px 3px 2px hsla(0,0%,0%,.3);
   -webkit-box-shadow: 3px 3px 2px hsla(0,0%,0%,.3);
   box-shadow: 3px 3px 2px hsla(0,0%,0%,.3);
}

Tip

For help creating more complicated shadows, use the box-shadow generator at http://westciv.com/tools/boxshadows. Unfortunately, however, it doesn’t include spread radius or inset.


The negative top and left values are what actually shift the speech bubble and create the appearance of movement, but increasing the shadow as well—from 1 pixel offset to 3 pixels offset—makes the movement look more realistic (Figure 2.22). Increasing the shadow also makes it appear more like the speech bubble is moving away from the background and closer to the user, instead of just farther up the page.

Figure 2.22. The larger shadow on hovered speech bubbles makes them appear to jump out at you a bit.


The Lowdown on the box-shadow Property

The box-shadow property is part of a draft of the Backgrounds and Borders module; this draft is found at http://dev.w3.org/csswg/css3-background/#the-box-shadow, but ultimately the finalized module can be found at www.w3.org/TR/css3-background.

In the property, you set the shadow’s horizontal and vertical offsets from the box, and you set the shadow’s color. You’ll usually also want to set a blur radius (it’s zero otherwise) and can optionally set a spread radius to expand or contract the overall width of the shadow, using positive or negative values, respectively. You can make a shadow appear inside a box instead of outside or behind it using the inset keyword, added at the start or end of the box-shadow value. (Spread radius and inset are not supported in Safari 4 and earlier, Safari on iOS 3 and earlier, or IE 9.)

You can apply multiple shadows to the same box by writing each in the same box-shadow property, separated by commas. They’ll be stacked on top of each other, with the first shadow declared on top.

Other than creating basic shadows behind boxes, you might want to use box-shadow for:


Table 2.5. box-shadow browser support
IEFirefoxOperaSafariChrome
Partial, 9+Yes with -moz-, 3.5+Yes, 10.5+Yes with -webkit-Yes with -webkit-


Workarounds for IE

The box-shadow property is not supported by IE 8 and earlier, but as with gradients, you can use IE’s filters to fake it. The DropShadow and Shadow filters are specifically designed to create drop shadows, and Glow works if you want an even glow around all sides of the box. Unfortunately, these filters don’t offer as many customization options for the drop shadow as you have with CSS3 box-shadow, as Chris Casciano demonstrates and explains in his article “CSS3 Box Shadow in Internet Explorer [Blur-Shadow]” at http://placenamehere.com/article/384/CSS3BoxShadowinInternetExplorerBlurShadow. I don’t think any of these filters will create the particular effect we want in this case.

Also in this article, Chris shows a clever technique using IE’s Blur filter instead of DropShadow, Shadow, or Glow to create a more realistic-looking drop shadow, but the technique requires making a copy of the box in the HTML, and then blurring this copy. Another article at http://dev.opera.com/articles/view/cross-browser-box-shadows uses the same technique, and also shows how to use Blur to create the appearance of an inset shadow. The extra HTML elements required in these tutorials are an acceptable compromise when you really must have a drop shadow in IE, but in the case of our speech bubbles, I don’t think the extra work and extra file size that would result from all those extra divs is worth the small visual gain. So we’re not going to walk through the steps to implement the Blur filter solution here; we’ll be satisfied with no drop shadows in IE.

Note

The PIE and IE-CSS3 scripts mentioned earlier in the chapter can also create drop shadows in IE. But with the IE-CSS3 script, the drop shadows have to be black.


Image-free Text Shadows

Why should the boxes get to have all the fun—shouldn’t text be able to have drop shadows too? Happily for us, CSS3 has a property named text-shadow that does just that.

The text-shadow property can give you a nice accessibility and usability benefit. With the graphic effects we’ve already looked at in this chapter, the CSS3 equivalent just replaces a decorative image, such as replacing a GIF of a curved corner with a CSS-generated curved corner—kind of trading an image for a faux-image. The text-shadow property, on the other hand, allows you to replace an image of text with real text. For instance, you may have a headline that you want to have a shadow behind it. Before text-shadow, you might create an image of that headline and its shadow and display that image in your page. The user has no control over text in an image to make it more readable for him or herself by scaling it, changing its color, changing the font, and any number of other things you can do to real text. Using text-shadow on real text gives control back to the user.

Using real text with text-shadow applied can also improve readability by creating more contrast between the text and its background. Have you ever watched a movie with closed captioning? The captions probably had a small shadow or outline around them to make the text stand out more on a variety of background colors. Slight drop shadows behind text in web pages can give the same readability boost.

Other advantages of real text: it’s searchable, it can be selected to copy and paste, and it’s more quickly and easily editable by you or your client than an image or Flash movie would be.

Of course, like many web techniques, text-shadow can backfire and decrease usability if not used well. I’m certainly not saying you should go out and add drop shadows to all your text; there are many cases where it would impede readability. You also always need to make sure that the text is still readable if the shadow isn’t there. But text-shadow is another tool in your arsenal that you can choose to use when appropriate.

So, text-shadow sounds great—how do you apply it?

Making Text Stand Out Using Shadows

Let’s add a text-shadow on hover to highlight the chosen comment just a bit. Add the following line to the blockquote:hover rule:

text-shadow: 1px 1px 1px hsla(0,0%,100%,.7);

Tip

Just like with box-shadow, text-shadow usually looks best when the color is semitransparent using HSLA or RGBA.


The syntax is almost exactly the same as the syntax for box-shadow. (The only difference is that you can’t set spread radius or inset on text-shadow.) We have a horizontal offset, vertical offset, optional blur radius, and color. In this case, there’s no need to add any browser-specific prefixes; Firefox, Safari, Chrome, and Opera all support the standard text-shadow property. Figure 2.23 shows the subtle shadow that appears behind the text of a blockquote that’s being hovered over.

Figure 2.23. A white shadow appears to the right and bottom of the text in the speech bubble that the user has her mouse over.


Another nice place to add a shadow behind text is the commenter’s name and date of comment. These two pieces of text are pretty small and are sitting on top of a patterned background. A very slight, sharp-edged text shadow would give it a subtle outline to make it stand out more and be a little easier to read.

Note

The page with all the changes to this point is named speech-bubble_3.html in the exercise files that you downloaded for this chapter.


Add the following line to the existing .comment-meta rule:

text-shadow: 1px 1px 0 hsla(0,0%,100%,.7);

Tip

For help creating more complicated shadows, use the text-shadow generator at http://westciv.com/tools/shadows.


The effect this produces is very subtle, but it needs to be. A thick outline around such small text would look strange and probably make it harder to read. But the slight text shadow we’re using adds just a little bit of contrast to make the text just a little bit more readable (Figure 2.24).

Figure 2.24. The sharp-edged shadow on the commenter’s name and date makes the text stand out a bit more compared to the non-shadowed text.


The Lowdown on the text-shadow Property

The text-shadow property is part of the Text module found at www.w3.org/TR/css3-text. It was part of CSS 2, removed from 2.1, and is back in 3.

In the property, you set the shadow’s color and its horizontal and vertical offsets from the text. You can also set a blur radius; the default (if you leave it out) is zero.

You can apply multiple shadows to the same text by writing each in the same text-shadow property, separated by commas. They’ll be stacked on top of each other, with the first declared shadow on the top.

Other than creating basic shadows behind text, you might want to use text-shadow for:

Also check out http://maettig.com/code/css/text-shadow.html for many examples of text-shadow effects; some are more practical than others, but all are good for jogging your creativity.


Table 2.6. text-shadow browser support
IEFirefoxOperaSafariChrome
NoYesYesYesYes


Workarounds for IE

The DropShadow, Shadow, or Glow filters for IE that I mentioned earlier can actually create shadows behind text too, not just boxes. To get a text shadow instead of a box shadow, you write the filter in the exact same way, but make sure there is no background color or background image on the element. If it has a background, IE will apply the shadow to the box; if it doesn’t have a background, it will apply the shadow to the content.

Unfortunately, when any of these filters are applied to text, they make that text very jagged. It’s similar to the unevenness of the text that showed up when we applied the gradient filter in IE (see Figures 2.17 and 2.20), but more extreme. In the case of our speech bubbles, I think it really impairs the readability, and the whole point of adding text-shadow here was to enhance readability. So, we won’t be adding IE filters to any text here. If you do want to add filters yourself, see http://msdn.microsoft.com/en-us/library/ms673539(VS.85).aspx for the syntax. There are also a couple jQuery plugins that uses IE filters, available at http://kilianvalkhof.com/2008/javascript/text-shadow-in-ie-with-jquery and www.hintzmann.dk/testcenter/js/jquery/textshadow.

Note

If you’re using the Mootools JavaScript framework, you may want to check out the MooTools text drop-shadow script, which works in IE and non-IE browsers, at http://pr0digy.com/mootools/text-dropshadows.


  • Creative Edge
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint