Need a thank you page? Grab our free HTML, Tailwind CSS, and JavaScript code snippet. It's easy to use and redirects users back to your homepage.
Table of Contents
After a user submits a form, buys a product, or signs up for your newsletter, it's important to confirm the action was successful. The best way to do this is with a "Thank You" page.
This post provides a complete copy-and-paste code snippet for a clean, modern thank you page.
What this code does:
- Shows a "Thank You!" message.
- Tells the user you received their submission.
- Automatically redirects the user back to the homepage after 5 seconds.
Prerequisites: We are using HTML for the structure, Tailwind CSS for styling, and JavaScript for the redirect. You don't need to install anything. We will load Tailwind CSS using a simple script link in the HTML head, which is the easiest way to get started.
Source Code
Step 1 (HTML Code):
First, we'll start with the HTML. This file will create the main layout for our thank you page. We are using Tailwind CSS classes (like flex, bg-gray-900, text-white) directly in the HTML for most of the design.
Copy the code below and paste it into your index.html file.
Step 2 (CSS Code):
Next, we move to the CSS. While Tailwind handles most of the design, it can't cover unique features like a custom cursor or the starting state for our reveal animation.
Create a styles.css file and paste this code inside it.
/* Apply the fonts via Tailwind config or style block */
body {
font-family: 'Inter', sans-serif;
overflow: hidden; /* Prevent page scroll, only right panel scrolls */
cursor: none; /* Hide the default cursor */
background-color: #f9fafb; /* bg-gray-50 */
}
a,
button {
cursor: none; /* Hide default cursor for links too */
}
.font-serif {
font-family: 'Playfair Display', serif;
}
/* --- Panel Slide-in Animations --- */
.panel-left {
animation: slideInFromLeft 0.8s cubic-bezier(0.23, 1, 0.32, 1) forwards;
opacity: 0;
}
.panel-right {
animation: slideInFromRight 0.8s cubic-bezier(0.23, 1, 0.32, 1) forwards;
opacity: 0;
}
@keyframes slideInFromLeft {
0% {
transform: translateX(-100%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideInFromRight {
0% {
transform: translateX(100%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
/* --- Staggered Content Reveal --- */
.reveal-item {
opacity: 0;
transform: translateY(20px);
transition: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
}
.reveal-item.is-visible {
opacity: 1;
transform: translateY(0);
}
/* --- Marquee Text Reveal --- */
.marquee-container {
position: relative;
height: 1.2em;
line-height: 1.2em;
overflow: hidden;
display: block;
}
.marquee-text {
display: block;
transform: translateY(110%);
transition: transform 1s cubic-bezier(0.23, 1, 0.32, 1);
transition-delay: var(--delay, 0s);
}
.is-visible .marquee-text {
transform: translateY(0);
}
/* --- Scroll-Linked Fade Animation --- */
#scroll-content {
transition: opacity 0.4s ease;
}
#scroll-content.is-scrolled {
opacity: 0.2;
}
/* --- Image Preview & Pan-Zoom Effect --- */
#image-preview-container {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.5s ease;
z-index: 0;
}
#preview-image {
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0.25;
filter: grayscale(50%);
transition: transform 6s ease-out, opacity 0.5s ease;
transform: scale(1.1); /* Start slightly zoomed in */
}
#preview-image.is-panning {
transform: scale(1) rotate(-1deg); /* Zoom out and rotate slightly on hover */
}
/* --- Interactive Link Styling --- */
.preview-link {
transition: all 0.3s ease;
position: relative;
}
.link-text {
position: relative;
display: inline-block;
}
/* Animated underline */
.link-text::after {
content: '';
position: absolute;
bottom: -2px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 2px;
background-color: #14532d;
transition: width 0.4s cubic-bezier(0.23, 1, 0.32, 1);
}
.preview-link:hover .link-text::after {
width: 100%;
}
/* Icon styling */
.link-icon {
width: 1.25rem;
height: 1.25rem;
transition: transform 0.3s ease;
}
.preview-link:hover .link-icon {
transform: translateX(5px);
}
/* --- Custom Cursor --- */
.custom-cursor-dot {
position: fixed;
width: 8px;
height: 8px;
background-color: #14532d;
border-radius: 50%;
pointer-events: none;
transform: translate(-50%, -50%);
transition: width 0.3s ease, height 0.3s ease, background-color 0.3s ease;
z-index: 9999;
}
.custom-cursor-dot.cursor-hover {
width: 32px;
height: 32px;
background-color: rgba(20, 83, 45, 0.3);
} Step 3 (JavaScript Code):
This is our final step. Here, we'll use JavaScript to make our functions work. We will write all of this logic in our script.js file.
Create a script.js file and paste this code inside it.
document.addEventListener('DOMContentLoaded', () => {
// --- 1. Personalization ---
try {
const urlParams = new URLSearchParams(window.location.search);
const name = urlParams.get('name');
const nameElement = document.getElementById('user-name');
if (name) {
const sanitizedName = name.replace(/<[^>]*>?/gm, '');
if (sanitizedName) {
nameElement.textContent = sanitizedName;
}
}
} catch (e) {
console.error('Error processing URL parameters:', e);
}
// --- 2. Staggered Reveal Animation ---
const revealItems = document.querySelectorAll('.reveal-item');
revealItems.forEach((item, index) => {
// Use a standard delay for all non-marquee items
let delay = 1200 + index * 150;
// Marquee items use their own inline style --delay
if (item.classList.contains('marquee-container')) {
delay = 0; // The animation will be handled by the CSS delay
}
setTimeout(() => {
item.classList.add('is-visible');
}, delay);
});
// --- 3. Interactive Image Preview (Desktop Only) ---
if (window.matchMedia('(min-width: 768px)').matches) {
const links = document.querySelectorAll('.preview-link');
const previewContainer = document.getElementById('image-preview-container');
const previewImage = document.getElementById('preview-image');
links.forEach((link) => {
link.addEventListener('mouseenter', () => {
const imageUrl = link.getAttribute('data-image');
if (imageUrl) {
previewImage.src = imageUrl;
previewContainer.style.opacity = '1';
previewImage.classList.add('is-panning'); // Add class to start pan/zoom
}
});
link.addEventListener('mouseleave', () => {
previewContainer.style.opacity = '0';
previewImage.classList.remove('is-panning'); // Remove class to stop
// Reset transform to prepare for next hover
previewImage.style.transition = 'opacity 0.5s ease'; // Only transition opacity on exit
previewImage.style.transform = 'scale(1.1)';
// Force reflow to reset transition
void previewImage.offsetWidth;
previewImage.style.transition =
'transform 6s ease-out, opacity 0.5s ease';
});
});
}
// --- 4. Custom Cursor Logic ---
const cursorDot = document.querySelector('.custom-cursor-dot');
const hoverElements = document.querySelectorAll('a, button');
window.addEventListener('mousemove', (e) => {
cursorDot.style.left = `${e.clientX}px`;
cursorDot.style.top = `${e.clientY}px`;
});
hoverElements.forEach((el) => {
el.addEventListener('mouseenter', () =>
cursorDot.classList.add('cursor-hover')
);
el.addEventListener('mouseleave', () =>
cursorDot.classList.remove('cursor-hover')
);
});
// --- 5. Scroll-Linked Fade Animation ---
const scrollPanel = document.getElementById('scroll-panel');
const scrollContent = document.getElementById('scroll-content');
if (scrollPanel && scrollContent) {
scrollPanel.addEventListener('scroll', () => {
if (scrollPanel.scrollTop > 50) {
scrollContent.classList.add('is-scrolled');
} else {
scrollContent.classList.remove('is-scrolled');
}
});
}
});Final Output:
Conclusion:
That's all there is to it! You now have a professional, responsive "Thank You" page. You can easily customize the text or change the colors by editing the Tailwind CSS classes in the HTML file. For example, to change the green checkmark to blue, you would change text-green-500 to text-blue-500.
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊


