This is a particular design trick that never fails to catch people’s eye! I don’t know the exact history of who-thought-of-what first and all that, but I know I have seen a number of implementations of it over the years. I figured I’d round a few of them up here.
Noel Delagado
See the Pen Direction-aware 3D hover effect (Concept) by Noel Delgado (@noeldelgado) on CodePen.
The detection here is done by tracking the mouse position on mouseover
and mouseout
and calculating which side was crossed. It’s a small amount of clever JavaScript, the meat of which is figuring out that direction:
var getDirection = function (ev, obj) {
var w = obj.offsetWidth,
h = obj.offsetHeight,
x = (ev.pageX - obj.offsetLeft - (w / 2) * (w > h ? (h / w) : 1)),
y = (ev.pageY - obj.offsetTop - (h / 2) * (h > w ? (w / h) : 1)),
d = Math.round( Math.atan2(y, x) / 1.57079633 + 5 ) % 4;
return d;
};
Then class names are applied depending on that direction to trigger the directional CSS animations.
Fabrice Weinberg
See the Pen Direction aware hover pure CSS by Fabrice Weinberg (@FWeinb) on CodePen.
Fabrice uses just pure CSS here. They don’t detect the outgoing direction, but they do detect the incoming direction by way of four hidden hoverable boxes, each rotated to cover a triangle. Like this:
Codrops
In an article by Mary Lou on Codrops from 2012, Direction-Aware Hover Effect with CSS3 and jQuery, the detection is also done in JavaScript. Here’s that part of the plugin:
_getDir: function (coordinates) {
// the width and height of the current div
var w = this.$el.width(),
h = this.$el.height(),
// calculate the x and y to get an angle to the center of the div from that x and y.
// gets the x value relative to the center of the DIV and "normalize" it
x = (coordinates.x - this.$el.offset().left - (w / 2)) * (w > h ? (h / w) : 1),
y = (coordinates.y - this.$el.offset().top - (h / 2)) * (h > w ? (w / h) : 1),
// the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);
// first calculate the angle of the point,
// add 180 deg to get rid of the negative values
// divide by 90 to get the quadrant
// add 3 and do a modulo by 4 to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/
direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;
return direction;
},
It’s technically CSS doing the animation though, as inline styles are applied as needed to the elements.
John Stewart
See the Pen Direction Aware Hover Goodness by John Stewart (@johnstew) on CodePen.
John leaned on Greensock to do all the detection and animation work here. Like all the examples, it has its own homegrown geometric math to calculate the direction in which the elements were hovered.
// Detect Closest Edge
function closestEdge(x,y,w,h) {
var topEdgeDist = distMetric(x,y,w/2,0);
var bottomEdgeDist = distMetric(x,y,w/2,h);
var leftEdgeDist = distMetric(x,y,0,h/2);
var rightEdgeDist = distMetric(x,y,w,h/2);
var min = Math.min(topEdgeDist,bottomEdgeDist,leftEdgeDist,rightEdgeDist);
switch (min) {
case leftEdgeDist:
return "left";
case rightEdgeDist:
return "right";
case topEdgeDist:
return "top";
case bottomEdgeDist:
return "bottom";
}
}
// Distance Formula
function distMetric(x,y,x2,y2) {
var xDiff = x - x2;
var yDiff = y - y2;
return (xDiff * xDiff) + (yDiff * yDiff);
}
Gabrielle Wee
See the Pen CSS-Only Direction-Aware Cube Links by Gabrielle Wee ✨ (@gabriellewee) on CodePen.
Gabrielle gets it done entirely in CSS by positioning four hoverable child elements which trigger the animation on a sibling element (the cube) depending on which one was hovered. There is some tricky stuff here involving clip-path
and transforms that I admit I don’t fully understand. The hoverable areas don’t appear to be triangular like you might expect, but rectangles covering half the area. It seems like they would overlap ineffectively, but they don’t seem to. I think it might be that they hang off the edges slightly giving a hover area that allows each edge full edge coverage.
Elmer Balbin
See the Pen Direction Aware Tiles using clip-path Pure CSS by Elmer Balbin (@elmzarnsi) on CodePen.
Elmer is also using clip-path here, but the four hoverable elements are clipped into triangles. You can see how each of them has a point at 50% 50%, the center of the square, and has two other corner points.
clip-path: polygon(0 0, 100% 0, 50% 50%)
clip-path: polygon(100% 0, 100% 100%, 50% 50%);
clip-path: polygon(0 100%, 50% 50%, 100% 100%);
clip-path: polygon(0 0, 50% 50%, 0 100%);
Nigel O Toole
Raw JavaScript powers Nigel’s demo here, which is all modernized to work with npm and modules and all that. It’s familiar calculations though:
const _getDirection = function (e, item) {
// Width and height of current item
let w = item.offsetWidth;
let h = item.offsetHeight;
let position = _getPosition(item);
// Calculate the x/y value of the pointer entering/exiting, relative to the center of the item.
let x = (e.pageX - position.x - (w / 2) * (w > h ? (h / w) : 1));
let y = (e.pageY - position.y - (h / 2) * (h > w ? (w / h) : 1));
// Calculate the angle the pointer entered/exited and convert to clockwise format (top/right/bottom/left = 0/1/2/3). See https://stackoverflow.com/a/3647634 for a full explanation.
let d = Math.round(Math.atan2(y, x) / 1.57079633 + 5) % 4;
// console.table([x, y, w, h, e.pageX, e.pageY, item.offsetLeft, item.offsetTop, position.x, position.y]);
return d;
};
The JavaScript ultimately applies classes, which are animated in CSS based on some fancy Sass-generated animations.
Giana
A CSS-only take that handles the outgoing direction nicely!
See the Pen CSS-only directionally aware hover by Giana (@giana) on CodePen.
Seen any others out there? Ever used this on something you’ve built?
Love the CSS Only version. Super Ingenious.
I did a css only version in 2013 which is similar to the first example above but animates the same message rather than 4 different messages.
It could do with a lot of tidying up now that I look at it again :)
It’s a pity only one of them is useably accessible for non-mouse / trackpad users: Nigel O Toole’s, which handles keyboard navigation quite well. Gabrielle Wee’s gives visual feedback via keyboard, but the multiple links underlying each element mean mashing Tab repeatedly to move past each one.
The rest range from “Why u mad? We left you the default fuzzy blue outline” to “LOL we even took that away! Keybords4Loozers Hover4Lyf!” deliberate breaking of default browser behaviour.
I love this stuff, and think it’s beautiful and clever, but please, if you’re going to actively make the internet unuseable for a good percentage of us, please stop.
Hi Anonymous Berlinerin,
I very much like your answer. Earlier I regularly visited galleries like this to find a bunch of interesting solutions to pick from. But for quite a long time I stopped implementing low quality solutions. And bad usability or no accessibility is just low quality. Testing takes a lot of time. I think already it is not worth it anymore. To find an accessible solution it needs so much testing, that it is less work to do it myself right from the beginning.
So I appreciate, that you did the testing and thanks to Paul O`Brien for showing his own CSS-only solution with keyboard support! Nigel and Paul added nice works to this set of ideas. Thank you!
About accessibility: it’s nice to see, that I am not the only one. All non-accessible examples are nice inspirations, of how it could look like. Quick and dirty is okay for prototypes. The code itself I consider being just a draft – in the best case. Anyway it’s not worthless. It can be used as a starting point for my own work or a “DON’T do this”-example for teaching. ;-)
It is just a pity, that accessibility still does not seem to be part of the quality assurance processes of most websites. One could think, that every developer should have heard about it and why it’s important. What does this say about developers, that don’t care?
No nice words in my mind for this kind of behaviour. I hope CSS Tricks will introduce a lable or something in future posts to highlight usable solutions.
I would really appreciate this and galleries like this would become much mor interesting again!
Thanks for this article, it’s not only gives us some interesting info but a lot of inspiration.
Here is my humble example of this (CSS only solution)
https://codepen.io/Konrud/embed/XZMPyg?height=700
Thanks Chris for including my plugin on this list, I have visited this website for years so its great to have my work featured. Also thanks to Anonymous Berlinerin as I always try to make my work accessible and glad this was recognised. I have just updated the plugin for better mobile support and a new animation so please check it out. https://nigelotoole.github.io/direction-reveal/