Here is HTML, CSS, JS code for a very cool hero section that has a spotlight effect, cursor tracking, and menu. The code uses the GSAP JavaScript library. The menu is also very cool that opens up with expanding animation. Everything is responsive as well.
Check out this demo below first and then you can have a look at the source code that you can directly copy-paste to your local HTML file and run it as it is.
DEMO
Open demo in full window – https://demos.webdevpuneet.com/set1/hero-cursor-tracking/index.html
Source Code
<!-- webdevpuneet.com -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hero with cursor tracking and menu using GSAP</title>
<meta name="description" content="Demo for Hero with cursor tracking and menu using GSAP" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
<meta name="robots" content="INDEX,FOLLOW" />
<script src="https://unpkg.co/gsap@3/dist/gsap.min.js"></script>
<style>
@import url("https://fonts.googleapis.com/css?family=Montserrat:700");
* {
box-sizing: border-box;
}
:root {
--bg: rgb(9, 14, 23);
--gradientBg: linear-gradient(45deg, #40e0d0, #9932cc, #ff1493, orange);
}
body {
font-family: Montserrat, sans-serif;
min-height: 100vh;
margin: 0;
padding: 0;
background-color: var(--bg);
color: #ffffff;
}
/* Reset */
a {
color: inherit;
}
ul {
list-style: none;
}
button {
border-radius: 0.4em;
background: var(--bg);
color: white;
border: none;
padding: 0.5rem;
font-size: inherit;
cursor: pointer;
}
.wrapper {
position: relative;
}
/* Text */
.hero__heading {
font-size: clamp(2rem, 5vw, 8rem);
text-transform: uppercase;
margin: 0;
}
/* Menu */
.menu {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: fixed;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;
background: var(--gradientBg);
clip-path: circle(0 at calc(100% - 2rem) 2rem);
transition: clip-path 500ms;
z-index: 1;
font-size: clamp(1rem, 2vw, 4rem);
}
.menu.is-open {
clip-path: circle(200% at calc(100% - 2rem) 2rem);
pointer-events: all;
}
.menu a {
display: block;
padding: 0.5em;
}
.menu-button {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 2;
}
.menu-button span:last-child,
.menu-button.is-active span:first-child {
display: none;
}
.menu-button.is-active span:last-child {
display: inline;
}
/* Hero */
.hero {
min-height: 100vh;
padding: clamp(1rem, 2vw, 5rem);
display: flex;
align-items: center;
}
.hero--secondary {
--mask: radial-gradient(
circle at var(--x, 50%) var(--y, 50%),
black var(--maskSize1, 0),
transparent 0,
transparent var(--maskSize2, 0),
black var(--maskSize2, 0),
black var(--maskSize3, 0),
transparent 0);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--gradientBg);
color: rgb(9, 14, 23);
-webkit-mask-image: var(--mask);
mask-image: var(--mask);
}
</style>
</head>
<body>
<header>
<button class="menu-button" data-btn="menu">
<span>Menu</span>
<span>Close</span>
</button>
<nav class="menu" data-menu>
<ul>
<li>
<a href="">About me</a>
</li>
<li>
<a href="">Projects</a>
</li>
<li>
<a href="">Writing</a>
</li>
</ul>
</nav>
</header>
<div class="wrapper">
<div class="hero">
<h1 class="hero__heading">Welcome to my website</h1>
</div>
<div class="hero hero--secondary" aria-hidden="true" data-hero>
<p class="hero__heading">Welcome to my website</p>
</div>
</div>
<div class="article-link" style="margin-bottom:20px;">
<a href="https://webdevpuneet.com/hero-with-cool-spotlight-effect-and-cursor-tracking/" target="_blank" style="display: inline-block; color:blue:!important;text-decoration: none;border:1px solid blue;color:blue;line-height:1;border-radius:25px;font-size:14px;padding:5px 20px;display:inline-block;">View article and source code »</a>
</div>
<script>
const hero = document.querySelector('[data-hero]')
/* Menu */
const menuButton = document.querySelector('[data-btn="menu"]')
const menu = document.querySelector('[data-menu]')
menuButton.addEventListener('click', () => {
menu.classList.toggle('is-open')
menuButton.classList.toggle('is-active')
})
/* Timeline */
const tl = gsap.timeline()
tl
.to(hero, {
'--maskSize1': '20%',
duration: 0.5,
ease: 'back.out(2)',
})
.to(hero, {
'--maskSize2': '28%',
'--maskSize3': 'calc(28% + 0.1rem)',
duration: 0.5,
delay: 0.5,
ease: 'back.out(2)',
})
/* Cursor */
window.addEventListener('mousemove', (e) => {
const { clientX, clientY } = e
const x = Math.round((clientX / window.innerWidth) * 100)
const y = Math.round((clientY / window.innerHeight) * 100)
gsap.to(hero, {
'--x': `${x}%`,
'--y': `${y}%`,
duration: 0.3,
ease: 'sine.out',
})
})
</script>
</body>
</html>
You must be logged in to post a comment.