3D Tilt Effect on Hover Using Vanilla JS

3D Tilt Effect on Hover Using Vanilla JS
Code Snippet:tilt - vanilla js
Author: Marc Müller
Published: January 10, 2024
Last Updated: January 22, 2024
Downloads: 414
License: MIT
Edit Code online: View on CodePen
Read More

This Vanilla JS code snippet helps you to create 3D tilt effect on the hover event. It adjusts angles and perspectives based on mouse movements, giving images a dynamic appearance. Helpful for adding interactive visual effects to images without external libraries.

You can use this code on websites featuring image galleries or product showcases. It adds interactivity, making images stand out for a more engaging user experience.

How to Create 3S Tilt Effect on Hover Using Vanilla JS

1. First of all, add the <img> tags for the images you want to apply the tilt effect to. Include the data-tilt attribute in each <img> tag. Replace the src attribute with the URL of your own images:

<img data-tilt src="https://source.unsplash.com/500x500?mountains=1" alt="mountains" width="500" height="500">
<img data-tilt src="https://source.unsplash.com/600x400?mountains=2" alt="mountains" width="600" height="400">

2. Ensure your CSS includes the necessary styling for the images and the layout. The following code contains styles for the images and basic layout adjustments. Customize as needed for your project.

::after {
  box-sizing: border-box;
html {
  font-family: system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  -webkit-text-size-adjust: none;
     -moz-text-size-adjust: none;
          text-size-adjust: none;

body {
  display: grid;
  place-items: center;
  gap: 4em;
  min-height: 100vh;
  margin: 0;
  padding: 4em;
  background: #f0f0fa;

img {
  max-width: 100%;
  height: auto;
  border-radius: 1em;
  box-shadow: 0 0 2em rgba(0, 0, 0, 0.25);
  margin: 50px auto;

3. Finally, include the following JavaScript code in your project. This code creates a tilt() method that enables the 3D tilt effect on images. Within the tilt() method, you can adjust various options like angle, perspective, scale, and more. Experiment with these to achieve the desired tilt effect.

Element.prototype.tilt = function (options) {

	// ----- config ----- //

	const config = {
		angle:            options?.angle            ?? 10,
		invert:           options?.invert           ?? false,
		perspective:      options?.perspective      ?? 1000,
		reset:            options?.reset            ?? true,
		scale:            options?.scale            ?? 1,
		transformElement: options?.transformElement ? this.querySelector(options.transformElement) : this,
		transitionEasing: options?.transitionEasing ?? 'cubic-bezier(.03, .98, .52, .99)',
		transitionSpeed:  options?.transitionSpeed  ?? 1500,

	let timeout;

	// ----- functions ----- //

	const setTransition = (el, config) => {
		if (typeof config.transitionSpeed === 'number') {
			config.transformElement.style.transition = `transform ${config.transitionSpeed}ms ${config.transitionEasing}`;

			if (timeout !== undefined) clearTimeout(timeout);

			timeout = setTimeout(() => {
				config.transformElement.style.transition = '';
			}, config.transitionSpeed);

	const handleOver = (e, config) => {
		setTransition(this, config);

		if (typeof config.perspective === 'number') {
			this.style.setProperty('--tilt-perspective', `${config.perspective}px`);

		if (typeof config.scale === 'number') {
			this.style.setProperty('--tilt-scale', `${config.scale}`);

	const handleMove = (e, config) => {
		let rect   = this.getBoundingClientRect();
		let x_pos  = Math.ceil(e.clientX - rect.left);
		let y_pos  = Math.ceil(e.clientY - rect.top);
		let w_half = rect.width / 2;
		let h_half = rect.height / 2;
		let x_rot  = config.angle / h_half * (h_half - y_pos);
		let y_rot  = config.angle / w_half * (w_half - x_pos);

		if (typeof config.invert === 'boolean' && config.invert) {
			x_rot *= -1;
			y_rot *= -1;

		this.style.setProperty('--tilt-x', `${x_rot.toFixed(2) * -1}deg`);
		this.style.setProperty('--tilt-y', `${y_rot.toFixed(2)}deg`);

	const handleOut = (e, config) => {
		this.style.setProperty('--tilt-scale', 1);

		if (typeof config.reset === 'boolean' && config.reset) {
			this.style.setProperty('--tilt-x', '0deg');
			this.style.setProperty('--tilt-y', '0deg');

		setTransition(this, config);

	// ----- events ----- //

	this.addEventListener('mouseover', e => handleOver(e, config));
	this.addEventListener('mousemove', e => handleMove(e, config));
	this.addEventListener('mouseout', e => handleOut(e, config));

	// ----- initial styles ----- //

	config.transformElement.style.willChange = 'transform';
	config.transformElement.style.transform = 'perspective(var(--tilt-perspective)) scale(var(--tilt-scale)) rotateX(var(--tilt-x)) rotateY(var(--tilt-y))';

document.querySelectorAll('[data-tilt]').forEach(el => {
		//override defaults:
		//angle: 10,
		//invert: false,
		//perspective: 1000,
		//reset: true,
		//scale: 1,
		//transformElement: '',
		//transitionEasing: 'cubic-bezier(.03, .98, .52, .99)',
		//transitionSpeed: 1500,

That’s all! hopefully, you have successfully created a 3D tilt effect on hover using Vanilla JS. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About CodeHim

Free Web Design Code & Scripts - CodeHim is one of the BEST developer websites that provide web designers and developers with a simple way to preview and download a variety of free code & scripts. All codes published on CodeHim are open source, distributed under OSD-compliant license which grants all the rights to use, study, change and share the software in modified and unmodified form. Before publishing, we test and review each code snippet to avoid errors, but we cannot warrant the full correctness of all content. All trademarks, trade names, logos, and icons are the property of their respective owners... find out more...