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

Build floating card elements with HTML & CSS

Dogstudio’s lead front-end developer Fabrice Lejeune offers a guide to creating the visually effective rollovers found throughout the KIKK site


Structure the main elements

First of all, you need to set up your stage. The structure of our floating card is quite simply composed of an image, a title and a caption, wrapped in a number of <div> and <span> containers and styled with CSS to add the various decorations. Within this, the card has an SVG border that gives us the ability to animate its dasharray and dashoffset stroke properties on hover. View the full CSS/SCSS and step code listings within the accompanying project files on FileSilo.

001 HTML:    
002 <article class="fc" id="fc">
003 <div class="fc__wrapper">    
004 <img src="    wd242/dog.jpg" class="fc__thumb">    005 <div class="fc__content">    
006 <h1>Floating Card</h1>    
007 <span class="caption">by     Dogstudio</span>    
008 </div>    
009 <span class="fc__light"></span>
010 <svg class="fc__border" xmlns="">
011 <rect height="100%" width="100%" />
012 </svg>    
013 </div>    
014 </article>    
015 CSS:    
016 //Border classes with stroke     animations    
017 .fc__border rect {    
018 fill: transparent;    
019 stroke: #777777;    
020 stroke-width: 2px;    
021 stroke-dasharray: 0 1232px;    
022 stroke-dashoffset: -616px;    
023 transition: stroke-dasharray 0.25s     ease-out, stroke-dashoffset 0.25s ease-out;    
024 }    
025 .fc:hover .fc__border rect {
026 stroke-dasharray: 1232px;    
027 stroke-dashoffset: 0;    
028 }

Move with the mouse

To move the card dynamically with JavaScript we handle the event mousemove on the main <div> wrapper. From here we calculate the current mouse position on the card with point 0,0 in the top left Next, calculate what angle or degree of movement this should give us on the x axis and z axis and apply it using the CSS transform property:

001 var fc = document.getElementById("fc");    
002 var wrapper = fc.getElementsByClassName("fc__wrapper")[0];    
003 var fcHalfWidth = 135;
004 var fcHalfHeight = 205;    
005 var maxRotateX = 6;    
006 var maxRotateY = 6;    
007 wrapper.addEventListener("mousemove", function(event) {    
008 // Get mouse position in the card
009 var fcRect = fc.getBoundingClientRect();    
010 var fcOffset = {    
011 top: + document.body.    scrollTop,    
012 left: fcRect.left + document.body.    scrollLeft    
013 };    
014 var mouseX = (event.pageX – fcOffset.left);    
015 var mouseY = (event.pageY –;    
016 // Move the floating card    
017 var diffX = -1 * (fcHalfWidth - mouseX);    
018 var diffY = fcHalfHeight – mouseY;
019 var rotateX = diffY / fcHalfHeight     * maxRotateX;    
020 var rotateY = diffX / fcHalfWidth * maxRotateY;    
021 =     "rotateX(" + rotateX + "deg) rotateY("     + rotateY + "deg)";    
022 });    

Add some depth

We now have something moving nicely but it’s still rather flat. To add some depth, we just use a CSS transform to translate on the z axis of the title <div> and the border layer from 100px. To keep the initial size of these two layers visual, we have to change the scale. As we defined a perspective of 1000px, for a translation of 100px you have to downscale layers by ten per cent.

Physics-based movement

When the mouse leaves the floating card, a more natural physics-based movement is applied when returning it back to its initial position. This is achieved by using the JavaScript library dynamic.js by Michael Villar (, which can be linked to your page via CDN as shown. What this allows us to do is add a ‘spring’ easing more conveniently, however the animation on the wrapper must be stopped when the mouse re-enters on it:

001 HTML:    
002 <script src=""></script>    
004 wrapper.addEventListener("mousemove", function(event) {    
005 ...    
006 dynamics.stop(wrapper);    
007 = "rotateX(" + rotateX + "deg) rotateY("     + rotateY + "deg)";    
008 });    
009 wrapper.addEventListener("mouseleave", function() {    
010 // Move the floating card to its     initial position    
011 dynamics.animate(wrapper, {
012 rotateX: 0,    
013 rotateY: 0    
014 }, {    
015 type: dynamics.spring,    
016 duration: 1500    
017 });    
018 });    

Add lighting effects

As we move our card in a 3D environment, playing with the light will add a more realistic effect. On the mouse move we change the angle and the width of the linear-gradient used as shadow on the image. It’s a little tricky but it does add another dimension to the effect during the movement. Preview the result via CodePen at