Sign up for a free trial of our self-paced courses.

Advanced CSS Tutorial

CSS Background Tricks

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

  • To create fixed-width rounded corner boxes.
  • To create relative-width rounded corner boxes.
  • To create "mountaintop corners" on boxes.
  • To create tabbed navigation.
  • To create drop shadow effects.
  • To create CSS sprites.

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. Unfortunately, until CSS3 is released and supported, designers who want rounded corners may be forced to compromise on semantic HTML markup.

For more information about rounded corners in CSS3, see The 'border-radius' properties of CSS Backgrounds and Borders Module Level 3.

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:

Syntax

<div id="box">
	<div class="bgTop"><!--for IE6*--></div>
		<div class="content">
			content goes here
		</div>
	<div class="bgBottom"></div>
</div>

In IE6, the height property is ignored on an element has no content in it. By adding the <!--for IE6*-->< comment, we make sure IE6 honors height property.

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:

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

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

div { border:1px dashed #f00; }

The result:

In the next example, the HTML markup is the same, but his 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:

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

And here it is with the dashed border to show how the sections are broken out:

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:

Syntax

<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</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):

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

If the white space between the corners of the blue circle image could be removed, you would get a circle. You could do that and this sample would still work. We've separated the corners for illustrative purposes.

Code Sample:

CssBackgroundTricks/Demos/FlexibleRoundCornerBox.html
---- C O D E   O M I T T E D ----
<style type="text/css">
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:20px 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>

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:
  • 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 early versions of Internet Explorer to render the box correctly. For a good explanation on this, see http://www.satzansatz.de/cssd/onhavinglayout.html

Here the result shown with two different widths:

Unfortunately, as the screenshot below shows, Internet Explorer 6 has a problem with this method for creating rounded corners:

Notice the right border where the two arrows are pointing. These extra lines are a result of the right border assigned to the "content" div. They don't always show up. It depends on the actual width of the box, which of course is dynamic.

It's possible to create rounded-corner boxes with flexible widths that do work in Internet Explorer 6 by having the borders fade into the background like this:

The code for this, which is in CssBackgroundTricks/Demos/FlexibleRoundCornerBox2.html, is almost identical. The only differences are

  1. The magnified background image looks like this (notice the corners are filled in). The center is transparent:
  2. The body and the "content" div have background colors (blue and white, respectively).
  3. In the bg class, the background color of all the spans has been set to "transparent". This makes it possible to change the background color of the "content" div without having to adjust anything else.

Mountaintop Corners

In an A List Part article, Dan Cederholm introduced another way to created 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:

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

As you can see, it looks like a hole so 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:

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:

And here is the code:

Code Sample:

CssBackgroundTricks/Demos/mountaintop.html
---- C O D E   O M I T T E D ----
<style type="text/css">
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>

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 use -1px for the positioning to push the span tags 1 pixel outside of the containing box. This is to fix the bug we saw earlier in Internet Explorer 6. If you don't need to support IE6, you can set those values to 0px.
  • 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}.

There are other ways of creating boxes with rounded corners. For a slew of different methods, see http://www.cssjuice.com/25-rounded-corners-techniques-with-css.

Tabbed Navigation

The screenshot below shows and example of a page that uses 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 type="text/css">
#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 {
	position:relative;
	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>

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 that the three states of the menu items. The magnified background images used are shown below:

Each image is 6 pixels wide by 37 pixels high.

Drop Shadows

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 type="text/css">
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>

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:

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

That's it. As you can see, creating drop shadow effects is relatively easy.

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):

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

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 ----

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 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.