Read in english (Automatic translate wiht Google)
All techniques to reduce render time are important. One of the best way to reduce HTTPRequest is using CSS-Sprite.
In this tutorial I will teach how to create a horizontal menu with this technique.
Step 1
Studies show that 80% of the time display of a page are spent in frontend (High Performance Web Sites is a really important book on the performance subject). We can reduce render time when had less HTTPRequest's, that means less number of css files, js files and other assets like images should reduce the render time. But the question is, How reduce number of images without lost design? CSS-Sprite is a good option. Our first step is slice the menu in a big image with all possible states like hover and normal. The designer create the layout below and the first step is evaluate the design we have.
Step 2
If we look carefully we can see that we have a tab with focus and others without, which is that we have 6 image files, 1 file for each focused image (focus represent current page and roll hover of mouse) and other 1 file for each no focus image. But with CSS-Sprite we can reduce all images of menu in only one image, this reduce the number of HTTPRequest and improve perfomance. We need slice the menu like below:
Step 3
In Step 2 we create our sprite of menu (the only image of menu have all items with rollover and rollout states). Now is time to jump for XHTML and CSS. We need create a simple XHTML file and one div for header, like below:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CSS-Sprite</title>
<link rel="stylesheet" href="application.css"/>
</head>
<body>
<div id="header_wrapper"></div>
</body>
</html>
|
Step 4
Now we must create the application.css file. In our css file we configure the TypeSelector body with background-color and create an IdSelector called of #header_wrapper, this selector will have properties like background-image, width of 100% and height of 90px.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@charset "utf-8";
/* CSS Document */
body{
background-color:#f0eee1;
margin:0;
padding:0;
}
#header_wrapper{
background:url(images/header_bg.jpg) repeat-x;
height:90px;
width:100%;
}
|
Step 5
Now it's time to create a div called of header, this guy will be the container for centralized content, in this case, image logo and menu container. To centralize the header we use the "margin: 0 auto;" in #header selector. That means our header will have 0 of margin top and all other margins will be caculated automatically, other important detail is height and width values. Our html file and css will be like this:
index.html
1
2
3
4
5
6
7
8
|
<body>
<div id="header_wrapper">
<div id="header">
<img src="images/logo.jpg"/>
</div>
</div>
</body>
|
application.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@charset "utf-8";
/* CSS Document */
body{
background-color:#f0eee1;
margin:0;
padding:0;
}
#header_wrapper{
background:url(images/header_bg.jpg) repeat-x;
height:90px;
width:100%;
}
#header{
margin:0 auto;
width:760px;
}
#header img{float:left;} /*image of logo will be left aligned*/
|
Step 6
Finaly the step of menu. First thing we need to do is create a div for menu, we set the id propertie to "menu". Now place a "ul" tag inside menu div, this tag will create the horizontal menu effect. In css file we create the selector for menu div like below:
application.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@charset "utf-8";
/* CSS Document */
body{
background-color:#f0eee1;
margin:0;
padding:0;
}
#header_wrapper{
background:url(images/header_bg.jpg) repeat-x;
height:90px;
width:100%;
}
#header{
margin:0 auto;
width:760px;
}
#menu ul { width:300px; height:90px; margin:0 auto; padding: 0; list-style-type: none;}
#menu li {float: left; display: inline;}
#menu a {text-decoration: none;}
#menu span {display:none;}
|
In above css code we specify "ul" tag inside "#menu", it will have 300px of width(the total size of our menu), 90px of height and set the "list-style-type" of "ul" tag for "none", that means the "ul" will not have any bullet for items. With "#menu li" tag all list items("li" tags) will be showed inline and align on left. To finalize this step with remove the decoration of "a" tag and hide the "span" tags.
Step 7
Now is time to create "li's" and "a" inside ul, like below:
1
2
3
4
5
6
7
8
9
10
11
|
<div id="header">
<img src="images/logo.jpg"/>
<div id="menu">
<ul>
<li><a href="#" class="home"><span>HOME</span></a></li>
<li><a href="#" class="projects"><span>PROJECTS</span></a></li>
<li><a href="#" class="contact"><span>CONTACT</span></a></li>
</ul>
</div>
</div>
|
Step 8
In this step start the secret of css-sprite technique. We use the same image to create all background's of menu items. Take a look in the css code below:
1
2
3
4
|
#menu a.home {width: 101px; height: 90px; background:url(images/menu.jpg) 0px 0px no-repeat;}
#menu a.home:hover {background:url(images/menu.jpg) 0px -90px no-repeat;}
#menu li.current a.home {background:url(images/menu.jpg) 0px -90px no-repeat;}
|
The above code represent when "a" inside the "menu" div tag has "home" class it will have size of 101x91 pixels and background image("images/menu.jpg") will be posicioned at 0 x of background-image and 0 y of background-image, respectively . But if you see the a.home:hover and li.current the background position of y is -90, that means the background image will be positioned on the part of hover in our menu sprite image.
Step 9
Repeat the last step other 2 times but recalculate the position of background-image, lik below:
1
2
3
4
5
6
7
8
|
#menu a.projects {width: 100px; height: 90px; background:url(images/menu.jpg) -100px 0px no-repeat;}
#menu a.projects:hover {background:url(images/menu.jpg) -100px -90px no-repeat;}
#menu li.current a.projects {background:url(images/menu.jpg) -100px -90px no-repeat;}
#menu a.contact {width: 101px; height: 90px; background:url(images/menu.jpg) -200px 0px no-repeat;}
#menu a.contact:hover {background:url(images/menu.jpg) -200px -90px no-repeat;}
#menu li.current a.contact {background:url(images/menu.jpg) -200px -90px no-repeat;}
|
Step 10
Our final html and css files are:
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CSS-Sprite</title>
<link rel="stylesheet" href="application.css"/>
</head>
<body>
<div id="header_wrapper">
<div id="header">
<img src="images/logo.jpg"/>
<div id="menu">
<ul>
<li class="current"><a href="#" class="home"><span>HOME</span></a></li>
<li><a href="#" class="projects"><span>PROJECTS</span></a></li>
<li><a href="#" class="contact"><span>CONTACT</span></a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
|
application.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
@charset "utf-8";
/* CSS Document */
body{
background-color:#f0eee1;
margin:0;
padding:0;
}
#header_wrapper{
background:url(images/header_bg.jpg) repeat-x;
height:90px;
width:100%;
}
#header{
margin:0 auto;
width:760px;
}
#header img{float:left;}
/*** MENU ***/
#menu {height:90px; float:right;}
#menu ul { margin:0 ; padding: 0; list-style-type: none;}
#menu li {float: left; display: inline;}
#menu a {float: left; display: inline; text-decoration: none;}
#menu span{display:none;}
/* MENU - HOME */
#menu a.home {width: 101px; height: 90px; background:url(images/menu.jpg) 0px 0px no-repeat;}
#menu a.home:hover {background:url(images/menu.jpg) 0px -90px no-repeat;}
#menu li.current a.home {background:url(images/menu.jpg) 0px -90px no-repeat;}
/* MENU - PROJECTS */
#menu a.projects {width: 100px; height: 90px; background:url(images/menu.jpg) -100px 0px no-repeat;}
#menu a.projects:hover {background:url(images/menu.jpg) -100px -90px no-repeat;}
#menu li.current a.projects {background:url(images/menu.jpg) -100px -90px no-repeat;}
/* MENU - CONTACT */
#menu a.contact {width: 101px; height: 90px; background:url(images/menu.jpg) -200px 0px no-repeat;}
#menu a.contact:hover {background:url(images/menu.jpg) -200px -90px no-repeat;}
#menu li.current a.contact {background:url(images/menu.jpg) -200px -90px no-repeat;}
|
Conclusion
In perfomance point of view we can reduce the size of final css file but the objective of this tutorial is teach the CSS-Sprite way to create tab-menus. With less than 11 steps you can reduce the number o image files and HTTPRequests, this technique can be used with any other group of images like icons or buttons. To reforce the perfomance subject in frontend development read the "High Performance Web Sites" book.
I hope you enjoyed this tip.
23/05/2008 em 02:28 PM
I think the first menu item should read: #menu a.home {width: 101px; height: 90px; background:url(images/menu.jpg) 0px 0px no-repeat;} #menu a.home:hover {background:url(images/menu.jpg) 0px -90px no-repeat;} #menu li.current a.home {background:url(images/menu.jpg) 0px 0px no-repeat;} or else the hover is always on the “home” button.
23/05/2008 em 09:39 PM
@Chuck, we change each menu item and the hover of each class is diferent and this reproduce the exactly effect we want. Hover and Current had the same properties because we wan’t the same effect.
Download the source file and take a look on the final result. Bye.