Notice: Undefined index: order_next_posts in /nas/content/live/gadgetmag/wp-content/plugins/smart-scroll-posts/smart-scroll-posts.php on line 194

Notice: Undefined index: post_link_target in /nas/content/live/gadgetmag/wp-content/plugins/smart-scroll-posts/smart-scroll-posts.php on line 195

Notice: Undefined index: posts_featured_size in /nas/content/live/gadgetmag/wp-content/plugins/smart-scroll-posts/smart-scroll-posts.php on line 196

Create an animated header with CSS and JS

Discover the techniques, tools and technologies needed to recreate the animated header found on the 1MD site


The HTML Header

Our 1MD header element begins with thinking of a divided composition. A composite image is divided into transparent PNG layers and animated one by one. The header HTML then takes these different images stacked within the #layers <div> container, followed by a canvas element. The amount of layers depends on the complexity of your composition, but be sure to give all your layers a common CSS class name and each one a unique id name.

001 <header id=”header”>
002 <div id=”layers”>
003 <img id=”layer1” class=”layer” 
004 <img id=”layer2” class=”layer” 
005 <img id=”layer3” class=”layer” 
006 <img id=”layer4” class=”layer” 
007 <img id=”layer5” class=”layer” 
008 <img id=”layer6” class=”layer” 
009 </div>
010 <canvas id=”canvas” width=”1200” 
011 </header>

CSS Animations

In the CSS we set an absolute position to all our layers in order to animate them with more ease. You’ll notice we set an animation called “animation1” which transforms the first layer’s position from (0,0) to (10px, -10px) and then to (-10px, 10px) and so on. We then attach this animation to our first layer (#layer1), although the principle stays the same for all other layers. Lastly we set the position attribute of the canvas to absolute.

001 layer {
002 position:absolute;
003 }
004 #header #layer1 {
animation:animation1 35s ease-in-out 
005 }
006 @keyframes animation1 {
007 0% {
008 transform:translate(0px, 0px);
009 }
010 20% {
011 transform:translate(10px, -10px);
012 }
013 40% {
014 transform:translate(-10px, 10px);
015 }
016 60% {
017 transform:translate(-10px, 10px);
018 }
019 80% {
020 transform:translate(10px, -10px);
021 }
022 100% {
023 transform:translate(0px, 0px);
024 }
025 }
026 #canvas {
027 position:absolute;
028 }

Animating the canvas

To add a cool finishing touch to our header we added some animated dots behind all the layers. This is our 1200 x 900 <canvas> element with a series of important JavaScript functions starting with “requestAnimationFrame” which essentially allows us to update the animation with a frame rate of 60fps, before listening to the “resize” event of the window in order to adapt the size of the canvas to the screen size:

001 canvas.width = $(window).width();
002 canvas.height = Math.min(canvas.
width / ratio, 900);
003 $(window).resize(function() {
004 canvas.width = $(window).width();
005 canvas.height = Math.min(canvas.
width / ratio, 900);
006 stage = {
007 centerX: canvas.width / 2,
008 centerY: canvas.height / 2
009 }
010 build();
011 }

Create the dots and lines

Next if you inspect the “randomRage” function, you’ll see that it simply generates some random numbers we use to set the dots’ position. To draw the dots and the lines, we use the “drawCircle” and the “drawLine” functions. By calling the “build” function, we create the first image on the canvas and all the assets we will update next. And finally each call of the “update” function performs “updateCoords”, “drawDots”, “checkProximity” and “drawLine” – each fairly self-explanatory:

001 function randomRage(min, max) {
002 return Math.random() * (max - min) 
+ min
002 }
003 function drawCircle(dot) {
004 ctx.beginPath();
005 ctx.arc(dot.x, dot.y, circleRadius, 
0, PI2, false);
006 ctx.fillStyle = styleColor;
007 ctx.lineWidth = .5;
008 ctx.fill();
009 ctx.closePath();
010 }
011 function drawLine(startX, startY, 
endX, endY) {
012 ctx.beginPath();
013 ctx.moveTo(startX, startY);
014 ctx.lineTo(endX, endY);
015 ctx.strokeStyle = lineColor;
016 ctx.stroke();
017 ctx.closePath();
018 }

Preview and customise

The full code is pretty lengthy and complex, so you can find the full listing on the disc but also via CodePen at By all means test it out and change the variable values such as ‘dotsCount’ and ‘maxSpeed’ to alter how it performs. You can also simply drop the JavaScript code into the head or footer of your page to create the dots map wherever your <canvas> element is located – that’s it!