1. Code
  2. CSS3

Creating a Sense of 3D With the Perspective Property of CSS3

Final product image
What You'll Be Creating

In this tutorial, we will create an interactive element with the CSS3 perspective property in order to give a sense of three dimensions. This tutorial will also teach you how to use jQuery with mouse events in order to obtain element positions in JavaScript and how to manipulate the CSS properties.

The HTML Structure for the Perspective Property

We need a parent-child relation for the perspective property to work properly. Let's first create the HTML structure and then continue with the CSS styling.

Here we are wrapping two card elements into a div with the id of cardsWrapper. Also, this cardsWrapper is wrapped into another div in order to be able to manipulate its position within the viewport easily.

Each element with the class of card has an image element, which embraces the screen and text elements. The structure is a bit vague for the time being, but I will explain the use of each element in the related upcoming sections.

Let's use the following CSS styling in order to position our elements.

Using the Perspective Property

The perspective property is something that you have to set in your parent div which contains the divs that you want to transform with the sense of perspective. Imagine the parent div is your world, and it has a certain perspective value that you are experiencing.

Let's add the perspective property to our parent div, which is card. We are selecting the card element as the parent, not cardsWrapper, since we want to have an individual perspective effect on each card element.

Tweak the CSS of the card as follows.

Now try to add a transform property to the image element to see the effect of the perspective.

Since image is the direct child of card, it is affected by the perspective. However, if you try to add a transform property to any child of the image, this would not work.

In order for these children to be transformed relative to their parent, which is the image element in this example, you should use transform-style: preserve-3d on the parent element.

Now we have a sufficient background in the perspective property and are ready to continue with styling the other elements.

Don't forget to remove the transform: rotateX(30deg) from your image element.

Styling the Cards

We have an image element, and on top of it we have an element called screen, and then the text. Since we are using perspective here, you can think of each of these elements as individual layers.

Now we will add a background-image to our image div and then style the screen and text elements.

Let's use the following CSS styling to add a background-image to each single card object.

Now we will style the screen element.

Since we want the screen element to be exactly the same size as its parent image element, we use 100% width and height values and a grey black background-color with an alpha channel.

The import part is transform: translateZ(30px) scale(0.940).

So here we just translate the screen element on the Z-axis by 20px. This makes it hover over the image element. Since it is towards us, it will be larger in size, due to the rules of perspective. Therefore, we scale it down to match the size with the parent element. If you use different translation values, the scale value would vary. Likewise, defining different height and width sizes for the parent element would result in a requirement of a different scaling value.

In order to understand what's happening here, just rotate your image element around the X and Y axes by adding the following line into your CSS rule:

transform: rotateX(30deg) rotateY(30deg)

Now the last part for this section is styling the text element, which is quite trivial.

We are basically using the same transform settings for the text element in order to have it on the same level as the screen element. The rest of the CSS is just simple styling. You can tweak it the way you like.

This is the final result with manual rotation to see the effect.

Before proceeding further, delete the rotation rules from your CSS, since we will control the rotation automatically in accordance with the cursor position.

Now we will write some jQuery code in order to make those cards interactive.

Let's get to it!

Adding Interaction With jQuery

Let's start with the base jQuery code.

We will be writing everything inside this function. This will allow jQuery to wait until the DOM is ready.

Since we are interested in interacting with our card element, we need to select it.

The next step is registering the cursor position on the card element. In order to do so, we will use the built-in mousemove event.

Now we need to track the cursor position. It's a bit tricky to get the correct values.

Here, e.clientX and e.clientY return the cursor position inside the viewport. However, since each card object is positioned relative to the viewport, we need to compensate for this by extracting the left and top offset values.

The last and the most important thing to consider is compensation for window scrolling. So, since your cursor position is registered relative to your viewport but the offset values are fixed, when you scroll, your object gets closer to the top or left of the viewport depending on the direction in which you scrolled. 

As a result, our relative distance to the top or left of the viewport would be smaller. However, since the offset values are fixed, we need to compensate for this, and this is done by the $(window).scrollLeft() and $(window).scrollTop(). So, by adding those values to the respective variables, we just compensate for the amount we scrolled. As a result, when you hover over any of your card elements, your X position would range from 0 to the width of the card, which is defined as 300px. Likewise, the Y position would range from 0 to the height of the card, which is 175px.

The next step is mapping the cursor position to a new range, which will be the amount of rotation we want to apply in units of degree, so that when your cursor stands in the middle of the card element, it would just look flat, but when you move to the left/right or top/bottom, you would get a rotation effect as if the card is following the cursor.

Here is a quick illustration for the result of the mapping function.

Mapping function

In this function, the in_min and in_max parameters are the minimum and maximum values of the input value respectively, which correspond to the width and height of the card element. out_min and out_max are the minimum and maximum values that the input will be mapped.

Let's use this map function with our X and Y cursor positions.

Now our mapped values are rX and rY.

The next step is setting a CSS rule for the image element by using the mapped values as rotation values.

Here we selected the children of the card element which are named image, and then set the CSS rule to rotate this element around the X and Y axes by rX and rY degrees respectively.

You will realise that the card elements follow the cursor in their respective perspectives. However, when the cursor is off the card elements, they retain their orientations. Moreover, they react to the presence of the cursor over the card element abruptly. So we also need to handle those cases when the mouse enters and leaves the card element.

In order to handle these problems, we need to use the mouseenter and mouseleave events.

When the mouse enters the region of the card element, we add a transition CSS rule to the image element. This will enable a smooth transition for the "gaze" of the image element.

Likewise, we need to handle the mouseleave event.

Here, I also add another transition CSS rule with a different timing, which makes a smoother transition to the initial position when the mouse leaves the card element. 

I also add the transform CSS rule in order to reset the rotations of the card element.

So our final jQuery code looks like this:

Here is the final result. I also used a different sans-serif font on the text element to make it look better.


Throughout this tutorial, we learned how to use the perspective property and the required HTML structure to make it work properly. Moreover, we covered how to register the mouse cursor position when hovered over a specific HTML element.

On top of that, we used the mousemovemouseenter, and mouseleave events to introduce interactivity by adding CSS rules to HTML elements with jQuery.

I hope you enjoyed this tutorial and learned some useful methods.

Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.