Building the eye in CSS3

Have you ever seen something that you just had to have? It may not be useful but YOU JUST WANT IT. Last week I came across something like that.

A great example of taking CSS3 skills to a extreme level. Building a eye ball. You can follow the tutorial here

Then i started thinking like its awesome and all, but how cool would it be if the eye moves according to user mouse movements.
So here I will show you how to extend the eye to track user movements on the page.

Getting Started

First follow the tutorial above or download the sample project from github
Open the project in your favourite text editor and browser. For this project, I strongly recommend using Google Chrome to test the eye.

It’s all about scripting

Create a file “mouse.js” in script directory. Open “index.html” and add a link to the js file in head tag.

	<script type="text/javascript" src='script/mouse.js'></script>

setting vars

Now open “mouse.js”. It’s always a good practice to set your variables at the top of the document. These variables will be used to track the position of the iris and mouse.

var mousePos,
    	eye_pos_x = 560,
    	eye_pos_y = 260,
    	eye_width = 100,
    	eye_height = 100,
    	iris_width = 30,
    	iris_height = 30,
    	skew_max_x = 15,
    	skew_max_y = 2,
    	skew_min_x = 5,
    	skew_min_y = -10,
    	eye, iris, css_rule;

Getting Mouse position

The position of an object on window is measured from the left top corner of the screen. So the Top-Left corner is considered as (0, 0).

function handleMouseMove(event) {
        var dot, eventDoc, doc, body, pageX, pageY;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = ( && || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );

        mousePos = {
            x: event.pageX,
            y: event.pageY

This method is called with an event object and has been tweaked to support old IE versions. It updates the value of mousePos variable each time it is called.

We will use the updated version of the mousePos object to rotate the iris around the eye.

    function moveEye(x, y) {
    	var x_pos = x - eye_pos_x - eye_width,
    		y_pos = y - eye_pos_y - eye_height,
    		x_skew, y_skew, scale = 0.98;

The method moveEye() takes two params namely x and y coordinates of the mouse. Now to limit position of iris within the eye, we will move the coordinate system to the center of the eye. Now (0, 0) represents the center of the eye.

	if(x_pos > eye_width) x_pos = eye_width - (iris_width);
    	if(y_pos > eye_height) y_pos = eye_height - (iris_height);
    	if(x_pos < -eye_width) x_pos = -eye_width + (iris_width);
    	if(y_pos < -eye_height) y_pos = -eye_height + (iris_height);

To limit the iris within the eye, we take care of the boundary conditions.

 x_skew = Math.abs(x_pos / eye_width) * (skew_max_x - skew_min_x);
    	y_skew = Math.abs(y_pos / eye_height) * (skew_max_y - skew_min_y) ;

Now as the eye moves towards the boundary of the eye, it bends to give the illution of an 3d object. The skew value of css transform property comes in handy. The amount of skew is calculated by the relative distance between the mouse and the boundary.

 	if((x_pos < 0 && y_pos < 0) || (x_pos > 0 && y_pos > 0)) {
    		y_skew = -y_skew;
    		scale = 0.9;

The iris at position (-x, -y) and (x, y) is skewed in wrong direction. To handle these special cases, we add another condition and reverse the y skew of the iris.

Finally to add all the properties to the iris element, we will use style property.

 	...'transform', 'translateX(' + x_pos + 'px) translateY(' + y_pos + 'px) skewX(' + x_skew + 'deg) skewY(' + y_skew +'deg) scale(' + scale + ')');


Finally we reach the heart of javascript – onload method.

 window.onload = function() {
    	iris = document.getElementsByClassName("iris")[0];
    	eye = document.getElementsByClassName("stage")[0];


Initializing the DOM elements vars. Now there is an anomaly, When the document is first loaded, the value of mousePos variable will be null. So we need to give it a good place to start. Let’s say at the center of the eye.

 	mousePos = {
            x: eye_pos_x + eye_width,
            y: eye_pos_y + eye_height

Now we add a listener that would register the javascript mousemove event and call handleMouseEvent method.

    	document.addEventListener('mousemove', handleMouseMove);

Finally we will call the moveEye method after a specified time to make use of css transition property.

	setInterval(function() {
		moveEye(mousePos.x, mousePos.y);
	}, 100); // setInterval repeats every X ms


That’s it. Now it’s ready to be added to your website.
Check out the source code at github and live demo here.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s