facebook google plus twitter
Webucator's Free Advanced CSS Tutorial

Lesson: CSS Background Tricks

Welcome to our free Advanced CSS tutorial. This tutorial is based on Webucator's Advanced CSS Training course.

Background images can be used to create effects not available in standard CSS (or yet supported by browsers). They can also be used to combine images into a single file to save on download time.

Some of the graphics used in this lesson were contributed by RamblingSoul.com.

Lesson Goals

  • Create fixed-width rounded corner boxes.
  • Create relative-width rounded corner boxes.
  • Create "mountaintop corners" on boxes.
  • Create tabbed navigation.
  • Create drop shadow effects.
  • Create CSS sprites.
  • Use new CSS3 background and color features.

Rounded Corner Boxes

There are many different methods of creating rounded-corner boxes using CSS. Most methods use background images and involve extra non-semantic HTML markup. CSS3 has been released and is supported in modern browsers, however; designers who want rounded corners and need to support Internet Explorer 8 and earlier may be forced to compromise on semantic HTML markup. We'll cover some tactics to achieve these effects on older browsers first, then look at how we can accomplish the same things with CSS3 for more modern browsers.

Fixed-width Rounded Corner Boxes

To create a fixed-width rounded-corner box with variable height, you need to use at least two background images, one for the top and one for the bottom, and sometimes a third for the middle. Each image must be the same width as the box, which is usually a div marked up like this:

<div id="box">
	<div class="bgTop"></div>
		<div class="content">
			content goes here
		</div>
	<div class="bgBottom"></div>
</div>

Our first example, CssBackgroundTricks/Demos/FixedRoundCornerBox1.html, uses images to cap the top and bottom of a container. It uses the CSS border property for the left and right borders.

The background images, which are 9 pixels high by 660 pixels wide, are shown below: Background Images Second Background Images

And here is the result in the browser with the CSS shown in the box itself: Browser Result

To make it easier to see what's going on, in the screenshot below we've added a dashed border around the divs using this code:

div { border:1px dashed #f00; }

The result: Fixed Round Corner Box with Dashed Border

In the next example, the HTML markup is the same, but this one uses a background image instead of the border property to style the left and right edges of the container. We cannot use the border property because the border here is fancier than any options provided by CSS.

The images used are shown below: Top Image Middle Image Bottom Image

And here is the result in the browser with the CSS shown in the box itself: Fixed Corner Box

And here it is with the dashed border to show how the sections are broken out: Fixed Corner Box with Dashed Border

Flexible-width Rounded Corner Boxes

Creating rounded corner boxes with flexible widths is more complicated because images have fixed widths. Instead of using images to cap the top and bottom, we use an image for each corner. The markup looks like this:

<div id="box">
	<span class="topLeft bg"></span>
	<span class="topRight bg"></span>
	<span class="bottomLeft bg"></span>
	<span class="bottomRight bg"></span>
	<div class="content">content goes here</div>	
</div>

Notice that we have assigned two classes to each of the span tags: one to capture its position (e.g., topLeft) and the other to indicate that it is a background (bg).

We could use four separate images; however, by taking advantage of background positioning, we can accomplish this with just a single image (magnified below): Magnified Image

The checkered portion of this image is transparent. Each corner of the image shown will serve as the background for the analogous corner of our box. Here's the code:

Code Sample:

CssBackgroundTricks/Demos/FlexibleRoundCornerBox.html
---- C O D E   O M I T T E D ----
<style>
body {
	margin:10px;
	font: 1.2em/1.1 Courier;
	color:#000;
}
#box {
	margin:10px;
	position:relative;
	height:1%;
}
#box .bg {
	position:absolute;
	height: 12px;
	width: 12px;
	background: #fff url(Images/blueCircle.gif) no-repeat;
}
#box .topLeft {
	top:0px;
	left:0px;
	background-position:top left;
}
#box .topRight {
	top:0px;
	right:0px;
	background-position:top right;
}
#box .bottomLeft {
	bottom:0px;
	left:0px;
	background-position:bottom left;
}
#box .bottomRight {
	bottom:0px;
	right:0px;
	background-position:bottom right;
}
#box .content {
	border:4px solid #00f;
	padding:25px 30px;
}
</style>
<title>Flexible-width Rounded Corner Boxes</title>
</head>
<body>
<div id="box">
	<span class="topLeft bg"><!--for IE6--></span>
	<span class="topRight bg"><!--for IE6--></span>
	<span class="bottomLeft bg"><!--for IE6--></span>
	<span class="bottomRight bg"><!--for IE6--></span>
	<div class="content">
	content goes here
	content goes here
	content goes here
	content goes here
	content goes here
	content goes here
	content goes here
	content goes here
	content goes here
	content goes here
	</div>
</div>
</body>
</html>

Code Explanation

Things to notice:

  • The box itself gets relative positioning. That's so we can position the spans absolutely within it.
  • Each span, via its bg class, has the following properties:
    position:absolute;
    height: 12px;
    width: 12px;
    background: #fff url(Images/blueCircle.gif) no-repeat;
    This will turn them into positionable 12 pixel squares with a background. If we were to change the height and width to 50 pixels, the box would look like this: Flex Round Corner Box
  • Each span is then positioned within the box and the background image is positioned so that the appropriate corner is revealed.
  • We put a 4-pixel blue border on the "content" div to meet up with the four corners.
  • We add a height: 1% declaration to our rule for #box. This is necessary for Internet Explorer to render the box correctly.

Here the result shown with two different widths: Two Different Widths Second Round Corner Box

Rounded Corners with CSS3

With the advent of CSS3 - and better support for newer CSS3's techniques among most browsers - we can accomplish the same rounded-corner effect much more easily. While most modern browsers now support CSS3, it's always the case that your use of CSS3 should be dictated by the audience you expect for your pages: folks using older version of browsers won't always see the same results.

CSS3's border-radius property let's us set the radius - in pixels, ems, or any other valid CSS length unit, or as a percentage of the parent - of any element:

div.rounded {
	border-radius:20px;
}

The code above would set rounded corners, with a radius of 20px, for any div of class rounded. The border-radius property is actually shorthand for setting the radius of each of the four corners of an element; as such, we might also write:

div.rounded {
	border-top-left-radius:20px;
	border-top-right-radius:20px;
	border-bottom-right-radius:20px;
	border-bottom-left-radius:20px;
}

We could, of course, give each corner a different radius:

div.rounded {
	border-top-left-radius:2em;
	border-top-right-radius:10px;
	border-bottom-right-radius:30px;
	border-bottom-left-radius:2.4em;
}

We can combine the specification of each corner into the shorthand version of the border-radius property, where the values are top-left, top-right, bottom-right, bottom-left, from first to last respectively. The following sample is the same as the previous code sample:

div.rounded {
	border-radius:2em 10px 30px 2.4em;
}

Code Sample:

CssBackgroundTricks/Demos/BorderRadius.html

Code Explanation

Open up CssBackgroundTricks/Demos/BorderRadius.html in a browser to view the results and in a code editor to check out the code. Our example presents two boxes with rounded corners:

Border Radius

The first div, with id #box1, has a red background; it's rounded corners (all with the same radius) result from the statement border-radius:20px;.

The second div, with id #box2, has a yellow background. We set it's top-right and lower-left corners to be really rounded, with a radius of 140px. Those corners, along with a border-radius of 10px for the top-left corner and 30px for the lower-right corner, makes the element look roughly like a lemon!

Mountaintop Corners

In an A List Part article, Dan Cederholm introduced another way to create rounded corners, which he dubbed "Mountaintop Corners."

The idea is similar to the last example, but doesn't involve using borders on the box. Instead, you cover the corners of the box with a concave image of the same color as the background leaving the concave portion transparent. You could use four images like this:

First Image Second Image

Third Image Fourth Image

But we can put these all together and use just a single image like this:

Single Image

As you can see, it looks like a hole; we named it hole.gif in the Demos/Images folder. That image is 18x18 pixels, so each corner is 9x9 pixels as you can see in the diagram below: Diagram

One nice feature about this method is that you can freely style the boxes without considering the color of the border or the rounded corners. The screenshot below shows the output for two boxes with different background colors: Two Boxes with Different Background Colors

And here is the code:

Code Sample:

CssBackgroundTricks/Demos/mountaintop.html
---- C O D E   O M I T T E D ----
<style>
body {
	margin:10px;
	font: 1.2em/1.1;
	color:#000;
	background:#fff;
}
h1 {
	font-size:1.2em;	
	padding:5px 10px;
}
.box {
	margin:10px;
	position:relative;
	height:1%;
}
.box .bg {
	position:absolute;
	height: 9px;
	width: 9px;
	background: transparent url('Images/hole.gif') no-repeat;
	border:1px solid red;
}
.box .topLeft {
	top:-1px;
	left:-1px;
	background-position:top left;
}
.box .topRight {
	top:-1px;
	right:-1px;
	background-position:top right;
}
.box .bottomLeft {
	bottom:-1px;
	left:-1px;
	background-position:bottom left;
}
.box .bottomRight {
	bottom:-1px;
	right:-1px;
	background-position:bottom right;
}
#box1 .content {
	padding:20px 30px;
	background:#ff0;
}
#box1 h1 {
	background:#ccc;
}
#box2 .content {
	padding:20px 30px;
	background:#0ff;
}
#box2 h1 {
	background:#faa;
}
</style>
<title>Mountaintop Boxes</title>
</head>
<body>
<div class="box" id="box1">
	<span class="topLeft bg"><!--for IE6--></span>
	<span class="topRight bg"><!--for IE6--></span>
	<span class="bottomLeft bg"><!--for IE6--></span>
	<span class="bottomRight bg"><!--for IE6--></span>
	<h1>Box 1</h1>
	<div class="content">
	content goes here
	</div>	
</div>
<div class="box" id="box2">
	<span class="topLeft bg"><!--for IE6--></span>
	<span class="topRight bg"><!--for IE6--></span>
	<span class="bottomLeft bg"><!--for IE6--></span>
	<span class="bottomRight bg"><!--for IE6--></span>
	<h1>Box 2</h1>
	<div class="content">
	content goes here
	</div>	
</div>
</body>
</html>

Code Explanation

Things to notice:

  • The HTML code is very similar to what we saw in the previous example. We've used ids to identify the two different boxes and we have added h1 elements above the "content" div.
  • We have added background colors to the h1 and "content" div.

Below is a shot of the top box with the corners outlined, which we did by adding this CSS code: span { border:1px dashed red}. Top Box with Corners Outlined

There are other ways of creating boxes with rounded corners.

Creating a Rooftop Panel

Duration: 20 to 30 minutes.

In this exercise you will use some of the techniques you have learned to create rounded corners to create a rooftop panel that looks like this: Rooftop Panel Image

  1. Open CssBackgroundTricks/Exercises/rooftop.html in your editor.
  2. Fill in the three empty rules to create a rooftop panel as shown in the screenshot above.
  3. You will need to make use of rooftop.gif in the Images folder. The image is 350 x 20 pixels.

Solution:

CssBackgroundTricks/Solutions/rooftop.html
---- C O D E   O M I T T E D ----
<style>
body {
	margin:10px;
	font: 1.2em/1.1;
	background:#fff;
}
p {
	margin:15px 20px;
}
.panel {
	position:relative;
	width:350px;
	background-color:#cef;
	padding-bottom:10px;
}
.panel .bg {
	position:absolute;
	height:20px;
	width:100%;
	top:0px;
	left:0px;
	background: transparent url('Images/roofTop.gif') no-repeat;
}

.panel h2 {
	padding-top:15px;
	text-align:center;
	font-size:2em;
	font-variant: small-caps;
	background-color:#add;
	color:#006;
}
</style>
---- C O D E   O M I T T E D ----

Tabbed Navigation

The screenshot below shows an example of a page that uses tabbed navigation: Page Using Tabbed Navigation

To create the navigation bar, we combine some of the techniques we have learned thus far. Let's start by looking at the code:

Code Sample:

CssBackgroundTricks/Demos/tabbedMenus.html
---- C O D E   O M I T T E D ----
<style>
#wrapper {
	width:846px;
	margin:10px auto;
}
#content {
	clear:both;
	width:838px;
	background-color:#eee;
	border:4px solid #000808;
}
p {
	margin:5px;
	padding:5px;
}
#mainMenu {
	width:846px;
	font-family: "Trebuchet MS";
}
#mainMenu li {
	display:block;
	width:120px;
	float:left;
	margin-left:1px;
}
#mainMenu li:first-child, #mainMenu li.first {
	margin-left:0px;
}
#mainMenu a {
	display:block;
	padding:10px;
	text-decoration:none;
	background:transparent url(Images/link.gif) repeat-x;
	color:#fff;
	text-align:center;
}
#mainMenu a:hover {
	background:transparent url(Images/hover.gif) repeat-x;
	color:#333;
}
#mainMenu a:active {
	background:transparent url(Images/active.gif) repeat-x;
	color:#fff;
}
</style>
<title>CSS Menu</title>
</head>
<body>
<div id="wrapper">
	<ul id="mainMenu">
		<li class="first"><a href="home.html">Home</a></li>
		<li><a href="services.html">Services</a></li>
		<li><a href="products.html">Products</a></li>
		<li><a href="support.html">Support</a></li>
		<li><a href="blog.html">Blog</a></li>
		<li><a href="about.html">About</a></li>
		<li><a href="contact.html">Contact</a></li>
	</ul>
	<div id="content">
---- C O D E   O M I T T E D ----
</div>
</div>
</body>
</html>

Code Explanation

This code should be pretty straightforward. It simply combines the list navigation techniques you learned in CSS Lists as Hierarchical Navigation with the background image techniques we've learned here.

Open the page in your browser to see the three states of the menu items. The magnified background images used are shown below: Magnified Background Images

Each image is 6 pixels wide by 37 pixels high.

Tabbed Navigation: Rounding the Corners

Duration: 15 to 25 minutes.

In this exercise, you will modify the tabbed menu we just showed so that the top corners of each menu item are rounded like this: Rounded Corners

  1. Open CssBackgroundTricks/Exercises/tabbedMenus.html.
  2. Modify the code so that it uses hole.gif from the Images folder to create the rounded corners shown in the screenshot above.

Solution:

CssBackgroundTricks/Solutions/tabbedMenus.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../reset-meyer.css">
<style>
	#wrapper {
		width:846px;
		margin:10px auto;
	}
	
	#content {
		clear:both;	
		width:838px;
		background-color:#eee;
		border:4px solid #000808;
	}
	
	p {
		margin:5px;
		padding:5px;	
	}

	#mainMenu {
		width:846px;
		font-family: "Trebuchet MS";
	}
	#mainMenu li {
		display:block;
		width:120px;
		float:left;
		margin-left:1px;
		position:relative;
	}
	#mainMenu li:first-child,#mainMenu li.first  {
		margin-left:0px;
	}
	
	#mainMenu a {
		display:block;
		padding:10px;
		text-decoration:none;
		background:transparent url(Images/link.gif) repeat-x;
		color:#fff;
		text-align:center;
	}
	
	#mainMenu a:hover {
		background:transparent url(Images/hover.gif) repeat-x;
		color:#333;
	}
	
	#mainMenu a:active {
		background:transparent url(Images/active.gif) repeat-x;
		color:#fff;
	}
	
	#mainMenu .bgLeft {
		position:absolute;
		top:-1px;
		left:-1px;
		height: 9px;
		width: 9px;
		background: transparent url('Images/hole.gif') no-repeat top left;
	}
	
	#mainMenu .bgRight {
		position:absolute;
		top:-1px;
		right:-1px;
		height: 9px;
		width: 9px;
		background: transparent url('Images/hole.gif') no-repeat top right;
	}
</style>
<title>CSS Menu</title>
</head>
<body>
<div id="wrapper">
<ul id="mainMenu">
	<li class="first"><span class="bgLeft"><!--for IE6--></span><span class="bgRight"><!--for IE6--></span><a href="home.html">Home</a></li>
	<li><span class="bgLeft"><!--for IE6--></span><span class="bgRight"><!--for IE6--></span><a href="services.html">Services</a></li>
	<li><span class="bgLeft"><!--for IE6--></span><span class="bgRight"><!--for IE6--></span><a href="products.html">Products</a></li>
	<li><span class="bgLeft"><!--for IE6--></span><span class="bgRight"><!--for IE6--></span><a href="support.html">Support</a></li>
	<li><span class="bgLeft"><!--for IE6--></span><span class="bgRight"><!--for IE6--></span><a href="blog.html">Blog</a></li>
	<li><span class="bgLeft"><!--for IE6--></span><span class="bgRight"><!--for IE6--></span><a href="about.html">About</a></li>
	<li><span class="bgLeft"><!--for IE6--></span><span class="bgRight"><!--for IE6--></span><a href="contact.html">Contact</a></li>
</ul>
<div id="content">
<p>"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
</div>
</div>
</body>
</html>

Drop Shadows

For older browsers (those that don't support CSS3), a drop shadow effect can be created by nesting one div inside of another div. Using relative positioning, the nested div, which will contain the content, can be pushed from the bottom right, thus allowing the outer div to show through. The outer div is then given a background color or image to create the drop shadow effect.

Take a look at the code below:

Code Sample:

CssBackgroundTricks/Demos/DropShadows.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Drop Shadows</title>
<style>
body {
	padding: 10px;
}
p {
	margin: 0;
	padding: 10px;
}
.box {
	width: 95%;
	margin: 10px;
}
.box .content {
	position: relative;
	background-color: #fff;
	border: 1px solid #c0c0c0;
	bottom: 3px;
	right: 3px;
}
.shadow1 {
	background: #ddd;
}
.shadow2 {
	background: url('Images/bg-dropShadow.gif') bottom right;
}
</style>
</head>
<body>
<div class="box shadow1">
	<div class="content">
		<p>This box has a solid drop shadow effect applied.</p>
	</div>
</div>
<div class="box shadow2">
	<div class="content">
		<p>This box has a drop shadow effect applied using a single image.</p>
	</div>
</div>
</body>
</html>

Code Explanation

Things to notice:

  • The HTML markup is quite simple: one div inside of another.
  • The nested "content" div has relative positioning and is pushed up and to the left. It also takes a background color (white) and a 1 pixel grey border.
  • The shadow of the first box is created with a background color.
  • The shadow of the second box is created with a background image.

The result is shown below: Result

In the screenshot below, we put a dashed border around the shadow divs to show that they are largely covered by the "content" divs: Shadows with Border

That's it. As you can see, creating drop shadow effects is relatively easy. But using CSS3 is even easier! Let's look at how we can create drop shadows with less markup and with considerably more control over the color and position of the shadow.

CSS3 Drop Shadows: The box-shadow Property

With the box-shadow property, we can attach a drop shadow to an element. The code

.shadow {
	box-shadow: 5px 10px #000;
}

adds to any element of class shadow a shadow having horizontal offset of 5px (the first parameter - how far to the right the shadow falls), vertical offset of 10px (the second parameter - how far down the shadow falls), and color black (the third parameter, #000). Note that the horizontal and vertical offset values can be negative, to display the shadow to the left or top of the element.

The box-shadow property accepts a few more parameters - the code below

.shadow {
				box-shadow: 3px -5px 4px 2px #f00;
}

would add a shadow which has:

  • 3px horizontal (right) spread;
  • -5px vertical (top) spread;
  • 4px blur radius, giving the shadow a "fuzzy" edge;
  • 2px spread distance, extending the shadow 2 pixels away from the element in all directions; and
  • red (#f00) color.

We can add multiple shadows to an element, using commas to delineate each shadow:

.shadow {
				box-shadow: 5px 5px #f00, -5px -10px #00f;
}

Let's look at some examples:

Code Sample:

CssBackgroundTricks/Demos/DropShadowsCSS3.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Drop Shadows</title>
<style>
body {
	padding: 30px;
}
p {
	margin: 0;
	padding: 10px;
}
.box {
	width: 90%;
	margin: 30px;
	background:#000;
	color:#fff;
}
#box1 {
	box-shadow: 5px 5px 10px #999;
}
#box2 {
	box-shadow: 5px 5px 2px #999;
}
#box3 {
	box-shadow: 5px 5px 5px 10px #999;
}
#box4 {
	box-shadow: 2px 2px 5px #f00, -5px -5px 5px #00f;
}
</style>
</head>
<body>
<div id="box1" class="box">
	<p>Box1: box-shadow: 5px 5px 10px #999;</p>
</div>

<div id="box2" class="box">
	<p>Box2: box-shadow: 5px 5px 2px #999;</p>
</div>

<div id="box3" class="box">
	<p>Box3: box-shadow: 5px 5px 5px 10px #999;</p>
</div>

<div id="box4" class="box">
	<p>Box4: box-shadow: 2px 2px 5px #f00, -5px -5px 5px #00f;</p>
</div>
</body>
</html>

Code Explanation

The result is shown below: CSS3 Drop Shadows

Note that in our markup we have only a single div - there's no need for a second (and semantically meaningless) div element inside each box.

In box1 we display a gray shadow with horizontal and vertical 5px spread and blur radius of 10px.

In box2 we display a gray shadow with horizontal and vertical 5px spread and blur radius of 2px; box2's shadow had a harder edge than that of box1 because box2 has a smaller blur radius.

In box3 we display a gray shadow with horizontal and vertical 5px spread, blur radius of 5px, and spread radius of 10px - the spread radius extends the shadow off from the box.

Finally, in box4, we display two shadows: a red shadow down and right, and a blue shadow (with negative horizontal and vertical values) up and left.

CSS Sprites

A CSS sprite is an image file that contains several graphics used on a web page. By showing different parts of the sprite in different locations, it appears that there are several different images, but they are all contained in a single file, which translates to a single download.

As a simple example, let's look at the images we used for tabbed navigation earlier. Here they are again (magnified): Tabbed Navigation Image

Instead of having three different images, let's combine these into a single image (magnified below): Combined Single Image

Now let's see how we can play with the background positioning to make use of this single tabSprite.gif image rather than the three separate images.

Code Sample:

CssBackgroundTricks/Demos/tabbedMenus-sprite.html
---- C O D E   O M I T T E D ----
	#mainMenu a {
		display:block;
		padding:10px;
		text-decoration:none;
		background:transparent url(Images/tabSprite.gif) 0px 0px repeat-x;
		color:#fff;
		text-align:center;
	}
	
	#mainMenu a:hover {
		color:#333;
		background-position:0px -37px;
	}
	
	#mainMenu a:active {
		color:#fff;
		background-position:0px -74px;
	}
---- C O D E   O M I T T E D ----

Code Explanation

Things to notice:

  • In the rule for #mainMenu a, we have changed the background image to Images/tabSprite.gif and added positioning of 0px 0px. That's because we want the link state to show the top portion of our tabSprite image.
  • In the rule for #mainMenu a:hover, we have replaced the rule for background with background-position:0px -37px;. That's because we inherit the background image from the #mainMenu a, but we want to bump it up 37 pixels so that it shows the middle portion of the image.
  • We do the same thing with the rule for #mainMenu a:active, but this time we bump it up 74 pixels.

The more graphic heavy a page is, the more it can benefit from using CSS sprites. Consider this small example we have just shown. The table below shows the file sizes for the three original graphics and then for the sprite:

Comparing CSS Sprite File Size with Separate Images
File Size
link.gif 590 bytes
hover.gif 612 bytes
active.gif 378 bytes
Total: 1,580 bytes
tabSprite.gif 817 bytes
Difference: 763 bytes

That savings of 763 bytes translates to a savings in file size of 48%. Add to that the overhead associated with each http download for the separate images and you'll find the savings can be significant.

Open CssBackgroundTricks/Demos/sprite.html for a more complex example that uses a single image to create a library of thumbnails that highlight when the user hovers over them. Check out the code and you'll see that only a single graphic is used.

Background Opacity & Images

CSS3 introduces a new way to specify color values: hue, saturation, and light (HSL) values. As the W3C specification states:

Hue is represented as an angle of the color circle (i.e., the rainbow represented in a circle). This angle is so typically measured in degrees that the unit is implicit in CSS; syntactically, only a <number> is given. By definition red=0=360, and the other colors are spread around the circle, so green=120, blue=240, etc. As an angle, it implicitly wraps around such that -120=240 and 480=120. One way an implementation could normalize such an angle x to the range [0,360) (i.e., zero degrees, inclusive, to 360 degrees, exclusive) is to compute (((x mod 360) + 360) mod 360). Saturation and lightness are represented as percentages. 100% is full saturation, and 0% is a shade of gray. 0% lightness is black, 100% lightness is white, and 50% lightness is 'normal'.

The W3C offers a set of tables as examples of HSL values:

HSL tables

Also new in CSS3 is the ability to specify the alpha channel of a color, setting the opacity of the given color. We can specify color and alpha with rgba:

/* green with 50% opacity */
				background-color:rgba(0, 255, 0, 0.5);

or with hsla:

/* green with 50% opacity */
				color:hsla(120, 100%, 50%, 0.5);

Code Sample:

CssBackgroundTricks/Demos/hsl-alpha.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>CSS3 HSL &amp; Alpha</title>
	<style>
		#main {
			background-image:url(Images/gridme.png);
			background-repeat: repeat;
		}
		h1 {
			background-color:rgba(40, 50, 200, 0.4);
		}
		#bg {
			margin:0 auto 5% auto;
			background-image:url(Images/chicago.jpg);
			background-repeat:no-repeat;
			background-position: 10px 10px;
			background-color:hsl(120, 75%, 40%);
			width:320px;
			height:301px;
			position: relative;
		}
		#caption {
			position:absolute;
			left:10%;
			top:30%;
			width:80%;
			height:20%;
			padding-top:10%;
			text-align: center;
			background-color:hsla(120, 75%, 40%, 0.4);
		}
	</style>
</head>
<body>
	<div id="main">
		<h1>CSS3 HSL &amp; Alpha</h1>
		<div id="bg">
			<div id="caption">
				Willis Tower in Chicago
			</div>
		</div>
	</div>
</body>
</html>

Code Explanation

Our example, ClassFiles/CssBackgroundTricks/Demos/hsl-alpha.html, shows a page with a tiled background pattern, a title with semitransparent purple background, and an image element with background color and a semitransparent caption block in the center:

Page Image

We use a repeated background image on the #main <div>, a grid pattern. We apply a background color to the <h1> using rgba, setting the alpha to 0.4 - a 40% opacity.

The #bg <div> has a background color, using hsl (with no alpha setting), and a no-repeat background image (which doesn't cover the entire element). The #caption <div>, positioned absolutely on top of the #bg <div>, has a semitransparent green background, set with hsla.

The hsl, hsla, and rgba methods of specifying color are not supported in IE 7-8, but are supported in IE 9 and recent versions of other browsers.

The opacity Property

CSS3's opacity property makes it easy to change the opacity of images, text, <div>s, and other elements. Where before we might have resorted to PNG images with a semitransparent alpha setting, we can now change the opacity via CSS. Even better, we can change opacity more easily with :hover to create rollover effects. Let's look at an example:

Code Sample:

CssBackgroundTricks/Demos/opacity.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>CSS3 Opacity</title>
	<style>
		#img1 {
			float:left;
		}
		#img1:hover {
			opacity:0.5;
			filter:alpha(opacity=50);
		}

		#bg {
			background-image:url(Images/chicago.jpg);
			width:300px;
			height:281px;
			float:right;
		}
		#caption {
			width:80%;
			height:20%;
			margin:30% 10%;
			padding-top:15%;
			text-align: center;
			background:#fff;
			opacity:0.2;
			filter:alpha(opacity=20);
		}
		#bg:hover #caption {
			opacity:0.9;
			filter:alpha(opacity=90);
		}

		#footer {
			clear:both;
		}
		#footer p:hover {
			opacity:0.5;
			filter:alpha(opacity=50);
		}
	</style>
</head>
<body>
	<div id="main">
		<h1>CSS3 Opacity</h1>
		<img src="Images/chicago.jpg" alt="Chicago skyline" id="img1">

		<div id="bg">
			<div id="caption">
				Willis Tower in Chicago
			</div>
		</div>

		<div id="footer">
			<p>Left image opacity changes on hover; right image caption div opacity changes on hover</p>
		</div>
	</div>
</body>
</html>

Code Explanation

The page presents three main elements: an image on the left, an image on the right, and a footer. Here's a screenshot of the page before any changes to element opacity:

Opacity Before Hover

We apply a change to some aspect of each of the three elements when the user mouses over, via the :hover selector:

  • The left image, without caption, changes to 50% opacity (opacity:0.5;) when moused over.
  • The caption on top of the right image (the image is itself a background) changes from its initial 20% opacity to 90% opacity when moused over. Note that the opacity for the text in the "caption" <div> is also affected by the opacity change - unlike, in our earlier example, where the color setting (in which we set the alpha value) for a <div> does not change the opacity of child elements.
  • The opacity of the footer text changes to 50% opacity when moused over.

CSS3's opacity property works well in all modern browser versions but for Internet Explorer before version 9. For earlier versions of IE, we can use filter:alpha(opacity=xx);, where xx represents the desired opacity in percentage units (without the percent sign). We've used both the CSS3 opacity and the IE-specific filter:alpha in this demo to ensure our code works for a greater number of users.

Backgrounds

CSS3 offers the ability to include multiple background images for a given element - use a comma-delimited list to specify as many as you like:

background-image:url(img1.gif), url(img2.png), url(img3.gif)

The order of the listed background images determines the position of the layer relative to the viewer, akin to the CSS z-index property: the first background image is on "top", the next below that, etc.

In similar fasion, specifying a comma-delimited list of background-position and/or background-repeat values assigns the position and repeat, respectively, for the multiple background images, as such:

div {
						background-image:url(img1.gif), url(img2.png), url(img3.gif);
						background-position:center top, right top, center bottom;
						background-repeat:no-repeat, repeat-x, repeat-y;
					}

In the example above, background image img1.gif is positioned center top and not repeated, img2.png is positioned right top and repeated horizontally, and img3.gif is positioned center bottom and repeated vertically.

Excess position or repeat values are ignored; that is, for an element for which three background images are specified and for which, say, four background-position values are set, the fourth set of position values would be ignored. If too few position or repeat values (i.e., fewer than the number of background images) are set, then the position or repeat values are repeated.

Specifying background-color when applying multiple background images applies the color as the final (lowest) background layer, behind all of the background images.

The background shorthand property is still available with multiple background images:

div {
						background:url(img1.gif) center top no-repeat, url(img2.png) right top repeat-x, url(img3.gif) center bottom repeat-y;
					}

CSS3 introduces three new background-related properties: background-clip, background-origin, and background-size. background-clip allows us to specify the painting area of the background - whether the background extends into the element's border. Possible values are:

background-clip values
Value Description
border-box Clipped to the element's border box (default)
padding-box Clipped to the element's padding box
content-box Clipped to the element's content box

background-origin specifies the background positioning area; that is, relative to what aspect of the element should the background image be positioned. Possible values are:

background-origin values
Value Description
border-box Relative to the element's border box
padding-box Relative to the element's padding box (default)
content-box Relative to the element's content box

background-size specifies the size of background image(s); possible values are:

background-size values
Value Description
length Width and height specified in pixels or ems; e.g., 10px 20px
percentage Width and height specified in percentage relative to the background positioning element; e.g., 50% 20%
cover Scale the background image, preserving its aspect ratio, to the smallest size such that both width and height completely cover the background positioning area
contain Scale the background image, preserving its aspect ratio, to the largest size such that both width and its height fit inside the background positioning area

The following example illustrates the background-clip, background-origin, and background-size properties.

Code Sample:

CssBackgroundTricks/Demos/background-clip-origin-size.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>CSS3 background-clip</title>
	<style>
		body {
			padding-left: 20px;
		}
		.bg {
			width: 250px;
			height: 150px;
			padding: 20px;
			margin-right: 20px;
			margin-bottom: 20px;
			float: left;
			background-color: #888;
			border: 10px dotted red;
			background-image: url('Images/chicago_small.jpg');
			background-repeat: no-repeat;
			color: #ff0;
		}
		div.bg:nth-child(2n + 1) {
			margin-right: 0;
		}
		div.bg code {
			background-color: rgba(0,0,0,0.45);
			padding: 3px;
			font-size: 14px;
			line-height: 20px;
		}
		#border {
			background-clip: border-box;
			background-origin: border-box;
		}
		#padding {
			background-clip: padding-box;
		}
		#content {
			background-clip: content-box;
		}
		#size {
			background-image: url('Images/chicago.jpg');
			background-origin: border-box;
			background-size: contain;
		}
		footer {
			clear: left;
		}
	</style>
</head>
<body>
	<div id="main">
		<h1>CSS3 <code>background-clip</code></h1>
		<div id="border" class="bg">
			<code>background-clip: border-box;</code>
			<br><code>background-origin: border-box;</code>
		</div>
		<div id="padding" class="bg">
			<code>background-clip: padding-box;</code>
		</div>
		<div id="content" class="bg">
			<code>background-clip: content-box;</code>
		</div>
		<div id="size" class="bg">
			<code>background-origin: border-box;</code>
			<br><code>background-size:contain;</code>
		</div>
		<footer>
			<p>Various <code>background-clip</code>, <code>background-origin</code>, and <code>background-size</code> examples</p>
		</footer>
	</div>
</body>
</html>

Code Explanation

The page presents four <div>s, each (including padding and border) 310px wide by 210px tall. Each <div> has a dotted red border, a dark-gray background, a not-repeated image background, and 20 pixels of padding:

background clip, position, size

The first (upper left) <div> specifies background-clip:border-box, which sets the background painting area to extend out to (under) the border, and background-origin:border-box, which positions the background image (the small photo of the Chicago skyline) relative to the edge of the border of the <div>.

The second (upper right) <div> specifies background-clip:padding-box - note that the gray background color extends up to, but does not sit under, the dotted border. Since it isn't specified, background-origin has here the default value padding-box; note that the background image is positioned up to (but not under) the border.

The third (lower left) <div> specifies background-clip:content-box, meaning that the background painting area does not extend into the <div>'s 20 pixels of padding.

Last, the fourth (lower right) <div> specifies background-origin:border-box, so that the background painting area extends up to (and under) the border of the <div>, and also background-size:contain, which sizes the background image as large as possible while still keeping it completely contained within the background painting area.

The next exercise asks you to put into use the concepts we've just reviewed.

Using HSL & Opacity

Duration: 15 to 25 minutes.

In this exercise, you will render a design that incorporates hsl and hsla color specifications and the CSS opacity property.

  1. Open ClassFiles/CssBackgroundTricks/Exercises/hsla-opacity/index.html in a text editor.
  2. Note that the markup for the page is done for you, as is some of the CSS coding.
  3. Tile the body with the image pattern_096.gif.
  4. Give the header and .photo elements a background color of #B7D3D9 with 50% opacity - convert the color to hsla using this tool.
  5. Set each photo's initial opacity to 50%. Note that we use max-width:100% for the two images, ensuring that the images will scale to smaller sizes if the browser width is reduced or if the page is viewed on a small-screen-size device.
  6. Center align all elements.
  7. Give the text in the caption a color of 50% black - use rgba.
  8. Use CSS's :target pseudo-class to highlight the user's selected element:
    • Set the photo to 100% opacity.
    • Set the background color of the .photo <div> to 100% opacity.
    • Set the color of the caption text to 100% black.
  9. Initially, before the user clicks anywhere, the page should look like this: opacity/hsla exercise
  10. Clicking on an image (the left one, in this example) should present the page like this: opacity/hsla exercise

Solution:

CssBackgroundTricks/Solutions/hsla-opacity/index.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>CSS3 HSL &amp; Alpha</title>
	<style>
		* {
			padding:0;
			margin:0;
		}
		body {
			padding-top: 1em;
			background-image: url('pattern_096.gif');
			background-repeat: repeat;
		}
		h1 {
			margin-bottom: 0.25em;
			text-align: center;
		}
		header {
			text-align: center;
			background-color: hsla(191, 31%, 78%, 0.5);
		}
		header p {
			padding: 2% 2% 0.5% 2%;
		}
		.photo {
			width: 44%;
			padding: 2% 3%;
			float: left;
			text-align: center;
			background-color: hsla(191, 31%, 78%, 0.5);
		}
		.photo img {
			max-width: 100%;
			opacity: 0.5;
		}
		.photo .caption {
			color: rgba(0,0,0,0.5);
		}
		div:target {
			background-color: hsla(191, 31%, 78%, 1.0);
		}
		div:target img {
			 opacity:1.0;
		}
		div:target .caption {
			color: rgba(0,0,0,1.0);
		}
		footer {
			text-align: center;
			clear: left;
		}
	</style>
</head>
<body>
	<h1>Two Photos</h1>
	<header>
		<p>A photo of a <a href="#cat">cat strangely sitting upright</a> and of <a href="#chicago">Millenium Park in Chicago</a></p>
	</header>
	<div id="cat" class="photo">
		<a href="#cat"><img src="cat.jpg"></a>
		<div class="caption">This cat seems to enjoy sitting upright</div>
	</div>
	<div id="chicago" class="photo">
		<a href="#chicago"><img src="chicago.jpg"></a>
		<div class="caption"><em>Cloud Gate</em> is a popular public sculpture</div>
	</div>
	<footer>
		<p>I am a footer</p>
	</footer>
</body>
</html>

Code Explanation

We set the specified elements' background color to hsla(191, 31%, 78%, 0.5) or hsla(191, 31%, 78%, 1.0) - for 50% and 100% opacity, respectively - to match the #B7D3D9 blueish tone.

We set an initial opacity:0.5 for the two photos.

We style the selected photo element via CSS's :target pseudo-class, changing the photo's opacity, the opacity of the element's background color, and the opacity of the caption text color.

Multiple Background Images with background-clip, background-origin, and background-size

Duration: 10 to 20 minutes.

In this exercise, you will

  1. Open ClassFiles/CssBackgroundTricks/Exercises/background-clip-origin-size/index.html in a text editor and in a browser.
  2. Note that the page holds a <div> with id bg; some of the styles for this <div> are already written for you in the <head> of the page.
  3. Style the #bg <div> to look like this: exercise screenshot
  4. Be sure to match the following features:
    1. A 10-pixel-wide, semitransparent, green border; use hsla to specify color
    2. The boardwalk.jpg background image fully covers the <div>, extending right up to the edge of the border of the element
    3. A second background image (grass.jpg) fill the width (but not the height) of the content area of the <div>

Solution:

CssBackgroundTricks/Solutions/background-clip-origin-size/index.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>CSS3 Background Clip, Origin, Size</title>
	<style>
		#bg {
			margin:auto;
			width:200px;
			height:150px;
			padding:20px 20px 200px 20px;
			border:20px solid hsla(90,100%,20%,0.5);
			background-image:url(grass.jpg), url(boardwalk.jpg);
			background-clip:content-box, border-box;
			background-origin: padding-box, border-box;
			background-size:100% auto, cover;
			background-repeat:no-repeat;
			text-align: center;
			color:#fff;
		}
	</style>
</head>
<body>
	<div id="main">
		<h1>CSS3 Background Clip, Origin, Size</h1>
		<div id="bg">
			This element has two background images
		</div>
	</div>
</body>
</html>

Code Explanation

We specify two background images; grass.jpg is listed first and, thus, sits on top of boardwalk.jpg.

We set the background painting area for each background image with a comma-separated pair of values for background-clip. grass.jpg gets a value of content-box and thus fills behind the text only; boardwalk.jpg gets a value of border-box and thus extends under the semitransparent border. Similarly, we set two values for background-origin to position the background images as specified.

Last, we set the size of the background images with background-size. grass.jpg is asked to fill the width of the space allocated to it (with a value of 100% auto) and boardwalk.jpg is asked to cover the whole element.