Free
Hero
Sproutline Hero
A hero block extracted from the Sproutline template, available in Tailwind CSS and Bootstrap.
0
3
A hero block extracted from the Sproutline template, available in Tailwind CSS and Bootstrap.
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.FontAwesomeConfig = { autoReplaceSvg: 'nest' };
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sproutline Hero | Tailwind CSS UI Block</title>
<meta name="description" content="A hero block extracted from the Sproutline template, available in Tailwind CSS and Bootstrap.">
<meta name="keywords" content="Sproutline, Tailwind CSS template, HTML website template, agency template, web design agency, dark website template, subscription design studio, growth calculator, case study page, pricing page">
<meta name="author" content="Let's templates">
<link rel="canonical" href="">
<meta property="og:type" content="product">
<meta property="og:site_name" content="Let's templates">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="">
<meta property="og:title" content="Sproutline | Tailwind CSS Agency Template">
<meta property="og:description" content="A dark, lime-accented Tailwind CSS agency template for web design studios, with a growth calculator, project hover list and case study pages.">
<meta property="og:image" content="">
<meta property="og:image:alt" content="Sproutline template preview">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="">
<meta name="twitter:title" content="Sproutline | Tailwind CSS Agency Template">
<meta name="twitter:description" content="A dark, lime-accented Tailwind CSS agency template for web design studios, with a growth calculator, project hover list and case study pages.">
<meta name="twitter:image" content="">
<meta name="twitter:image:alt" content="Sproutline template preview">
<script src="https://cdn.tailwindcss.com/3.4.17"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: { night: '#060d1a', deep: '#0a1528', ocean: '#12306b', lime: { DEFAULT: '#a3e635', dark: '#84cc16' }, haze: '#c5d0e2' },
fontFamily: { sans: ['"Plus Jakarta Sans"', 'sans-serif'], serif: ['"DM Serif Display"', 'serif'] }
}
}
}
</script>
<style>
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: 180ms ease-out both page-fade-out; }
::view-transition-new(root) { animation: 220ms ease-in both page-fade-in; }
@keyframes page-fade-out { to { opacity: 0; } }
@keyframes page-fade-in { from { opacity: 0; } }
html { scroll-behavior: smooth; }
[hidden] { display: none !important; }
body { background: radial-gradient(60rem 40rem at 0% 20%, rgba(29, 78, 216, .35), transparent 60%), radial-gradient(50rem 40rem at 100% 0%, rgba(29, 78, 216, .3), transparent 60%), #071226; }
.frame-plain { background: #070f1e; }
.frame-glow { background: radial-gradient(40rem 22rem at 50% 30%, rgba(37, 99, 235, .22), transparent 70%), #070f1e; }
.marquee { animation: marquee 32s linear infinite; }
.marquee:hover { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-50%); } }
.fade-edges { mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); }
.grow-bar { transition: width .6s ease; }
.hover-image { transition: opacity .3s ease; }
.reveal-ready [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity .6s ease, transform .6s ease; transition-delay: var(--reveal-delay, 0ms); }
.reveal-ready [data-reveal].is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.marquee { animation: none; }
.grow-bar, .hover-image { transition: none; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
</style>
</head>
<body class="font-sans text-white antialiased">
<% active_page = "index" %>
<% nav = { "projects" => "Projects", "benefits" => "Benefits", "services" => "Services", "pricing" => "Pricing" } %>
<% nav.each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% { "index" => "Home" }.merge(nav).merge("contact" => "Contact").each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<!-- block:start hero -->
<section class="px-3 sm:px-6 lg:px-24">
<div class="frame-glow mx-auto max-w-7xl border-x-4 border-white/10 px-5 pb-16 pt-16 text-center md:px-12 md:pt-24">
<p class="flex items-center justify-center gap-3 text-xl font-semibold">Rated 4.9 <span class="flex gap-1 text-lime" aria-hidden="true"><% 5.times do %><i class="fa-solid fa-star"></i><% end %></span></p>
<p class="mt-2 text-haze">by 300+ founders and marketing teams</p>
<h1 class="mx-auto mt-8 max-w-5xl text-4xl font-semibold leading-[1.1] tracking-tight sm:text-5xl lg:text-7xl">A pretty site is a start. You need one that <span class="text-lime">grows.</span></h1>
<p class="mx-auto mt-6 max-w-xl text-lg leading-relaxed text-haze">We design and build fast websites that turn visitors into customers. Unlimited requests, one flat monthly plan, zero hiring headaches.</p>
<div class="mt-9 flex flex-wrap justify-center gap-4">
<a href="contact.html" class="rounded-xl border-2 border-lime/70 bg-lime px-7 py-4 font-semibold text-night shadow-[0_0_30px_rgba(163,230,53,.35)] transition hover:bg-lime-dark">Book an intro call</a>
<a href="pricing.html" class="rounded-xl border-2 border-lime/70 px-7 py-4 font-semibold text-lime transition hover:bg-lime/10">See the plan</a>
</div>
<p class="mt-6 flex items-center justify-center gap-3 font-medium"><span class="relative flex h-2.5 w-2.5"><span class="absolute inset-0 animate-ping rounded-full bg-lime opacity-70 motion-reduce:animate-none"></span><span class="relative h-2.5 w-2.5 rounded-full bg-lime"></span></span>3 project slots open for next month</p>
</div>
</section>
<!-- block:end hero -->
<script>
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
const watchMotion = !reducedMotion && !navigator.webdriver && 'IntersectionObserver' in window;
document.querySelectorAll('[data-menu-toggle]').forEach((button) => {
const menu = document.getElementById(button.getAttribute('aria-controls'));
button.addEventListener('click', () => {
const open = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!open));
menu.classList.toggle('hidden', open);
});
});
document.querySelectorAll('[data-hover-list]').forEach((root) => {
const image = root.querySelector('[data-hover-image]');
root.querySelectorAll('[data-hover-row]').forEach((row) => {
row.addEventListener('mouseenter', () => { image.src = row.dataset.image; image.alt = row.dataset.alt; image.style.opacity = '1'; });
row.addEventListener('mousemove', (event) => { image.style.transform = `translate(${event.clientX + 24}px, ${event.clientY - 110}px) rotate(-3deg)`; });
row.addEventListener('mouseleave', () => { image.style.opacity = '0'; });
});
});
document.querySelectorAll('[data-growth]').forEach((root) => {
const oldRate = Number(root.dataset.oldRate) / 100;
const newRate = Number(root.dataset.newRate) / 100;
const money = (value) => `$${Math.round(value).toLocaleString('en-US')}`;
const paint = () => {
const visitors = Number(root.querySelector('[data-visitors]').value);
const value = Number(root.querySelector('[data-value]').value);
const before = visitors * oldRate * value;
const after = visitors * newRate * value;
root.querySelector('[data-visitors-label]').textContent = visitors.toLocaleString('en-US');
root.querySelector('[data-value-label]').textContent = money(value);
root.querySelector('[data-old-revenue]').textContent = money(before);
root.querySelector('[data-new-revenue]').textContent = money(after);
root.querySelector('[data-old-bar]').style.width = `${(before / after) * 100}%`;
root.querySelector('[data-extra]').textContent = `+${money(after - before)}`;
const days = Math.max(1, Math.ceil(4950 / ((after - before) / 30)));
root.querySelector('[data-payback]').textContent = days > 90 ? 'about 3 months' : `${days} day${days === 1 ? '' : 's'}`;
};
root.addEventListener('input', paint);
paint();
});
document.querySelectorAll('[data-tabs], [data-stepper]').forEach((root) => {
const tabs = [...root.querySelectorAll('[role="tab"]')];
const fill = root.querySelector('[data-step-fill]');
const select = (tab) => {
tabs.forEach((other) => { const on = other === tab; other.setAttribute('aria-selected', String(on)); other.tabIndex = on ? 0 : -1; document.getElementById(other.getAttribute('aria-controls')).hidden = !on; });
if (fill) fill.style.width = `${((tabs.indexOf(tab) + 1) / tabs.length) * 100}%`;
};
tabs.forEach((tab, index) => {
tab.addEventListener('click', () => select(tab));
tab.addEventListener('keydown', (event) => {
const move = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[event.key];
if (!move) return;
event.preventDefault();
const next = tabs[(index + move + tabs.length) % tabs.length];
select(next); next.focus();
});
});
});
document.querySelectorAll('[data-billing]').forEach((root) => {
const price = root.querySelector('[data-price]');
root.querySelectorAll('[data-billing-option]').forEach((option) => option.addEventListener('click', () => {
root.querySelectorAll('[data-billing-option]').forEach((other) => other.setAttribute('aria-pressed', String(other === option)));
price.textContent = price.dataset[option.dataset.billingOption];
}));
});
document.querySelectorAll('[data-project-browser]').forEach((root) => {
const list = root.querySelector('[data-project-list]');
const items = [...list.children];
const search = root.querySelector('[data-project-search]');
const sort = root.querySelector('[data-project-sort]');
const count = root.querySelector('[data-project-count]');
const apply = () => {
const query = String(search.value || '').trim().toLowerCase();
const sorted = [...items].sort((a, b) => sort.value === 'lift' ? b.dataset.lift - a.dataset.lift : sort.value === 'az' ? a.dataset.name.localeCompare(b.dataset.name) : b.dataset.year - a.dataset.year);
let shown = 0;
sorted.forEach((item) => { const match = !query || item.textContent.toLowerCase().includes(query); item.hidden = !match; if (match) shown += 1; list.append(item); });
count.textContent = shown;
root.querySelector('[data-project-empty]').hidden = shown > 0;
};
search.addEventListener('input', apply);
sort.addEventListener('change', apply);
apply();
});
document.querySelectorAll('[data-faq-search]').forEach((root) => {
const input = root.querySelector('[data-faq-query]');
const items = [...root.querySelectorAll('[data-faq-item]')];
input.addEventListener('input', () => {
const query = String(input.value || '').trim().toLowerCase();
let shown = 0;
items.forEach((item) => { const match = !query || item.textContent.toLowerCase().includes(query); item.hidden = !match; if (match) shown += 1; });
root.querySelector('[data-faq-empty]').hidden = shown > 0;
});
});
document.querySelectorAll('[data-chip-form]').forEach((form) => {
form.querySelectorAll('[data-chip]').forEach((chip) => chip.addEventListener('click', () => {
const single = chip.closest('[data-single]');
if (single) single.querySelectorAll('[data-chip]').forEach((other) => other.setAttribute('aria-pressed', String(other === chip)));
else chip.setAttribute('aria-pressed', String(chip.getAttribute('aria-pressed') !== 'true'));
form.querySelector('[data-chip-summary]').textContent = [...form.querySelectorAll('[data-chip][aria-pressed="true"]')].map((c) => c.dataset.chip).join(' · ') || 'Nothing picked yet';
}));
form.addEventListener('submit', (event) => {
event.preventDefault();
const status = form.querySelector('[data-form-status]');
const picked = form.querySelectorAll('[data-chip][aria-pressed="true"]').length;
if (!picked || !form.checkValidity()) { status.textContent = form.dataset.error; return; }
status.textContent = form.dataset.success;
});
});
document.querySelectorAll('[data-contact-form]').forEach((form) => {
form.addEventListener('submit', (event) => {
event.preventDefault();
const status = form.querySelector('[data-form-status]');
if (!form.checkValidity()) {
status.textContent = form.dataset.error;
form.querySelector(':invalid')?.focus();
return;
}
status.textContent = form.dataset.success;
form.reset();
});
});
document.querySelectorAll('[data-current-year]').forEach((el) => { el.textContent = new Date().getFullYear(); });
(() => {
const items = document.querySelectorAll('[data-reveal]');
if (!items.length || !watchMotion) return;
document.documentElement.classList.add('reveal-ready');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
entry.target.classList.add('is-visible');
observer.unobserve(entry.target);
});
}, { rootMargin: '0px 0px -10% 0px' });
items.forEach((item) => observer.observe(item));
})();
</script>
</body>
</html>
Agency
Unlock the entire library of premium templates and blocks. Renews automatically, cancel anytime.