Chapter 3. Using Modernizr the Right Way

The Modernizr library is a tool that is built using JavaScript. Similar to the way that JavaScript can be used in a "wrong" and a "right" way, the same rules apply to Modernizr. By "wrong" and "right" I mean that it is very forgiving and will work whether implemented correctly or incorrectly. This chapter will be broken into phases or frames, and each frame will add something new to progress the experience. We'll focus on how a core experience can be enhanced by progression into more cutting edge features available in current cutting edge browsers.

I've always been a fan of the old 8-bit and 16-bit video games. So, I thought that would be a great look for something fun we can build. We'll start out with the first frame, building on our foundation of code that we made in the previous chapter. In the first frame we'll keep the look pretty close to that of the previous chapter, but this time round we'll feature detect to pull out the extra bits that can be done by more modern browsers. The following screenshot gives you a peek at our final video game built:

Using Modernizr the Right Way

By the end of this chapter when we reach frame five, we will have achieved the following:

  • A CSS cloud will be raining every feature that tested true
  • All images will have been replaced so that only CSS remains for the visuals

Frame 1 – swapping images for CSS

In this section, we will be doing the following:

  • Replace all core design images with CSS-only versions
  • Recreate the logo using CSS border radius, box shadow, and web fonts
  • Spice up the header logo using CSS gradients
  • Recreate the navigation tabs using CSS border radius
  • Replace the frame background using CSS gradients and background size
  • Begin building the video game's look and feel

The first set of feature testing we'll be doing is for CSS gradients and also background size. This will allow us to achieve identical look but free from the shackles of PNG images. Cutting down on the amount of images used on the page will free up resource overhead and allow faster page loads. We won't remove the need for images entirely just yet, but the main site elements will all be converted.

Keeping it WebKit, for now

Everything that we will be doing right now will be using the WebKit vendor prefix of webkit where needed, which will work in WebKit browsers such as Safari and Chrome. Then towards the end of the chapter, we'll make sure all the vendors are addressed and we'll fill in those as well. Sticking with just one vendor for now will keep things simple as we work to get to the point of progressive experiences.

The main elements—navigation, background, and logo—currently consist of stripes and curves. Both of which can be recreated with CSS.

The stripes

The stripes can be replicated using CSS gradients in tandem with background size. Before we can use something like that we'll want to know that it's available to be used. We have two options to do this: either use the HTML selectors added for us or use the JavaScript to test a combination of features and on success add new classes to the DOM elements.

The following code snippet gives a small example of how that would be accomplished with CSS in our stylesheet:

/* Method 1: Using the seasoned html elements and CSS. */	

#frame-1{
  ... Image version of striped background
}

.cssgradients #frame-1{
  ... CSS gradient version of striped background
}

The following code snippet gives an example of how the same effect can be accomplished in our JavaScript:

// Method 2: Using JavaScript to add a CSS class.
if( Modernizr.cssgradients ){
  //Use jQuery to season with the css class.
  $( "#frame-1" ).addClass("stripes");
}

We will then add the following stripes CSS class containing the gradient instructions for the earlier example:

/* CSS Stripe class to be added by JavaScript*/
.stripes{
   CSS Gradient info
}

With the new class added to the frame, the all new CSS version of the stripes will gracefully replace the original PNG image version.

Time to put this to practice. First we'll cover the navigation and then move into the first frame. Once that's completed we can move into adding fun with some visual elements.

In the stylesheet, I'll remove the background from the original frame class:

/* Structure class for each frame panel */
.frame{

  height: 700px;
  position: relative;
  border-bottom: dotted 5px #fff;
  background-color: #eee;
}

Also I'll create a CSS class called vert-stripe-img that will contain the background image removed from the frame, using the following code snippet:

.vert-stripe-img{
  //The original background image relocated to it's own class.
  background: url( images/grey-stripe.png );
}

And while we're at it, let's also create a similar class with the near identical look but using the CSS gradients and background size this time and naming it vert-stripe-gradient:

.vert-stripe-gradient{
  background-image: -webkit-linear-gradient(0deg,transparent 50%, #fff 50%);
  background-size:5px;
}

I'm going to make a slight modification to the earlier frame CSS class by removing the background image. I'll be doing this so that frame acts more like a structure class and not a structure and styling combination. Now all instances of the frame class in the code will be for the structure only.

As you can see by checking the results for gradient and background size support via JavaScript, we can toggle what type of background is displayed. If the support is available the PNG background is exchanged for the purely CSS gradient version. I've made the stripes of the CSS version a little bit wider, as shown in the following code snippet, so it's a little easier to distinguish which is in use for the purposes of these exercises:

$(document).ready(function(){
//Check for CSS Gradient and Background Size support.
// If both are present then switch to using the gradient version.
if( Modernizr.cssgradients && Modernizr.backgroundsize ){
  $('#frame-1').removeClass('vert-stripe-img').addClass('vert-stripe-gradient'),
  }
});

From this point forward, I'm going to automatically add the vert-stripe gradient class to the subsequent frame panels in the exercises ahead. This is intended more as a proof-of-concept and in the future frames we will assume that this feature exists. My goal is that by the end of this chapter the gears in your head will be turning, thinking about all the possibilities available to you with this library. Hopefully, this gives an idea about how to use feature detection to toggle based on this feature set. The preceding example uses JavaScript.

However, the same could be achieved using only CSS selectors and chaining them together, as seen in the following code snippet:

//The same effect achieved with CSS only.
#frame-1{
  background: url( images/grey-stripe.png );
}
//The background gradients achieved by chaining together the CSS classes.
.backgroundsize.cssgradients #frame-1{
  background-image: -webkit-linear-gradient(0deg,transparent 50%, #fff 50%);
  background-size:5px;
}

Doing this would achieve the same effect. By chaining together the two CSS classes, the browser will pick up and apply the gradients only if those two classes exist inside the HTML element. The effect of the preceding code snippet where we widened the stripes can be seen in the following screenshot:

The stripes

Now that we have stripes, let's do the same thing but using slanted stripes for the top navigation header on the page using the following code snippet:

//Image class for the striped navigation.
.nav-stripes-img{
 background: url( images/stripe-header.png ) 0 0 #333;
}

//Gradient class for the striped navigation.
.nav-stripes-gradient{
  background-size: 10px 10px;
  background-image:
-webkit-gradient(linear, 0% 0%, 100% 100%, 
  color-stop(25%, rgba(0, 0, 0, 0.1)), 
  color-stop(25%, transparent), 
  color-stop(50%, transparent), 
  color-stop(50%, rgba(0, 0, 0, 0.1)), 
  color-stop(75%, rgba(0, 0, 0, 0.1)), 
  color-stop(75%, transparent), 
  color-stop(100%, transparent));
  background-color: #333;
}

And naturally we need to add the controller that enables this gradient striped in the JavaScript. It will be virtually identical to the previous statement, as seen in the following code snippet:

<script>
$(document).ready(function(){

//Check for CSS Gradient and Background Size support.
// If both are present then switch to using the gradient version.
if( Modernizr.cssgradients && Modernizr.backgroundsize ){
    
// Remove the navigation header image based 
// stripes and replace with the CSS as well.
$('#navbar').removeClass('nav-stripes-img').addClass('nav-stripes-gradient'),
  }
}); //end document ready
</script>

With the JavaScript and CSS in place, the browser should now be showing the CSS gradient version of the stripes, which again are just a little bit wider than the image-based ones so they are visually easier to detect while we are testing features. That should about do it for the striped elements, which brings us to the curvy elements.

The curves

By curves I refer to the rounded parts, whether they be a full circle, like in the logo or a rounded edge, like without top tabs, which remind me a bit of cartoon piano keys. All of these are done with images for now but can be completely replicated using borderradius.

As this is a single feature dependency and not multiple, the previous example needed both, gradient support as well as background size support. We can do this much more easily using just the stylesheet we want without having to worry about the order of these special element declarations in the HTML tag. This is done by simply placing borderradius before whatever element we are targeting. I prefer to target with just CSS as much as possible because it keeps things simple and it's all done in a single file so it's easier to debug. Let's first start with the navigation tabs. I'm going to prepend a class of no-borderradius to the original, and also add in a border radius supported version, as seen in the following code snippet:

/* Navigation tabs using the current image based structure */
.no-borderradius #nav a{
  margin: 0 5px;
  line-height: 3em;
  color: white;
  font-size: 3em;
  text-decoration: none;
  font-family: 'Fredoka One', Arial;
  background: url( images/link-tabs.png ) no-repeat 0px 0 transparent;
  display: inline-block;
  height: 138px;
  width: 75px;
  text-align: center;
}
.no-borderradius #nav a:hover{
  color: black;
  background-position: -75px 0;
}

/* Navigation now using only CSS if borderradius is supported */
.borderradius #nav a{
  padding: 50px 20px 30px 20px;
  margin: 0 10px;
  background: #333;
  height: 100px;
  border-bottom-right-radius: 10em;
  border-bottom-left-radius: 10em;
  box-shadow: 6px 0px 0 #999;
  line-height: 3em;
  color: white;
  font-size: 3em;
  text-decoration: none;
  font-family: 'Fredoka One', Arial;
}
.borderradius #nav a:hover{
  color: #eee;
  background: black;
}

Last but not least, let's recreate the grey underneath the tabs with box-shadow using another CSS declaration, as seen the following code snippet:

/* Progressively add a box-shadow to the navigation tabs */
.boxshadow #nav a{
  box-shadow: 6px 0px 0 #999;
}

And as simple as that we have a default version of the navigation tabs and a progressive version using border radius support. If you want to see the difference between the two versions, simply edit the element in your browser console, prepend no- to the borderradius and box-shadow properties, and that's it!

Speaking of borders, before we convert the circle in the logo to CSS, let's first convert the logo banner to CSS as well. We can achieve this with a little trickery using the border property. However we'll need to do a bit of adding of some div elements, as seen in the following code snippet, to make this possible:

<!--  The HTML markup for CSS version of the logo  -->
<div id="logo">
<div class="logo-inner">
  <div class="circle">M</div>
  </div>
 </div>

This varies a bit from the original that was simply a single div element with an id field of logo. Again we have one of two options. We can either add the additional HTML and use only the stylesheet or add the new HTML via JavaScript and then use CSS to target everything.

I'm going to use JavaScript this time because I don't like having extra DOM nodes in my markup if I don't need to. Plus, the logo will look just fine should the feature be false, or even if the JavaScript was disabled (although that would be a real buzz kill for Modernizr). The HTML in use is as follows:

$(document).ready(function(){

//Add inner html to the logo	div if border radius is supported.
  if( Modernizr.borderradius ){
  
    var innerHtml = '<div class="logo-inner">';
        innerHtml += '<div class="circle">M</div>';
        innerHtml += '</div>';
    $('#logo').html(innerHtml);
  }

}); //end of document ready

And then of course the CSS styles to follow suit:

/* Logo */  
.no-borderradius  #logo{
  position: absolute;
  width: 70px;
  height: 110px;
  background: url(images/logo.png);
  top: -5px;
  left: 10%;

}

.borderradius #logo{
  position: absolute;
  left: 10%;
  width: 0;
  height: 70px;
  border-left: 35px solid #999;
  border-right: 35px solid #999;
  border-bottom: 35px solid transparent;

}

.borderradius #logo .logo-inner{

  position: absolute;
  width: 0;
  height: 70px;
  border-left: 32px solid black;
  border-right: 32px solid black;
  border-bottom: 32px solid transparent;
  left: -32px;
  top: -5px;

}

.borderradius #logo .logo-inner .circle {

  border-radius: 50%;
  border: solid 2px #999;
  width: 50px;
  height: 50px;
  text-align: center;
  line-height: 50px;
  color: white;
  font-size: 30px;
  position: absolute;
  left: -27px;
  top: 10px;	
  font-family: 'Fredoka One', Arial;

}

Like earlier there is a no- state to handle the feature not being supported and additional styles for the newly added DOM elements, logo-inner and circle.

Some key things have taken place here. The banner that holds the circular logo has been replicated with CSS using a border trick. You have seen a border consists of four edges and in this instance the div element itself isn't actually shown, merely its borders. The bottom border is set to transparent and the two sides are set to display, which is what creates that triangular effect and gives us a banner type look. The logo container div is doing the exact same thing, which is what gives it a nice grey edge. Nested inside all of this is the circle, which is achieved with borderradius. A circle can be created by setting the width and height of a block-level element to be identical to each other and then applying a borderradius property of half or in our case 50 percent.

Only one last progression is remaining and then we can move onto the graphics and other bits that we'll be building on in each additional frame panel. Let's add a little bit of polish to the logo by way of a radial gradient. Until now we've been using variations on linear gradients, so let's see what we can do with the radial version:

/* Add a bit of polish to the logo using a radial gradient to mimmic reflection */
.cssgradients #logo .logo-inner .circle{

 background: -webkit-radial-gradient(circle, rgba(216, 216, 216, 0.84), black);

}

Now the logo has a radial gradient, which mimics a light reflection and gives it a more three-dimensional quality. Now, not only is the entire code base able to deliver the identical experience using both images and CSS, but additionally we've done some subtle enhancements by adding a gradient to the logo, as seen in the following screenshot:

The curves

Now that the core has a core and progressive version we can move on to the content within these frame panels and do even more really cool and fun things.

Clouds

The first thing I'd like to do is add some clouds behind the Modernizr headline. The HTML is as follows:

<hgroup>
   <h1 class"title">Modernizr</h1>
   <h2 class="subtitle">The feature detection library.</h2>
</hgroup>
  <div class="mini-cloud mini-cloud-l"></div>
  <div class="mini-cloud mini-cloud-r"></div>

The clouds are the same graphics we had seen earlier and as you probably must have noticed, looking at the selectors in the following code snippet there is a left and right cloud. Let's look at the CSS for them:

/* Mini clouds */
.mini-cloud{
  background: url(images/cloud.png) no-repeat 0 0 transparent;
  width: 162px;
  height: 104px;
  position: absolute;
}

/* Left position of mini cloud */
.mini-cloud-l{
  left: 34%;
  top: 250px;
}

/* Right position of mini cloud */
.mini-cloud-r{
  left: 55%;
  top: 278px;
}

I'm also going to bump the headers down a bit from the top of the page to get the alignment of all the visual elements into a better state of balance. The following code snippet will move everything into the vertical center of the frame:

/* Same as before but altering the position from top */
h1{
  font-family: 'Fredoka One', Arial;
  padding-top: 10%;
  font-size: 4em;
  color: #D91E76;
  top: 154px;
}

h2{
  font-family: 'Squada One', Arial,cursive;
  color: #333;
  top: 165px;
}

Finally let's really add the Modernizr logo above the clouds; it will sit just above the h1 tag and rest on it just like a cake topper would on a delicious three-tiered cake.

Here is the HTML. This time I'm using an inline img element because I'd like to cover as many bases as possible in these exercises. More commonly one might use a CSS background image, even merged with other images as a sprite to reduce HTTP requests. We'll do something a bit like that later with feature detection, but right now an inline image will do just nicely, as seen in the following code snippet:

<!--  The html for the logo -->
<div id="modernizr-logo">
 <img src="images/modernizr-logo.png" >
</div>

The CSS styles for the logo, more or less positioning it within the frame panel using the following code snippet:

/* Modernizr logo, more or less positioning it within the frame */
#modernizr-logo{
  position: relative;
  width: 125px;
  margin: 0 auto;
  height: 60px;
  top: 15px;
  z-index: 3;
}

If everything went according to plan, the logo should now look something like the following screenshot:

Clouds

That's a pretty good stopping point. So far we've replaced all of the navigation and background with a pure CSS3 version using WebKit, just CSS selectors, and JavaScript partnered with CSS. After that we swapped the logo with a purely CSS version using JavaScript and spiced up the logo with a radial gradient. After this was achieved we started on the actual content of the page by adding in some clouds and the official Modernizr logo.

In the subsequent sections, frames we will be building on this current look and feel by adding in even more style elements that leverage the CSS classes, and once that's done we will start playing around with the new features we have by changing the look and experimenting with the gradients a bit more. The last two frames in particular will be focused more on having some fun with the newer features once they have been detected, although they will also bring some new things to the table.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset