Fernwise Call to action Call to action Block - Let's templates
Unlock every premium block and template with All-Access from $20 / 3 months, cancel anytime. Get All-Access
All blocks
Free Call to action

Fernwise Call to action

A call to action block extracted from the Fernwise template, available in Tailwind CSS and Bootstrap.

0 1
Fernwise Call to action preview
fernwise.html
<!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 Call to action | Tailwind CSS UI Block</title>
  <meta name="description" content="A call to action 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%"] } %>
<% [3, 5, 8].each do |n| %>
<% end %>
<% periods.each do |label, (value, path, change)| %>
<% end %>
<% %w[Jan Feb Mar Apr May Jun Jul Aug].each do |m| %>
<% end %>
<% partners = [["fa-leaf", "Acrewood"], ["fa-wallet", "Northwind Pay"], ["fa-feather", "Lumio"], ["fa-kiwi-bird", "Kitepoint"], ["fa-book", "Brightledger"], ["fa-cube", "Quanta"], ["fa-anchor", "Harbor & Co"]] %>
<% (partners + partners).each_with_index do |(icon, name), index| %>
<% end %>
<% statement = [["Fernwise", false], ["helps grow and", true], [:chart, nil], ["protect", true], ["wealth", false], ["with strategic finance", true], [:shield, nil], ["and", true], ["investment, providing data-driven", false], ["solutions for lasting security", true]] %>
<% statement.each do |text, strong| %>
<% if text == :chart %>
<% elsif text == :shield %>
<% else %>
<% text.split.each do |word| %>
<% end %>
<% end %>
<% end %>
<!-- block:start cta -->
  <section class="mx-auto max-w-7xl px-5 pb-20 pt-16 md:px-10">
    <div class="arches-dark relative grid rounded-[2rem] text-white md:grid-cols-2">
      <div class="relative z-10 p-8 md:p-14">
        <h2 class="text-4xl font-medium leading-tight md:text-5xl">Made for Growth, Grounded in Trust</h2>
        <p class="mt-5 max-w-md leading-relaxed text-white/85">So we built a platform that makes money simpler: bank-grade security, live insights and plans that adapt as your life does.</p>
        <a href="signup.html" class="mt-8 inline-block rounded-full bg-white px-7 py-3 font-medium text-pine transition hover:bg-cream">Get started now</a>
      </div>
      <div class="relative min-h-[18rem] overflow-hidden rounded-b-[2rem] md:overflow-visible md:rounded-none">
        <img src="https://images.unsplash.com/photo-1544005313-94ddf0286df2?auto=format&fit=crop&crop=focalpoint&fp-x=0.5&fp-y=0.35&w=800&h=900&q=80" alt="Young woman in a striped top smiling with confidence" class="absolute bottom-0 right-6 h-[115%] w-[85%] rounded-t-[10rem] object-cover md:h-[128%] md:w-[70%]">
      </div>
    </div>
  </section>
  <!-- block:end cta -->
<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>

From this template

Fernwise screenshot

Finance & Fintech

Fernwise

Unlimited access to all products

Unlock the entire library of premium templates and blocks. Renews automatically, cancel anytime.

$20 / 3 months or $60 / year
Get Unlimited Access