Free
Hero
Fernwise Hero
A hero block extracted from the Fernwise template, available in Tailwind CSS and Bootstrap.
0
4
A hero block extracted from the Fernwise 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>Fernwise Hero | Tailwind CSS UI Block</title>
<meta name="description" content="A hero block extracted from the Fernwise template, available in Tailwind CSS and Bootstrap.">
<meta name="keywords" content="Fernwise, Tailwind CSS template, HTML website template, fintech template, finance website, wealth management template, banking app landing page, investment website, pricing table, sign up form">
<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="Fernwise | Tailwind CSS Fintech Template">
<meta property="og:description" content="A calm, modern Tailwind CSS fintech template with a bento hero and live chart, a services carousel, a comparison table and a multi-step sign-up.">
<meta property="og:image" content="">
<meta property="og:image:alt" content="Fernwise template preview">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="">
<meta name="twitter:title" content="Fernwise | Tailwind CSS Fintech Template">
<meta name="twitter:description" content="A calm, modern Tailwind CSS fintech template with a bento hero and live chart, a services carousel, a comparison table and a multi-step sign-up.">
<meta name="twitter:image" content="">
<meta name="twitter:image:alt" content="Fernwise 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=Archivo:wght@700;800&family=Mulish:wght@400;500;600&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: { pine: { DEFAULT: '#1e3d36', light: '#2f6b5e' }, jade: '#4fa595', paper: '#f5f5f3', stone: '#ecece9', cream: '#ecebdc', mist: '#dde9e7', zest: '#e6e04a' },
fontFamily: { sans: ['Mulish', 'sans-serif'], brand: ['Archivo', 'sans-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; }
.arches { background-image: radial-gradient(circle at 70% 120%, transparent 38%, rgba(236,235,220,.55) 38.4%, transparent 39.2%, transparent 46%, rgba(236,235,220,.55) 46.4%, transparent 47.2%); }
.arches-dark { background-image: radial-gradient(circle at 12% 110%, transparent 30%, rgba(255,255,255,.08) 30.4%, transparent 31.4%, transparent 38%, rgba(255,255,255,.08) 38.4%, transparent 39.4%), radial-gradient(circle at 92% 110%, transparent 30%, rgba(255,255,255,.08) 30.4%, transparent 31.4%, transparent 38%, rgba(255,255,255,.08) 38.4%, transparent 39.4%), linear-gradient(110deg, #4fa595 0%, #2f6b5e 45%, #1e3d36 100%); }
.marquee { animation: marquee 30s linear infinite; }
.marquee:hover { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-50%); } }
.chart-line { transition: d .6s ease; }
.ring-fill { transition: stroke-dashoffset 1.2s ease; }
.draw { stroke-dasharray: 600; stroke-dashoffset: 0; transition: stroke-dashoffset 1.4s ease; }
.reveal-ready .draw:not(.is-drawn) { stroke-dashoffset: 600; }
[data-word] { transition: color .4s ease; }
.rail-card { transition: background-color .4s ease, color .4s ease, transform .4s ease; }
.rail-card[data-active="true"] { background: #1e3d36; color: #fff; transform: translateY(-.75rem); }
.rail-card[data-active="true"] .rail-muted { color: rgba(255,255,255,.75); }
.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; }
.chart-line, .ring-fill, .draw, [data-word], .rail-card { transition: none; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
</style>
</head>
<body class="bg-paper font-sans text-pine antialiased">
<% active_page = "index" %>
<% nav = { "index" => "Home", "about" => "About us", "services" => "Services", "pricing" => "Pricing", "faq" => "FAQ" } %>
<% nav.each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% nav.merge("contact" => "Contact", "signup" => "Sign up").each do |slug, label| %>
<% active = active_page == slug %>
<% end %>
<% periods = { "1M" => ["$12,480", "M0 70 C 30 66 45 50 70 54 S 110 30 140 40 S 190 22 220 26 S 260 12 280 18", "+4.1%"], "6M" => ["$196,000", "M0 78 C 25 80 30 40 55 44 S 85 28 105 42 S 140 30 160 34 S 200 10 225 18 S 260 30 280 26", "+18.6%"], "1Y" => ["$342,900", "M0 84 C 30 82 50 70 80 62 S 130 50 160 36 S 210 30 240 14 S 270 8 280 6", "+32.4%"] } %>
<!-- block:start hero -->
<section class="mx-auto grid max-w-7xl items-center gap-14 px-5 pb-16 pt-6 md:px-10 lg:grid-cols-[1.05fr_1fr] lg:pb-24">
<div class="grid grid-cols-2 gap-4 sm:gap-5">
<div class="flex flex-col justify-between rounded-[1.75rem] bg-mist p-5 sm:p-6" data-reveal>
<span class="text-2xl" aria-hidden="true">✦✦</span>
<p class="mt-6 text-right text-sm sm:text-base">Active members</p>
<div class="mt-3 flex -space-x-2">
<% [3, 5, 8].each do |n| %><img src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-<%= n %>.jpg" alt="" class="h-8 w-8 rounded-full border-2 border-mist object-cover"><% end %>
<span class="grid h-8 w-8 place-items-center rounded-full border-2 border-mist bg-pine text-xs text-white" aria-hidden="true"><i class="fa-solid fa-plus"></i></span>
</div>
</div>
<div class="relative min-h-[11rem] rounded-[1.75rem] bg-gradient-to-br from-jade to-pine sm:min-h-[15rem]" data-reveal style="--reveal-delay: 80ms">
<img src="https://images.unsplash.com/photo-1563986768609-322da13575f3?auto=format&fit=crop&crop=focalpoint&fp-x=0.72&fp-y=0.55&fp-z=2.2&w=700&h=800&q=80" alt="Hand holding a phone showing a banking app next to a laptop" class="absolute inset-x-3 -top-8 bottom-3 h-[calc(100%+1.25rem)] w-[calc(100%-1.5rem)] rounded-[1.4rem] object-cover shadow-xl">
</div>
<div class="flex flex-col justify-between rounded-[1.75rem] bg-cream p-5 sm:p-6" data-reveal style="--reveal-delay: 160ms">
<p class="text-3xl font-medium">56+</p>
<div class="mt-6 flex items-end justify-between gap-2"><p class="text-lg">Currencies</p><i class="fa-solid fa-globe text-4xl" aria-hidden="true"></i></div>
</div>
<div class="rounded-[1.75rem] bg-pine p-5 text-white sm:p-6" data-chart data-reveal style="--reveal-delay: 240ms">
<div class="flex flex-wrap items-center justify-between gap-2">
<p class="text-lg font-medium" aria-live="polite"><span data-chart-value><%= periods["6M"][0] %></span> <span data-chart-change class="text-xs text-zest"><%= periods["6M"][2] %></span></p>
<div class="flex rounded-full bg-white/10 p-0.5 text-[11px]" role="group" aria-label="Chart period">
<% periods.each do |label, (value, path, change)| %>
<button type="button" data-period="<%= label %>" data-value="<%= value %>" data-path="<%= path %>" data-change="<%= change %>" aria-pressed="<%= label == '6M' %>" class="rounded-full px-2 py-1 transition aria-pressed:bg-zest aria-pressed:text-pine"><%= label %></button>
<% end %>
</div>
</div>
<svg viewBox="0 0 280 90" class="mt-4 w-full" role="img" aria-label="Portfolio value trend">
<g stroke="rgba(255,255,255,.12)"><line x1="0" y1="20" x2="280" y2="20"/><line x1="0" y1="45" x2="280" y2="45"/><line x1="0" y1="70" x2="280" y2="70"/></g>
<path data-chart-line class="chart-line" d="<%= periods["6M"][1] %>" fill="none" stroke="#e6e04a" stroke-width="3" stroke-linecap="round" style="filter: drop-shadow(0 4px 6px rgba(230,224,74,.35))"/>
</svg>
<div class="mt-1 flex justify-between text-[9px] text-white/50" aria-hidden="true"><% %w[Jan Feb Mar Apr May Jun Jul Aug].each do |m| %><span><%= m %></span><% end %></div>
</div>
</div>
<div>
<h1 class="text-5xl font-medium leading-[1.05] tracking-tight md:text-6xl xl:text-7xl">Building Your Wealth, Protecting Your Tomorrow</h1>
<p class="mt-6 max-w-md leading-relaxed text-pine/80">From the coffee you buy today to the home you'll buy in ten years, Fernwise helps every dollar you earn work a little harder for you.</p>
<a href="signup.html" class="mt-8 inline-block rounded-full bg-pine px-7 py-3 font-medium text-white transition hover:bg-pine-light">Get started now</a>
</div>
</section>
<!-- block:end hero -->
<script>
document.querySelectorAll('[data-menu-toggle]').forEach((button) => {
const menu = document.getElementById(button.getAttribute('aria-controls'));
if (!menu) return;
button.addEventListener('click', () => {
const open = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!open));
menu.classList.toggle('hidden', open);
});
});
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
const watchMotion = !reducedMotion && !navigator.webdriver && 'IntersectionObserver' in window;
document.querySelectorAll('[data-chart]').forEach((chart) => {
const line = chart.querySelector('[data-chart-line]');
chart.querySelectorAll('[data-period]').forEach((button) => {
button.addEventListener('click', () => {
chart.querySelectorAll('[data-period]').forEach((other) => other.setAttribute('aria-pressed', String(other === button)));
line.setAttribute('d', button.dataset.path);
chart.querySelector('[data-chart-value]').textContent = button.dataset.value;
chart.querySelector('[data-chart-change]').textContent = button.dataset.change;
});
});
});
document.querySelectorAll('[data-word-reveal]').forEach((root) => {
const words = [...root.querySelectorAll('[data-word]')];
if (!watchMotion) return;
const muted = words.map((word) => word.classList.contains('text-pine/35'));
const paint = () => {
const rect = root.getBoundingClientRect();
const progress = Math.min(Math.max((innerHeight * 0.85 - rect.top) / (rect.height + innerHeight * 0.3), 0), 1);
const lit = Math.round(progress * words.length);
words.forEach((word, index) => {
if (!muted[index]) return;
word.classList.toggle('text-pine', index < lit);
word.classList.toggle('text-pine/35', index >= lit);
});
};
addEventListener('scroll', paint, { passive: true });
paint();
});
(() => {
if (!watchMotion) return;
const rings = document.querySelectorAll('[data-ring]');
const draws = document.querySelectorAll('.draw');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
entry.target.querySelectorAll('[data-ring]').forEach((ring) => { ring.style.strokeDashoffset = ring.dataset.offset; });
entry.target.querySelectorAll('.draw').forEach((path) => path.classList.add('is-drawn'));
observer.unobserve(entry.target);
});
}, { threshold: 0.3 });
rings.forEach((ring) => { ring.dataset.offset = ring.getAttribute('stroke-dashoffset'); ring.style.strokeDashoffset = 100; });
document.querySelectorAll('[data-draw-group]').forEach((group) => observer.observe(group));
if (draws.length) document.documentElement.classList.add('reveal-ready');
})();
(() => {
const counters = document.querySelectorAll('[data-count-to]');
if (!counters.length || !watchMotion) return;
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const el = entry.target;
const target = Number(el.dataset.countTo);
const decimals = (el.dataset.countTo.split('.')[1] || '').length;
const start = performance.now();
const tick = (now) => {
const progress = Math.min((now - start) / 700, 1);
el.textContent = (target * progress).toFixed(decimals);
if (progress < 1) requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
observer.unobserve(el);
});
}, { threshold: 0.6 });
counters.forEach((el) => observer.observe(el));
})();
document.querySelectorAll('[data-rail]').forEach((rail) => {
const track = rail.querySelector('[data-rail-track]');
const items = [...track.querySelectorAll('[data-rail-item]')];
const step = () => (items[0]?.getBoundingClientRect().width || 300) + 20;
const mark = () => {
const center = track.getBoundingClientRect().left + track.clientWidth / 2;
let best = items[0];
items.forEach((item) => {
const rect = item.getBoundingClientRect();
if (Math.abs(rect.left + rect.width / 2 - center) < Math.abs(best.getBoundingClientRect().left + best.getBoundingClientRect().width / 2 - center)) best = item;
});
items.forEach((item) => { item.dataset.active = String(item === best); });
};
let frame;
track.addEventListener('scroll', () => { cancelAnimationFrame(frame); frame = requestAnimationFrame(mark); }, { passive: true });
rail.querySelector('[data-rail-prev]')?.addEventListener('click', () => track.scrollBy({ left: -step(), behavior: reducedMotion ? 'auto' : 'smooth' }));
rail.querySelector('[data-rail-next]')?.addEventListener('click', () => track.scrollBy({ left: step(), behavior: reducedMotion ? 'auto' : 'smooth' }));
});
document.querySelectorAll('[data-billing]').forEach((root) => {
root.addEventListener('change', (event) => {
if (event.target.name !== 'billing') return;
const yearly = event.target.value === 'yearly';
root.querySelectorAll('[data-monthly]').forEach((price) => { price.textContent = yearly ? price.dataset.yearly : price.dataset.monthly; });
root.querySelectorAll('[data-billing-note]').forEach((note) => { note.textContent = yearly ? 'per month, billed yearly' : 'per month'; });
});
});
document.querySelectorAll('[data-faq-search]').forEach((root) => {
const input = root.querySelector('[data-faq-input]');
const items = [...root.querySelectorAll('[data-faq-item]')];
const empty = root.querySelector('[data-faq-empty]');
const count = root.querySelector('[data-faq-count]');
let topic = 'all';
const apply = () => {
const query = String(input.value || '').trim().toLowerCase();
let shown = 0;
items.forEach((item) => {
const match = (topic === 'all' || item.dataset.topic === topic) && (!query || item.textContent.toLowerCase().includes(query));
item.hidden = !match;
if (match) shown += 1;
});
empty.hidden = shown > 0;
count.textContent = shown;
};
input.addEventListener('input', apply);
root.querySelectorAll('[data-faq-topic]').forEach((chip) => {
chip.addEventListener('click', () => {
topic = chip.dataset.faqTopic;
root.querySelectorAll('[data-faq-topic]').forEach((other) => { other.setAttribute('aria-pressed', String(other === chip)); other.selected = other === chip; });
apply();
});
});
});
document.querySelectorAll('[data-accordion]').forEach((accordion) => {
accordion.addEventListener('click', (event) => {
const trigger = event.target.closest('[data-accordion-trigger]');
if (!trigger) return;
const open = trigger.getAttribute('aria-expanded') !== 'true';
trigger.setAttribute('aria-expanded', String(open));
document.getElementById(trigger.getAttribute('aria-controls')).hidden = !open;
});
});
document.querySelectorAll('[data-service-tabs]').forEach((root) => {
const tabs = [...root.querySelectorAll('[role="tab"]')];
const select = (tab) => tabs.forEach((other) => {
const active = other === tab;
other.setAttribute('aria-selected', String(active));
other.tabIndex = active ? 0 : -1;
document.getElementById(other.getAttribute('aria-controls')).hidden = !active;
});
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];
next.focus();
select(next);
});
});
});
document.querySelectorAll('[data-timeline]').forEach((timeline) => {
const fill = timeline.querySelector('[data-timeline-fill]');
if (!fill) return;
const update = () => {
const rect = timeline.getBoundingClientRect();
const progress = Math.min(Math.max((innerHeight * 0.6 - rect.top) / rect.height, 0), 1);
fill.style.transform = `scaleY(${watchMotion ? progress : 1})`;
};
addEventListener('scroll', update, { passive: true });
update();
});
document.querySelectorAll('[data-wizard]').forEach((wizard) => {
const steps = [...wizard.querySelectorAll('[data-wizard-step]')];
const bar = wizard.querySelector('[data-wizard-bar]');
const label = wizard.querySelector('[data-wizard-label]');
const status = wizard.querySelector('[data-form-status]');
let current = 0;
const show = (index) => {
current = index;
steps.forEach((step, i) => { step.hidden = i !== index; });
bar.style.width = `${((index + 1) / steps.length) * 100}%`;
bar.value = (index + 1) / steps.length;
label.textContent = `Step ${index + 1} of ${steps.length}`;
wizard.querySelectorAll('[data-wizard-dot]').forEach((dot, i) => dot.classList.toggle('step-primary', i <= index));
};
const valid = () => {
const fields = [...steps[current].querySelectorAll('[required]')];
const bad = fields.find((field) => !field.checkValidity());
if (bad) { status.textContent = wizard.dataset.error; bad.focus(); return false; }
status.textContent = '';
return true;
};
wizard.addEventListener('click', (event) => {
if (event.target.closest('[data-wizard-next]') && valid()) show(Math.min(current + 1, steps.length - 1));
if (event.target.closest('[data-wizard-back]')) show(Math.max(current - 1, 0));
});
wizard.addEventListener('submit', (event) => {
event.preventDefault();
if (!valid()) return;
const plan = wizard.querySelector('[name="plan"]:checked')?.value || 'Starter';
status.textContent = `Account created on the ${plan} plan. Check your inbox to verify your email.`;
});
show(0);
});
document.querySelectorAll('[data-contact-form]').forEach((form) => {
form.addEventListener('submit', (event) => {
event.preventDefault();
const status = form.parentElement.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>
Finance & Fintech
Unlock the entire library of premium templates and blocks. Renews automatically, cancel anytime.