CSS3 is one of the coolest new web technologies available to web developers right now. Using some of its many features, it is possible to reproduce the effects that you might have previously done in Photoshop, with CSS code that is more maintainable, faster to load, and hip with the latest trends. Read on to learn about the power tools available to you and how to combine them to produce the ultimate graphical effects.
CSS3 has many features, but some of them are imperative to learn if you are going to be reproducing Photoshop-like effects. I call these my “power tools.” They include the following:
- Border Radii
- Box Shadows
- Text Shadows
- Gradients
- Multiple Backgrounds
Each of these features can help replace some of the images that you might have created in Photostop in the past. By doing this, you are making your website more maintainable since you can change a property just by changing your CSS file rather than editing an image in Photoshop. You are also making your website load faster since images use a lot of bandwidth. Let’s explore these features one by one.
Power Tool #1: Border Radius
Browser Support:
- Safari: 3.2+
- Firefox: 3.0+
- Chrome: 3.0+
- Opera: 10.5+
- Internet Explorer: 9.0+
By now, you’ve probably heard about border-radius a million times. It is super easy to use and is supported accross all modern browsers. If you don’t already know, border radius is a way to create rounded corners with CSS—no images necessary! Let’s take a look at the syntax.
-webkit-border-radius: size; -moz-border-radius: size; border-radius: size;
There are three syntaxes that you will need to use. The first is for Webkit-based browsers, like Safari and Chrome; the second is for Mozilla-based browsers, like Firefox; and the last is the un-prefixed version, for browsers that support it, including IE9, Opera, and Safari 5.
Applying a 10 pixel border radius to a div creates the following effect:
OK, easy! Let’s move on to the next power tool.
Power Tool #2: Box Shadows
Browser Support:
- Safari: 3.2+
- Firefox: 3.5+
- Chrome: 3.0+
- Opera: 10.5+
- Internet Explorer: 9.0+
Box shadows are another well supported feature. Their syntax looks like this:
-webkit-box-shadow: offset_x offset_y blur_radius color; -moz-box-shadow: offset_x offset_y blur_radius color; box-shadow: offset_x offset_y blur_radius color;
Once again we have to use the vendor prefixes for Webkit and Mozilla. The first and second parameters of the box-shadow property are the offset positions from the left and top coordinates of the element. Setting a positive value to these properties moves the shadow to the right and down from the element, and setting a negative value moves the shadow to the left and up from the element. The blur_radius is the amount of blur you want to add to your shadow (how hard or fuzzy you want it). Finally, the last parameter is the color that you want the shadow to be. Adding a shadow to our previously used rounded div will create a nice looking effect.
-webkit-box-shadow: 5px 5px 10px #555; -moz-box-shadow: 5px 5px 10px #555; box-shadow: 5px 5px 10px #555;
Another neat feature of CSS box shadows is the inset keyword. When the inset keyword is present, the shadow is rendered inside the box rather than outside. This can create a nice depressed look especially for buttons. Here is what our div would look like with an inset shadow.
-webkit-box-shadow: 0 0 20px #333 inset; -moz-box-shadow: 0 0 20px #333 inset; box-shadow: 0 0 20px #333 inset;
The last feature of box shadows that is worth mentioning is the ability to have multiple shadows on the same element. This is very useful and can eliminate having extra markup in your HTML just to apply an additional shadow. All you have to do to create multiple shadows is separate them with commas. Here is an example:
-webkit-box-shadow: 0 0 20px #333 inset, 20px 15px 30px yellow, -20px 15px 30px lime, -20px -15px 30px blue, 20px -15px 30px red; -moz-box-shadow: 0 0 20px #333 inset, 20px 15px 30px yellow, -20px 15px 30px lime, -20px -15px 30px blue, 20px -15px 30px red; box-shadow: 0 0 20px #333 inset, 20px 15px 30px yellow, -20px 15px 30px lime, -20px -15px 30px blue, 20px -15px 30px red;
Power Tool #3: Text Shadows
Browser Support:
- Safari: 3.2+
- Firefox: 3.5+
- Chrome: 3.0+
- Opera: 10.1+
- Internet Explorer: Hopefully coming soon!
Text shadows are like box shadows except that they are shadows for text rather than the whole element. Luckily, there is no vendor prefix necessary for text shadow.
text-shadow: offset_x offset_y blur_radius color;
The options for text shadow are the same as for box-shadow except that there is no inset text shadow support. Here is a demo that makes otherwise-invisible text pop off the page.
color: #fff /* text color to white */ text-shadow: 0 0 50px #333;
This creates the following effect:
As with box shadows, it is possible to have multiple text shadows just by separating them with commas. Here is an example that creates a flaming text effect.
text-shadow: 0 0 4px #ccc, 0 -5px 4px #ff3, 2px -10px 6px #fd3, -2px -15px 11px #f80, 2px -18px 18px #f20;
Text shadows can create some awesome effects, and can complement other effects very nicely.
Power Tool #4: Gradients
Browser Support:
- Safari: 4+
- Firefox: 3.6+
- Chrome: 5+
- Opera: Hopefully coming soon!
- Internet Explorer: Hopefully coming soon!
Gradients are one of the most powerful features available to you if you want to create these awesome effects. While full browser support is still not quite there, you can always provide fallback styling to browsers without support. Remember: Websites do not need to look the same in every browser. There are two types of gradients that you can create: linear gradients and radial gradients. As you might expect, linear gradients move along a straight line and radial gradients go around a circle. Gradients can be used anywhere you might have used an image in the past, such as for the background, border-image, or list bullets.
Unfortunately for web developers, there are two different syntaxes: one for Mozilla and another for Webkit.
Syntax for Webkit
Safari and Chrome both use the Webkit rendering engine, so they always use the same syntax. Their gradient syntax is pretty simple:
-webkit-gradient(<type>, <point> [, <radius>]?, <point> [, <radius>]? [, <stop>]*)
Webkit uses the same same syntax for both linear and radial gradients. Just change the type parameter to switch between them.
Syntax for Mozilla
Firefox uses separate syntaxes for linear and radial gradients, both of which are very different from their Webkit counterparts.
-moz-linear-gradient( [<point> || <angle>,]? <stop>, <stop> [, <stop>]*) -moz-radial-gradient( [<position> || <angle>,]? [<shape> || <size>,]? <stop>, <stop>[, <stop>]*)
Let’s look at these syntaxes separately.
Linear Gradients
For simplicty, here is a Webkit’s syntax just for linear gradients.
-webkit-gradient(linear, start_x start_y, end_x end_y, stop, stop...)
Firefox’s syntax looks like this.
-moz-linear-gradient(angle start_x start_y, stop, stop...)
In the Webkit syntax start_x and start_y parameters specify the starting position of the gradient, and end_x and end_y specify the ending position of the gradient. You can use any of the standard CSS dimension values, including percentages, as well the keywords left, top, bottom, right, and center as values for these position parameters. Stops are a way for you to specify specific colors to be used at specific points along the gradient. You can have as many color stops as you want, but you must have at least two: a starting and ending color. For additional color stops, you can use the color-stop() function providing a position as a percentage or a decimal between 0 and 1 as well as a color. For example: color-stop(50%, black)
would create a black color stop at exactly half way through the gradient. Rather than writing 0% and 100% for the starting and ending colors, the convenience functions from() and to() exist. All you have to provide to these is the color.
Firefox’s syntax is much less straight forward, and has many ways of accomplishing the same goal. The only thing that is static about the syntax are the color stops, which are just a color followed by a position as a percentage. For the starting and ending positions, you can leave off 0% and 100%, and if you leave the position off of any of the other color stops, they are distributed evenly throughout the gradient. Unlike the Webkit syntax, Firefox’s syntax does not have an ending position, only a starting position and an angle. The gradient will run out from the starting position at the specified angle. If you leave the angle out, it will run out perpendicularly from that point. If you leave out the starting point all together, the gradient will run from top to bottom. This syntax is kind of confusing and a bit less flexible than Webkit’s simple syntax, so it is best to learn by example.
Here is a simple example of CSS gradients in action. This gradient goes from the top left corner to the bottom left corner (in other words, from top to bottom) and from red to white.
-webkit-gradient(linear, left top, left bottom, from(red), to(white)); -moz-linear-gradient(red, white)
Setting this as the background property of a div, we get the following result:
By adding a color stop and changing the angle of the gradient, we can get a different effect.
-webkit-gradient(linear, left top, right bottom, from(red), color-stop(50%, white), to(red)); -moz-linear-gradient(left top, red, white, red);
Radial Gradients
Here is the syntax for radial gradients in Webkit.
-webkit-gradient(radial, inner_circle_center_x inner_circle_center_y, inner_circle_radius, outer_circle_center_x outer_circle_center_y, outer_circle_radius, stop, stop...)
Firefox’s syntax looks like this.
-moz-radial-gradient(center_x center_y, shape size, stop, stop...)
The Webkit syntax is a bit more complicated than the linear gradient syntax, but the same principles still apply. Radial gradients in Webkit have two circles: a starting circle and an ending circle. You specify the center X and Y positions for each of these circles along with their radii. Finally you specify the color stops the same way you did for linear gradients.
The Firefox syntax for radial gradients is similar to the syntax for linear gradients in that all of its parts except the color stops can be left out. You can specify the center X and Y positions of the gradient much like the inner circle’s coordinates in the Webkit syntax, but there is no outer circle in Firefox. Instead you can specify a shape and size of the gradient. The shape can be either a circle or an ellipse, the latter of which is not currently possible to create in Webkit. The size accepts many different keywords, but not a pixel size as you might have expected. You can read about what each of these constants do on the Mozilla Developer Center. For this tutorial, we will just use the defaults. Once again, if you leave the center X and Y positions out, they will be assumed to be the center of the object you are filling with a gradient. If you leave out the shape and size, the gradient will be assumed to be a circle that fills the entire box.
-webkit-gradient(radial, center center, 0, center center, 50, from(white), to(red)); -moz-radial-gradient(white, red)
If we apply this gradient to the background of a div, this is what we will get.
Power Tool #5: Multiple Backgrounds
Browser Support:
- Safari: 3.2+
- Firefox: 3.6+
- Chrome: 3.0+
- Opera: 10.5+
- Internet Explorer: 9.0+
Multiple backgrounds make it easy to create complex effects in CSS without needing to create additional markup in your HTML. Having support for this means that elements can have multiple gradients and image backgrounds along with the standard background color. There is no difference in the syntax of multiple backgrounds from single backgrounds – just comma separate them and off you go!
Here is an example of a div with a gradient background and a nice textured effect using an image:
background: url(noise.png), -webkit-gradient(linear, left top, left bottom, from(#999), to(#333)); background: url(noise.png), -moz-linear-gradient(#999, #333);
We have to declare it twice since, as we’ve learned, there is a different gradient syntax for each browser. This creates the following effect:
Combining the Power: Building an Awesome CSS3 Button
Now that we have five great power tools at our disposal, let’s combine them to produce an even more awesome effect.
There are so many different types of buttons that you can choose to design. To be simple, let’s emulate something that already exists – the Mac OS X button style.
We will start off with our HTML code for this demo. It is really quite simple, just two DIVs and some text.
<div class="panel"> <div class="button">Button</div> </div>
Now we will start off with our basic CSS. First, let’s style the panel.
.panel { background: -webkit-gradient(linear, left top, left bottom, from(#bbbcbb), to(#959695)); background: -moz-linear-gradient(#bbbcbb, #959695); background-color: #b7b9b7; width: 100px; }
The panel is just a nice container for our button. It has a gradient going from top to bottom between two nice grey colors. For those browsers that don’t support gradients, a fallback background-color is given.
Now, let’s look at the CSS for the actual button.
.button { display: inline-block; margin: 20px; padding: 3px 6px; font-family: 'Lucida Grande', Arial, sans-serif; font-size: 13px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; border: 1px solid rgba(0, 0, 0, 0.6); background: -webkit-gradient(linear, left top, left bottom, from(#fbfcfb), to(#9d9e9d)); background: -moz-linear-gradient(#fbfcfb, #9d9e9d); background-color: #c0c2c0; text-shadow: rgba(255, 255, 255, 0.4) 0px 1px; -webkit-box-shadow: rgba(255, 255, 255, 0.4) 0 1px; -moz-box-shadow: rgba(255, 255, 255, 0.4) 0 1px; box-shadow: rgba(255, 255, 255, 0.4) 0 1px; -webkit-user-select: none; -moz-user-select: none; cursor: default; }
There is a decent amount of code here, which uses all of the power tools that I described above, except for multiple backgrounds. There are several sections to this code, which we will take one by one. The first two lines are just some simple layout information. Setting the button to display: inline-block makes it automatically extend to fit the content, no matter how much text you put in the button. The next section gives some font information to the button. Finally, in the third section we get to use our first power tool: border radius. In the case of our lovely button, we give it a nice 3px radius. Next we give the button a border. Notice that we are using rgba as a color here. This allows us to make the color partially transparent as we do here, creating a nice grayish color. In the next section of code, we set up the background of the button. We give it a gradient background as well as a solid color for fallback in browsers that don’t support gradients yet. Next, we use text shadow to make the text look slightly engraved into the button. Once again we use rgba here to give a partially transparent white to the text shadow. The pen-ultimate section of code creates a box shadow. Now, this does not actually look like a shadow, it actually looks like a second border, but it gives a nice highlight to the bottom of the button to make it look engraved into the background and compliments the border color. This is a useful trick to know if you ever want something to look like it has multiple borders – I use it a lot. Finally, the last section of CSS code is a nice trick that prevents text selection in Webkit based browsers and Firefox, and sets the cursor to the default arrow rather than the text selection cursor.
So far, this code makes our button look like this:
OK, so not too bad yet! Let’s move on to the button’s depressed look.
.button:active { background: #B5B5B5; -webkit-box-shadow: rgba(255, 255, 255, 0.4) 0 1px, black 0px 1px 3px inset, rgba(0, 0, 0, 0.4) 0px -5px 12px inset; -moz-box-shadow: rgba(255, 255, 255, 0.4) 0 1px, black 0px 1px 3px inset, rgba(0, 0, 0, 0.4) 0px -5px 12px inset; box-shadow: rgba(255, 255, 255, 0.4) 0 1px, black 0px 1px 3px inset, rgba(0, 0, 0, 0.4) 0px -5px 12px inset; text-shadow: rgba(255, 255, 255, 0.3) 0px 1px; }
When the button is pressed down, we change a number of things. First, we set the background to a plain color, removing the gradient that we had set eariler. This is because we will be creating the depressed look with a box shadow rather than a gradient. The next thing we do, is set that shadow—or rather multiple shadows. The first shadow in the list is the same one that we had in the normal state: the highlight on the bottom of the button. The second and third shadows are the ones that make our button look pressed. The first of these is a black inset shadow that is set down from the top 1 pixel and has 3 pixels of blur—a pretty dark looking shadow. The last shadow is also black but a slightly transparent black that is set up from the bottom 5 pixels with 12 pixels of blur. This creates the darkened look on the bottom of the button when it is pressed. The final thing that we need to do when this button is pressed down is just reduce the opacity of the text shadow by one notch so that it doesn’t stand out like a sore thumb.
That’s it! Our button is complete. Here is what the pressed down version looks like:
Conclusion
Replacing images with CSS3 has many benefits. It makes your job as a web developer easier since you don’t need to open Photoshop every time you need to make a change to your user interface. It makes your web site or web application load faster since it doesn’t need to download so many heavy images. And it allows you to create a more rich, interactive, and desireable experience for users such that they will keep coming back for more.
I will leave you with a bit of inspiration of things that you could do with CSS3. These aren’t necessarily the most real world examples, but they show what is possible with a bit of work.
iPhone Made With Pure CSS3
The first demo, created by Jeff Batterton, is an iPhone created with pure CSS3 – no images used. It is very impressive, utilizing CSS gradients, text shadows, box shadows, transitions and transforms. Unfortunately, it currently only looks correct in Webkit based browsers like Safari and Chrome. It can be your task to make the demo work in Firefox!
Pure CSS3 iOS Icons
Another demo, perhaps even more amazing was written by Louis Harboe. It is a recreation of some of the iOS icons in pure CSS, and very realistic recreations at that! This demo also only works in Webkit based browsers. If you want to learn about how some of these icons were reproduced, you can head over to Louis Harboe’s blog where he describes the process.
I hope you’ve enjoyed this article! Feel free to catch up with me on Twitter, or leave your thoughts in the comments!