CSS3 is a hot topic these days. Designers and developers are starting to widely utilize CSS3 and new tutorials are popping up nearly everyday. As a designer it is an exciting time to be at the forefront of it’s development. There are, however, many designers and developers that see browser support for CSS3 as insufficient. In their defense, not all clients are open to letting their websites look moderately different from browser to browser.

Thankfully Faruk Ateş, Paul Irish and Alex Sexton have developed a script, Modernizr, that detects CSS3, as well as HTML5, browser support and allows us to take advantage of CSS3 in compatible browsers while providing alternative fallbacks to incompatible browsers. The script adds a unique class to the <html> element of a page specific to each CSS3 property supported. As an example, in browsers that support CSS3 border radius a class of borderradius will be added to the <html> element, while in browsers without support for CSS3 border radius a class of no-borderradius will be added to the <html> element. This opens up a world of opportunities, giving us just what we need to fully implement CSS3 without worrying about incompatible browsers.

View a Sample CSS3 Menu with Fallbacks

Putting Modernizr & CSS3 to Use

I built the following sample navigation to demonstrate how Modernizr works with CSS3 and how to build out fallbacks for incompatible browsers. With the help of Modernizr, the benefits of this navigation include:

  • 100% compatible with all browsers
  • No images and no flash for modern browsers with CSS3 support
  • One image for depreciated browsers without CSS3 support

Step 1: The HTML Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html class="no-js" lang="en">
  <head>
    <meta charset="utf-8">
    <title>CSS3 Navigation</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <h1>Sample Navigation</h1>
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About Us</a></li>
      <li><a href="#">Our Services</a></li>
      <li class="last"><a href="#">Contact Us</a></li>
    </ul>
    <script src="modernizr-1.7.min.js"></script>
  </body>
</html>

The HTML here is pretty cut and dry. We have the basic structure of an HTML5 document, including a heading and an unordered list with a set of links. A few things to note here:

  • The no-js class on the <html> element
  • The last class on the last <li> element within the unordered list
  • The Modernizr script included at the bottom of the document

Once we include the Modernizr script at the bottom of the document we need to set it into action with adding the no-js class to the <html> element. The last class on the last <li> element is in place for older browsers which do no support the :last-child pseudo-class.

Step 2: Adding General Styles to the Heading

1
2
3
4
5
6
7
h1 { 
  color: #222;
  font-size: 15px; 
  line-height: 36px; 
  margin: 0;
  padding: 0 10px;
}

Before we jump into the CSS3 and specific property support we declare the general styles for the heading.

Step 3: Declaring Heading Styles for Browsers with CSS3 Support

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.cssgradients h1 { 
  background: -moz-linear-gradient(#f5f5f5, #d9d9d9);
  background: -webkit-gradient(linear, left top, left bottom,
        from(#f5f5f5), to(#d9d9d9));
  border: 1px solid #bbb;
  -moz-border-radius: 4px 4px 0 0; 
  -webkit-border-radius: 4px 4px 0 0;
  border-radius: 4px 4px 0 0;
  -moz-box-shadow: inset 0 1px 0 #fff; 
  -webkit-box-shadow: inset 0 1px 0 #fff;
  box-shadow: inset 0 1px 0 #fff;
  height: 34px;
  width: 198px;
}

First up we use the Modernizr class of cssgradients to target browsers who specifically support this CSS3 property. Equally, we could use a borderradius or boxshadow class since we will be using these properties as well. We will be using CSS3 gradients later on so we will choose the cssgradients class to keep everything consistent.

Within this CSS3 please note that we are using the old WebKit gradient syntax. The new WebKit gradient syntax will mirror that of the Mozilla syntax however at the time of publish the new syntax is only viewable within the WebKit Nightly builds.

Step 4: Declaring Heading Styles for Browsers without CSS3 Support

1
2
3
4
5
.no-cssgradients h1 { 
  background: url("bg.png") 0 0 no-repeat;
  height: 36px;
  width: 200px;
}

To target browsers without CSS3 gradient support we use the no-cssgradients class. In place of all of the CSS3 declarations we used before we now use a background image instead.

Step 5: Adding General Styles to the Unordered List & Links

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
ul { 
  list-style: none;
  margin: 0;
  padding: 0;
  width: 220px;
}

a {
  border: 1px solid #bbb; 
  border-bottom: 1px solid #ccc;
  border-width: 0 1px 1px 1px;
  color: #3690cf;
  display: block; 
  font-weight: bold; 
  line-height: 30px; 
  padding: 0 10px; 
  text-decoration: none;
  -moz-transition: all .25s ease-in-out;
  -webkit-transition: all .25s ease-in-out;
  transition: all .25s ease-in-out;
}

a:hover {
  background: #fff;
  color: #222;
  padding: 0 10px 0 18px;
}

As with our heading before, we will declare all of the general styles for the unordered list and links. These styles apply to all browsers and are unspecific to browsers with or witout CSS3 support.

Within the <a> element CSS rule set we use the CSS3 transition property. This property will be ignored by browsers that do not support it however using it here will prevent us from having to use another CSS rule set specific for CSS3 links. Additionally it is worth noting that the transition value is set to all, which will transition all of our priorities including color, background-color, padding, opacity, and more.

Step 6: Declaring Unordered List & Link Styles for Browsers with CSS3 Support

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
.cssgradients li {
  background: -moz-linear-gradient(#fff, #f2f5f5);
  background: -webkit-gradient(linear, left top, left bottom,
        from(#fff), to(#f2f5f5));
  position: relative;
}

.cssgradients a:before {
  border-bottom: 4px solid transparent;
  border-left: 4px solid #666;
  border-top: 4px solid transparent;
  content: "";
  display: block;
  height: 0;
  left: 10px;
  opacity: 0;
  position: absolute;
  top: 11px;
  width: 0;
}

.cssgradients a:hover::before {
  opacity: 1;
}

.cssgradients li:last-child a {
  border: 1px solid #bbb;
  border-width: 0 1px 1px 1px;
  -moz-border-radius: 0 0 4px 4px;
  -webkit-border-radius: 0 0 4px 4px;
  border-radius: 0 0 4px 4px;
}

Keeping in pace with our cssgradients class for CSS3 support we declare all of our styles for the unordered list and links. Here we kick things up a bit with different pseudo classes and elements, along with a combining the :before pseudo-element with the :hover pseudo-class.

We start this block of code by declaring our styles for the <li> element, including a CSS3 gradient and a position of relative. You may wonder why we are declaring a gradient background on the <li> element and not the <a> element. The reason for this is because CSS3 background gradients are seen as background images and we are currently unable to transition a background image within CSS3. What we have done is declared a background gradient on the <li> element and then declared a solid background color to the <a> element upon hover. This way the <a> elements background will transition on top of the <li> elements background gradient giving the impression that the gradient is smoothly transitioning into a solid white. The relative position on the <li> element is necessary to properly position our arrow, which we will build next with all CSS.

We use the :before pseudo-element to attach the arrow to the beginning of all of the links. Building the arrow using CSS borders is not too difficult and is actually pretty fascinating. We do set an opacity of 0 to the arrow to hide it until hovered upon. We then combine the :before pseudo-element with the :hover pseudo-class to display arrow when a link is hovered over by setting the opacity to 1. Right now we could technically combine the two rule sets into one under the .cssgradients a:hover::before selector and omit the opacity property altogether since the transition property does not yet apply contents of the :before pseudo-element. However we have left them separate because transition support for the :before pseudo-element is coming and when available the opacity property will provide the perfect transition.

Lastly, we use the :last-child pseudo-class to select the last <li> element and round the bottom corners and change the border.

Step 7: Declaring Unordered List & Link Styles for Browsers without CSS3 Support

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.no-cssgradients a {
  background: url("bg.png") 0 -36px no-repeat;
  height: 30px;
}

.no-cssgradients a:hover {
  background: url("bg.png") 0 -66px no-repeat;
}

.no-cssgradients li.last a {
  background: url("bg.png") 0 -96px no-repeat;
  border: none;
  height: 31px;
}

.no-cssgradients li.last a:hover {
  background: url("bg.png") 0 -127px no-repeat;
}

Finally to wrap everything up, and to provide a fallback for browsers without CSS3 support, we use the no-cssgradients class. Using this class we use a background image fallback for the CSS3 gradients, border radius, and pseudo classes and elements.

Wrapping Up

View a Sample CSS3 Menu with Fallbacks

Hopefully this short tutorial has opened you up on how to use CSS3 while still providing support for older browsers. Modernizr is a fantastic tool and can be used far wider than what has been outlined here.