Vue componentFree

Tilt

Tilt is an interactive Vue component that brings depth and motion to any element. It reacts smoothly to mouse movement, tilting toward the pointer while casting dynamic shadows, creating a realistic 3D effect that makes your UI feel more alive and engaging.

by Steffan Halvorsenv1.0.0Updated last year

Install
Full screen ↗

Code

16 files in the repo
<template>
	<div
		class="tilt-container"
		:class="{
			darkmode: theme === 'dark'
		}"
		:style="{
			borderRadius: shadowBorderRadius + '%'
		}"
		ref="container"
	>
		<div
			class="tilt-image"
			:style="{
				border: border ? border : (theme === 'dark' ? '10px solid white' : '10px solid black')
			}"
			v-bind="$attrs"
		>
			<slot>
				<img
					src="@/assets/alps.png"
					alt="tilt image"
				/>
			</slot>
		</div>
	</div>
</template>
<script>
	export default {
		name: 'Tilt',
		inject: ['theme'],
		props: {
			maxTilt: {
				type: Number,
				default: 8,
				control: 'slider',
				min: 0,
				max: 45
			},
			shadowBlur: {
				type: Number,
				default: 60,
				control: 'slider',
				min: 0,
				max: 300
			},
			shadowDistanceX: {
				type: Number,
				default: 3,
				control: 'slider',
				min: 0,
				max: 20
			},
			shadowDistanceY: {
				type: Number,
				default: 3,
				control: 'slider',
				min: 0,
				max: 20
			},
			shadowBorderRadius: {
				type: Number,
				default: 10,
				control: 'slider',
				min: 0,
				max: 100
			},
			shadowColor: {
				type: String,
				default: '',
				control: 'color'
			},
			border: {
				type: String,
				default: ''
			}
		},
		mounted() {
			window.addEventListener('mousemove', this.handleMouseMove);
			window.addEventListener('mouseleave', this.resetTilt);
		},
		beforeUnmount() {
			window.removeEventListener('mousemove', this.handleMouseMove);
			window.removeEventListener('mouseleave', this.resetTilt);
		},
		computed: {
			shadowColored() {
				if (this.shadowColor) return this.shadowColor;
				return this.theme === 'dark' ? 'rgba(255, 255, 255, 0.25)' : 'rgba(0, 0, 0, 0.25)';
			}
		},
		methods: {
			handleMouseMove(e) {
				const rect = this.$refs.container.getBoundingClientRect();
				// center of component
				const centerX = rect.left + rect.width / 2;
				const centerY = rect.top + rect.height / 2;
				// distance from cursor to center
				const offsetX = e.clientX - centerX;
				const offsetY = e.clientY - centerY;
				// normalize -1 to 1
				const percentX = offsetX / (rect.width / 2);
				const percentY = offsetY / (rect.height / 2);
				// clamp to avoid crazy tilts far outside
				const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
				const tiltX = clamp(-percentY, -1, 1) * this.maxTilt;
				const tiltY = clamp(percentX, -1, 1) * this.maxTilt;
				this.$refs.container.style.transform = `rotateX(${tiltX}deg) rotateY(${tiltY}deg) translateZ(10px)`;
				this.$refs.container.style.boxShadow = `${-tiltY * this.shadowDistanceX}px ${tiltX * this.shadowDistanceY}px ${this.shadowBlur}px ${this.shadowColored}`;
			},
			resetTilt() {
				this.$refs.container.style.transform = `rotateX(0deg) rotateY(0deg) translateZ(0)`;
				this.$refs.container.style.boxShadow = `0 12px ${this.shadowBlur}px ${this.shadowColored}`;
			}
		}
	};

</script>
<style scoped>
	.tilt-container {
		display: inline-block;
		/* Add perspective for enhanced depth */
		transition: transform 0.15s ease-out;
		will-change: transform, box-shadow;
	}

	.tilt-image {
		display: block;
		width: 100%;
		height: auto;
		border-radius: 4px;
		transform-style: preserve-3d;
	}

</style>

Props

PropTypeDefaultDescription
maxTiltNumber8—
shadowBlurNumber60—
shadowDistanceXNumber3—
shadowDistanceYNumber3—
shadowBorderRadiusNumber10—
shadowColorString''—
borderString''—
All media & effects →
Preview of CarouselFree

Component · Media & effects

Carousel

Carousel is a flexible Vue component for showcasing content with smooth horizontal or vertical rotation. Designed for both simplicity and style, it lets you present images, cards, or custom elements in an engaging, interactive way that adapts to any layout.

Preview of Hero SplitFree

Component · Hero sections

Hero Split

Split Vue 3 hero section with copy and two CTAs on the left and a Tailwind-drawn app window mockup on the right. Dark mode, typed props, no images.

by Vueplay1 installs
Preview of Bento GridFree

Component · Feature sections

Bento Grid

Bento-style Vue 3 feature grid with wide and tall tiles and small CSS-drawn visuals like maps, timelines and code. Tailwind CSS, dark mode, typed tiles.

by Vueplay
Preview of BlockFree

Component · Layout

Block

Pro feature

Upgrade to Pro

Upgrade to unlock more of Vueplay. Cancel any time.

  • Custom domains with HTTPS
  • Private projects
  • No "Made with Vueplay" badge
  • GitHub sync

$120/year

Compare plansBilling settings