Fernwise Navbar Navbar 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 Navbar

Fernwise Navbar

A navbar block extracted from the Fernwise template, available in Tailwind CSS and Bootstrap.

0 2
Fernwise Navbar 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 Navbar | Tailwind CSS UI Block</title>
  <meta name="description" content="A navbar 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" } %>
<!-- block:start navbar -->
  <header class="relative z-40">
    <nav class="mx-auto flex max-w-7xl items-center justify-between gap-6 px-5 py-6 md:px-10" aria-label="Main">
      <a href="index.html" class="leading-none" aria-label="Fernwise Finance home">
        <span class="block font-brand text-[1.7rem] font-extrabold tracking-tight">Fernwise</span>
        <span class="block font-brand text-[10px] font-bold uppercase tracking-[0.35em]">Finance</span>
      </a>
      <ul class="hidden items-center gap-10 text-[15px] font-medium lg:flex">
        <% nav.each do |slug, label| %>
          <% active = active_page == slug %>
          <li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="border-b-2 pb-1 transition <%= active ? 'border-pine' : 'border-transparent text-pine/70 hover:text-pine' %>"><%= label %></a></li>
        <% end %>
      </ul>
      <div class="flex items-center gap-2">
        <a href="signup.html" <%= 'aria-current="page"'.html_safe if active_page == "signup" %> class="hidden rounded-full bg-pine px-6 py-2.5 text-sm font-medium text-white transition hover:bg-pine-light sm:inline-block">Sign up</a>
        <button type="button" data-menu-toggle aria-controls="mobile-menu" aria-expanded="false" aria-label="Open menu" class="grid h-11 w-11 place-items-center rounded-full bg-pine text-white lg:hidden"><i class="fa-solid fa-bars" aria-hidden="true"></i></button>
      </div>
    </nav>
    <div id="mobile-menu" class="hidden px-5 pb-4 lg:hidden">
      <ul class="grid gap-1 rounded-3xl bg-white p-3 font-medium shadow-lg">
        <% nav.merge("contact" => "Contact", "signup" => "Sign up").each do |slug, label| %>
          <% active = active_page == slug %>
          <li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="block rounded-2xl px-4 py-3 <%= active ? 'bg-pine text-white' : 'hover:bg-stone' %>"><%= label %></a></li>
        <% end %>
      </ul>
    </div>
  </header>
  <!-- block:end navbar -->
<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