
CSS3 has come a long way since it was first introduced and there are so many features that can help you to achieve great things – and there’s still plenty more to look forward to. Not so long ago, it felt like we were hiding behind the lack of cross-browser compatibility to avoid learning new techniques – techniques that would actually dramatically improve our workflow and enhance our webpages.
Not anymore, as CSS animations are finally available in all major browsers, even in Internet Explorer (since version 10), so now we don’t need to hide behind anything anymore. We can achieve many things just through using CSS.
So what we’re going to do in this tutorial is use the Google images results page as inspiration and create an expanding image preview grid that will also be responsive. The expanding image preview grid can be used for anything you like, but for our purposes we’ll assume this is for advertising a pixel-art game to potential new users. The idea here is that when you click on the images, you will be presented with more information about the game underneath. So, let’s get started!
Get ahead
The first step is to create a new HTML5 file and then add the meta information within the head section. What we need to make sure of is that we have the ‘viewport’ meta tag included for when we make this responsive, as well as the IE conditional for the HTML5 shiv. Lastly we’re going to add in a Modernizr file.
001 <head> 002 <meta charset=”UTF-8” /> 003 <meta http-equiv=”X-UA-Compatible” content=”IE=edge,chrome=1”> 004 <meta name=”viewport” content=”width=device-width, initial-scale=1.0”> 005 <!--[if IE]> 006 <script src=”http://html5shiv.googlecode.com/svn/trunk/html5.js”> </script> 007 <![endif]--> 008 <title>Grid Thumbnails</title> 009 <link rel=”stylesheet” type=”text/css” href=”css/main.css” /> 010 <script src=”js/modernizr.custom.js”> </script> 011 </head>
Section grid
In this step, we’re going to start adding in some HTML for our product’s content. In between the ‘body’ tag we’re going to add a ‘section’ element that will be used as a wrapper and then within that we will create an ‘article’ element. We then give our article element an ID name of ‘01’ and this will, of course, be our first product.
001 <section> 002 <article id=”01”> 003 </article> 004 </section>
Expand the HTML
Now that we have the article element added, let’s go ahead and add some more HTML that will allow us to add in the necessary content. The first bit of content will be our images. Within the anchor element we’ll add a target ID of ‘#01’ so when we click the image, the browser will move up accordingly. Everything else is straightforward.
001 <section> 002 <article id=”01”> 003 <a href=”#01”><img src=”images/ cover01.jpg” /></a> 004 <div class=”info”> 005 <div class=”description”> 006 <h1></h1> 007 <p></p> 008 </div> 009 </div> 010 </article> 011 </section>
List and more button
We have almost finished our skeleton HTML for our first product, and all we need to do now is add in an unordered list and another anchor tag for a ‘learn more’ button that we will position at the bottom of our product description. We give this button a class name of ‘moreBtn’ and in the next step we will add in all the content that is needed.
001 <a href=”#01”><img src=”images/cover01.jpg” /></a> 002 <div class=”info”> 003 <div class=”description”> 004 <h1></h1> 005 <p></p> 006 </div> 007 <ul> 008 <li></li> 009 <li></li> 010 <li></li> 011 </ul> 012 <a class=”moreBtn” href=”#”></a> 013 </div>
The image content
Let’s finish up our HTML by adding in the content to the markup we added in the last few steps. Firstly we need to give our product description a title. As this will be our first product, it would make sense to call this ‘Product #01’. Then, using some dummy text (Lorem Ipsum), we can populate the rest of our product description. Now copy and paste this HTML 15 times or more.
001 <article id=”01”> 002 <a href=”#01”><img src=”images/cover01.jpg” /></a> 003 <div class=”info”> 004 <div class=”description”> 005 <h1>Product #1</h1> 006 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In in massa ultrices diam lobortis convallis quis in risus. Phasellus a augue vitae sapien condimentum condimentum quis at eros. In nisl lacus, pharetra nec commodo quis, accumsan ac sapien.</p> 007 </div> 008 <ul> 009 <li>Lorem ipsum dolor</li> 010 <li>Consectetur adipiscing</li> 011 <li>Fringilla libero</li> 012 </ul> 013 <a class=”moreBtn” href=”#”> learn more</a> 014 </div> 015 </article>
Article white space
When using the ‘article’ element, we must ensure that we leave no whitespace in between the last closing article element and the next open one. This is because we will be changing the layout of these elements using ‘display: inline-block’ and whitespace will cause a 4px gap in between each element when the page is rendered. Also, make sure when you’ve copied and pasted each article element, you change the article ID and anchor target ID.
001 </div> 002 </article><article id=”02”> 003 <a href=”#02”><img src=”images/cover01.jpg” /></a>
The CSS reset
Now create a new CSS file, call it ‘styles.css’ and save it within a new folder called ‘CSS’. Then at the very top we are going to add in a CSS reset. The most popular one is Eric Meyer’s, which you can find at meyerweb.com/eric/tools/css/reset but the one thing you’ll want to add to this is the ‘box-sizing’ reset.
001 *, *:after, *:before {
002 -webkit-box-sizing: border-box;
003 -moz-box-sizing: border-box;
004 box-sizing: border-box;
005 }
The body section
Firstly we give our body some default styling and then the section element will be used as a container. We want the maximum width to be no more than a 1,000px wide. This will allow us to have enough room to fit at least three images across the screen. We then centre the grid using ‘margin: 0 auto’ and just in case we need to position anything absolutely, we can set its position to ‘relative’.
001 body {
002 font-family: Arial, sans-serif;
003 color: #aaaeb2;
004 background: #f1f1f1;
005 }
006 section {
007 max-width: 1000px;
008 margin: 0 auto;
009 position: relative;
010 }
011
Section article
We’re going to set the product images to ‘inline-block’, which will force them to sit side by side but also act as blocks, so we can specify their width and height properties. We then make sure they are vertically aligned to the top of their row and give them a 50 per cent width to help make these more responsive for when we finally add the media queries to our CSS.
001 section article {
002 vertical-align: top;
003 display: inline-block;
004 width: 50%;
005 margin-bottom: -4px;
006 }
007
Style the content images
Each image will be set to 100 per cent of its containing element, which will be our ‘article’ element. The height will be based on its width to maintain its aspect ratio. Lastly we will give it a 4px padding all around to allow us some breathing space in between each image.
001 section img {
002 width: 100%;
003 height: auto;
004 padding: 4px;
005 }
Style the information
The information that will be shown underneath our product images after we have clicked the image will be set to 150 per cent wide and hidden. We will also add some padding and margin to give the content some breathing space and then float it to the left.
001 section .info {
002 width: 150%;
003 padding: 3em 0;
004 margin: 0 10%;
005 position: relative;
006 float: left;
007 opacity: 0;
008 height: 0;
009 font-size: 0;
010 }
Product content styles
Let’s now add some styles to our product information. Firstly we’ll make sure we use ‘em’ values here so everything can become scalable for when we make this responsive. We will give our product title some bottom margin and then combine the ‘p’ and ‘ul’ elements to the same rule and give them some bottom margin and then set the ‘line-height’ to 140 per cent.
001 section .info h1 {
002 margin-bottom: .5em;
003 }
004 section .info p,
005 section .info ul {
006 margin-bottom: 2em;
007 line-height: 140%;
008 }
List styles
Now let’s target our unordered list and give it some left margin that will be a fixed value using pixels. The list items will then be given square bullet points instead of the default circles. This is personal preference, so you may want to leave it as the default. The last thing we’re doing is applying a line height of 140 per cent to each list item.
001 section .info ul {
002 margin-left: 20px;
003 }
004 section .info li {
005 list-style: square;
006 line-height: 140%;
007 }
Learn more button
The ‘Learn more’ button will be placed at the very bottom of our product information and we will make sure that it has some breathing space by giving it a little margin and padding. The button will be blue with white text and we will also give it a nice transition into a lighter blue for when users hover over it.
001 section .info .moreBtn {
002 display: block;
003 margin-top: .4em;
004 padding: .4em;
005 background: #006699;
006 text-align: center;
007 font-size: 1.1em;
008 color: white;
009 text-decoration: none;
010 text-transform: uppercase;
011 transition: 0.3s background-color;
012 }
013 section .info .moreBtn:hover {
014 background: #0672a8;
015 }
nth-child selectors
In this step, we will use ‘:nth-child()’ selector to select the first ‘.info’ of every two and the second ‘.info’ of every two. The first ‘.info’ can remain where it is, but the second should be moved to the left by adding a negative value of -100 per cent, which will make it appear in the same position as the first.
001 article:nth-child(2n+1) .info {
002 left: 0;
003 }
004 article:nth-child(2n+2) .info {
005 left: -100%;
006 }
Reveal the info
In this step, we’re going to add in a rule that will allow us to reveal the product’s information. Firstly we will set its height to ‘auto’ so it will change from ‘0’ to whatever value is required to contain all of its content. The font size will also go from ‘0’ to 100 per cent and then we’ll set the opacity to ‘1’ to reveal our content. Finally we give it some animation by using ‘transition’.
001 section article:target .info {
002 height: auto;
003 font-size: 100%;
004 opacity: 1;
005 transition: .4s .4s opacity;
006 }
Image identifier
To make it obvious which product image the user is looking at, we can add a nice subtle drop shadow to the bottom of our image. So, when we click on that image, using the ‘target’ pseudo-selector (as we did in the previous step) we can make sure the drop shadow is added to that clicked image. Let’s polish it off by adding some animation to the shadow.
001 section article:target img {
002 box-shadow: 0 8px 3px -4px
rgba(0,0,0,.5);
003 transform: scale(1.1);
004 transition: .5s;
005 }
Info elements
Now because there are three products per row, the ‘.info’ elements need adjusting again so they always start on the screen’s far left. Here we’ve moved the second of three products 100 per cent to the left and the third 200 per cent to the left. It’s important to use percentages here for our page to be responsive.
001 section article:nth-child(3n+1) .info {
002 left: 0;
003 }
004 section article:nth-child(3n+2) .info {
005 left: -100%;
006 }
007 section article:nth-child(3n+3) .info {
008 left: -200%;
009
Finish the more button
We have already added some styles to the ‘Learn more’ button in an earlier step, but let’s add some more to help with how we position it and to resize it. To achieve this we will give it a display value of ‘inline-block’ and float it left. We’re going to clear the float and then specify its width as ‘auto’. Lastly we will use margin-top to give us some space.
001 section article .moreBtn {
002 display: inline-block;
003 float: left;
004 clear: both;
005 width: auto;
006 margin-top: 2em 0 0 0;
007 }
008
Position the content
One of the last steps to complete is positioning our product content properly using the ‘float’ and ‘width’ properties. As we have mentioned before, we want this to be responsive, so we will need to use percentages here. The description will be 50 per cent of the width of the article element and the unordered list will be 30 per cent. This will give us lots of white space.
001 section article .description {
002 float: left;
003 width: 50%;
004 }
005 section article ul {
006 float: right;
007 width: 30%;
008 }
Media queries
To make our project fully responsive, we need to add some media queries with a minimum width of 400px. When the browser window reaches a minimum width of 400px, each product will then be made 30 per cent wide and the product information will be made 280 per cent wide. This will also cause the grid to become a row of three instead of two.
001 @media only screen and (min-width: 400px) {
002 section article {
003 width: 33%;
004 }
005 section article .info {
006 width: 280%;
007 }
008 }
009
Final thoughts
Now we can resize our page and be happy that our page renders well in different-sized browser windows. As you can see, using CSS3 for things like image grids can be very easy to achieve and also very effective. As a web designer, you have to ask yourself whether or not you really need to use jQuery all the time for animated elements. This tutorial has aimed to show you otherwise – so have fun creating yours!