Create your portfolio gallery using html5 canvas – tutorial

19/02/12

In this tutorial we will build a photo gallery and enhance it with html5 canvas and css3 transitions. See the demo and try the hover effect. The grayscale “copies” of the images are created with canvas and we use pure css3 for the smooth changes.

Photo gallery with html5 canvas

Download the source files

Portfolio gallery with canvas
.zip 0.25MB

Step 1 : Html markup

Let’s start with a simple markup, each portfolio entry being an element of an unordered list.

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>Gallery :: Tutorial by PeHaa </title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
	<div id="wrap">
		<h1>Gallery</h1>
		<ul id="gallery">
			<li><a href=""><img src="images/flo1.jpg"><div>Spring flowers 1</div></a></li>
			<li><a href=""><img src="images/lights2.jpg"><div>City lights 1</div></a></li>
			<li><a href=""><img src="images/flo3.jpg"><div>Spring flowers 2</div></a></li>
			<li><a href=""><img src="images/lights1.jpg"><div>City lights 2</div></a></li>
			<li><a href=""><img src="images/flo2.jpg"><div>Spring flowers 3</div></a></li>
			<li><a href=""><img src="images/lights3.jpg"><div>City lights 3</div></a></li>
		</ul>
		<p>Photos by <a href="http://pinkonhead.com">Pinkonhead</a></p>
	</div>
</body>
</html>


Step 2: Basic styles

We start our stylesheet with a basic reset.

html, body, div, span, h1, h2,  p, a,  ul, li, img
{margin: 0; padding: 0;
border: 0; outline: 0;
font-size: 100%;background: transparent;}
ul {list-style: none;}
:focus {outline: 0;}
a {text-decoration:none;}

We will use 300px x 300px images. The main containing element #wrap is centered up (margin: 0 auto) and given the width of 1020px (=340 x 3).
The list items are given float : left and are positioned relatively. The image title is wrapped in a div element that slides up on hover. To achieve a smooth effect we apply a css3 transition.
(Note that for the simplicity of this tutorial I don’t use any vendor prefixes. Therefore, you’ll find them in the source file to download).

#wrap {
  width: 1020px; 
  margin: 0 auto;
} 
li {
  float:left; 
  position:relative; 
  display:inline-block; 
  width:300px; 
  height:300px;
  margin:10px; 
  padding:10px; 
  background:#fff; 
  box-shadow:0 0 5px rgba(0,0,0,.35);
}
li div {
  position:absolute;
  height:0; 
  width:280px;
  background:rgba(0,0,0,.45); 
  overflow:hidden;
  bottom:10px; 
  left:10px;
  padding: 0 10px;
  line-height:50px;
  color:#fff;
  transition:height 1s;
}
li:hover div {
  height:50px;
}

Click on the image to below to see the result at the current stage.

Photo gallery with canvas

Step 3: Canvas

Now, we will make use of the html5 canvas element to draw the grayscale versions of our images. Below you’ll find a createCanvas custom function that creates a canvas element, takes a copy of an image, performs the conversion and draws it to the canvas and finally inserts the canvas to the DOM where desired. With .each() method the createCanvas function is iterated across all images within the #gallery list.

$(window).load(function() {

	  $('#gallery img').each(function() {

	    createCanvas(this);
	  });

	  function createCanvas(image) {

	    var canvas = document.createElement('canvas');
	    if (canvas.getContext) {
	      var ctx = canvas.getContext("2d");

// specify canvas size
	      canvas.width = image.width;
	      canvas.height = image.height;

// Once we have a reference to the source image object we can use 
// the drawImage(reference, x, y) method to render it to the canvas. 
//x, y are the coordinates on the target canvas where the image should be placed.
	      ctx.drawImage(image, 0, 0);

// Taking the image data and storing it in the imageData array. 
//You can read the pixel data on a canvas using the getImageData() method. 
// Image data includes the colour of the pixel (decimal, rgb values) and alpha value. 
// Each color component is represented by an integer between 0 and 255. 
//imageData.data contains height x width x 4 bytes of data, with index values ranging from 0 to (height x width x 4)-1.
	      var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height),
	          pixelData = imageData.data;

// Loop through all the pixels in the imageData array, and modify
// the red, green, and blue color values.
	      for (var y = 0; y < canvas.height; y++) {
	        for (var x = 0; x < canvas.width; x++) {

// You can access the color values of the (x,y) pixel as follows :
	          var i = (y * 4 * canvas.width) + (x * 4);

// Get the RGB values.
	          var red = pixelData[i];
	          var green = pixelData[i + 1];
	          var blue = pixelData[i + 2];

// Convert to grayscale. One of the formulas of conversion (e.g. you could try a simple average (red+green+blue)/3)   
	          var grayScale = (red * 0.3) + (green * 0.59) + (blue * .11);

	          pixelData[i] = grayScale;
	          pixelData[i + 1] = grayScale;
	          pixelData[i + 2] = grayScale;
	        }
	      }

// Putting the modified imageData back on the canvas.
	      ctx.putImageData(imageData, 0, 0, 0, 0, imageData.width, imageData.height);

// Inserting the canvas in the DOM, before the image:
	      image.parentNode.insertBefore(canvas, image);
	    }
	  }
	});


Step 4: Styling the canvas

If you look into the generated code source you’ll find

<ul id="gallery">
	<li><a href=""><canvas width="300" height="300"></canvas><img src="images/flo1.jpg"><div>Spring flowers 1</div></a></li>
	<li><a href=""><canvas width="300" height="300"></canvas><img src="images/lights2.jpg"><div>City lights 1</div></a></li>
	<li>...</li>
	...
</ul>

Let’s add some styling to define the canvas behavior in normal and hover state:

canvas {
  opacity:1; 
  position:absolute; 
  top:10px;
  left:10px;
  transition:opacity 1s .2s;
}
li:hover canvas {
  opacity:0;
}

And that’s it ! This example will not work in Internet Explorer versions below 9. You could provide an alternative solution using grayscale filter and adding some jQuery to recreate the transition effect on hover – but this part is not covered in this tutorial.

The beautiful photos featured here were taken by Pinkonhead, and are shared as freebies on her blog. Enjoy.

13 Responses to “Create your portfolio gallery using html5 canvas – tutorial”

  1. Pinkonhead

    Feb 20th, 2012

    Great tutorial !! Thanks for using my photos :)

  2. farook

    Feb 27th, 2012

    I am exicited about HTML5 but Flash can do all these things html5 can do in a better way.Creating slideshow in HTML5! wow! what, flash did that 10 years ago! It is very easy to create a flash animation, for example a ball bouncing in flash professional in less than am minute. Javascript is a mess when compared to AS3.

    • Brecht

      Nov 16th, 2012

      Well … why creating this in html5 ?

      Because, more and more people are browsing the internet on their smartphones, tablets…

      so gues what? they can’t deal with flash. And yes, flash did this a long time ago, but ask a lot of webdevelopers… if they can do things without flash, they will.

    • Meaghan

      Mar 18th, 2013

      Flash is out. HTML5 is in! Gotta move with the times!

  3. Thank you for very useful effect!

  4. modraideja

    Apr 5th, 2012

    Wow, beautiful gallery, tnx for the tutorial :)

  5. image masking

    Apr 27th, 2012

    Thanks for nice tutorial :D

  6. […] 24. Create Your Portfolio Gallery Using HTML5 Canvas […]

  7. Petter

    Jan 10th, 2013

    Hallo i wonder if i could extrude the .js to separate filé and the link it ?

  8. Andrea Baccolini

    Jul 8th, 2013

    Hi, how can I do so that the canvas replaces the images? Thanks

  9. Vusi

    Apr 11th, 2014

    Thanks lot, helped, was able to implement other creative executions, but still following your tutorial. Thanks once again.

  10. R P

    Jun 5th, 2014

    Question / Suggestion : why didn’t you choose figcaption instead of div?

  11. Nav

    Aug 7th, 2014

    Uncaught SecurityError: Failed to execute ‘getImageData’ on ‘CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.

    How did you get around this?

    Thanks

Leave a Reply