Open demo

CSS code

HTML
<header class="ht" id="ht">
  <a class="logo" href="#">Alpine Trails</a>
  <nav class="panel" id="ht-panel" aria-label="Main">
    <ul class="links"><li><a href="#" aria-current="page">Routes</a></li><li><a href="#">Guides</a></li><li><a href="#">Gear</a></li><li><a href="#">Journal</a></li></ul>
  </nav>
  <a class="cta" href="#">Book a trek</a>
  <button class="toggle" type="button" aria-expanded="false" aria-controls="ht-panel" aria-label="Menu"><i></i><i></i><i></i></button>
</header>
CSS
/* Fixed header that is transparent over the hero and turns solid and compact (.solid) once the page scrolls.
   Below 992px the links collapse behind a menu button; opening the menu also makes the header solid. */
.ht{--ht-ink:#1a1d26;--ht-muted:#4b5468;--ht-focus:#fff;
  position:fixed;top:0;left:0;right:0;z-index:20;display:flex;align-items:center;justify-content:space-between;gap:20px;
  min-height:74px;padding:0 36px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  transition:background .25s,box-shadow .25s,min-height .25s,padding .25s}
.ht,.ht *{box-sizing:border-box}
.ht ul{list-style:none;margin:0;padding:0}
.ht a{text-decoration:none}
.ht a:focus-visible,.ht button:focus-visible{outline:2px solid var(--ht-focus);outline-offset:2px}
.ht .logo{font-weight:800;font-size:1.1rem;color:#fff;letter-spacing:-.01em;border-radius:6px;transition:color .25s}
.ht .links{display:flex;gap:4px}
.ht .links a{display:block;padding:10px 14px;font-size:.9rem;font-weight:600;color:rgba(255,255,255,.9);border-radius:9px;transition:color .2s,background .2s}
.ht .links a:hover,.ht .links a[aria-current="page"]{color:#fff;background:rgba(255,255,255,.14)}
.ht .cta{font-size:.85rem;font-weight:700;padding:10px 18px;border-radius:10px;color:var(--ht-ink);background:#fff;white-space:nowrap;transition:transform .15s,background .25s,color .25s}
.ht .cta:hover{transform:translateY(-1px)}
.ht .toggle{display:none;width:44px;height:44px;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  background:none;border:1px solid rgba(255,255,255,.45);border-radius:10px;cursor:pointer;transition:border-color .25s}
.ht .toggle i{display:block;width:20px;height:2px;border-radius:2px;background:#fff;transition:transform .2s,opacity .2s,background .25s}
.ht .toggle[aria-expanded="true"] i:nth-child(1){transform:translateY(7px) rotate(45deg)}
.ht .toggle[aria-expanded="true"] i:nth-child(2){opacity:0}
.ht .toggle[aria-expanded="true"] i:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
/* solid state */
.ht.solid{--ht-focus:#0f766e;min-height:62px;background:#fff;box-shadow:0 6px 24px -12px rgba(15,20,40,.2)}
.ht.solid .logo{color:var(--ht-ink)}
.ht.solid .links a{color:var(--ht-muted)}
.ht.solid .links a:hover,.ht.solid .links a[aria-current="page"]{color:var(--ht-ink);background:#f2f4f8}
.ht.solid .cta{color:#fff;background:var(--ht-ink)}
.ht.solid .toggle{border-color:#d7dbe3}
.ht.solid .toggle i{background:var(--ht-ink)}
@media (max-width:991.98px){
  .ht{flex-wrap:wrap;gap:0 12px;padding:15px 16px}
  .ht.solid{padding:9px 16px}
  .ht .toggle{display:flex}
  .ht .cta{margin-left:auto}
  .ht .panel{display:none;order:9;flex-basis:100%;padding:10px 0 6px}
  .ht .panel[data-open]{display:block}
  .ht .links{flex-direction:column;gap:2px}
}
@media (prefers-reduced-motion:reduce){.ht,.ht *{transition:none!important}}
JavaScript
/* .solid past 40px of scroll or while the menu is open. The menu button toggles aria-expanded and data-open
   on the nav; Esc closes it and returns focus to the button. */
(() => {
  const hd = document.getElementById('ht'); if (!hd) return;
  const toggle = hd.querySelector('.toggle'), panel = document.getElementById(toggle.getAttribute('aria-controls'));
  const isOpen = () => toggle.getAttribute('aria-expanded') === 'true';
  const paint = () => hd.classList.toggle('solid', scrollY > 40 || isOpen());
  const set = open => { toggle.setAttribute('aria-expanded', open); panel.toggleAttribute('data-open', open); paint(); };
  addEventListener('scroll', paint, { passive: true }); paint();
  toggle.addEventListener('click', () => set(!isOpen()));
  document.addEventListener('keydown', e => { if (e.key === 'Escape' && isOpen()) { set(false); toggle.focus(); } });
})();

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS, Bootstrap 5.3.8 JS bundle

HTML
<header class="ht" id="ht">
  <nav class="navbar navbar-expand-lg fixed-top" aria-label="Main">
    <div class="container-fluid">
      <a class="navbar-brand" href="#">Alpine Trails</a>
      <div class="d-flex align-items-center gap-3 ms-auto ms-lg-0 order-lg-last">
        <a class="btn cta" href="#">Book a trek</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#ht-panel" aria-controls="ht-panel" aria-expanded="false" aria-label="Menu"><i></i><i></i><i></i></button>
      </div>
      <div class="collapse navbar-collapse" id="ht-panel">
        <ul class="navbar-nav mx-auto">
          <li class="nav-item"><a class="nav-link active" href="#" aria-current="page">Routes</a></li>
          <li class="nav-item"><a class="nav-link" href="#">Guides</a></li>
          <li class="nav-item"><a class="nav-link" href="#">Gear</a></li>
          <li class="nav-item"><a class="nav-link" href="#">Journal</a></li>
        </ul>
      </div>
    </div>
  </nav>
</header>
CSS
/* Bootstrap .navbar.fixed-top, transparent over the hero; .solid on the header swaps the navbar variables. */
.ht{--ht-ink:#1a1d26;--ht-muted:#4b5468}
.ht .navbar{--bs-navbar-padding-y:0;--bs-navbar-padding-x:36px;--bs-navbar-color:rgba(255,255,255,.9);--bs-navbar-hover-color:#fff;
  --bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-brand-padding-y:0;--bs-navbar-brand-margin-end:0;
  --bs-navbar-nav-link-padding-x:14px;--bs-nav-link-font-size:.9rem;
  --ht-soft:rgba(255,255,255,.14);--ht-focus:#fff;
  min-height:74px;transition:background .25s,box-shadow .25s,min-height .25s,padding .25s}
.ht .container-fluid{padding:0;gap:20px}
.ht .navbar-brand{font-weight:800;font-size:1.1rem;letter-spacing:-.01em;border-radius:6px}
.ht .navbar-nav{--bs-nav-link-padding-y:10px;--bs-nav-link-font-weight:600;gap:4px}
.ht .nav-link{border-radius:9px;transition:color .2s,background .2s}
.ht .nav-link:hover,.ht .nav-link.active{background:var(--ht-soft)}
.ht .cta{--bs-btn-font-size:.85rem;--bs-btn-font-weight:700;--bs-btn-padding-x:18px;--bs-btn-padding-y:10px;--bs-btn-border-radius:10px;--bs-btn-border-width:0;
  --bs-btn-color:var(--ht-ink);--bs-btn-bg:#fff;--bs-btn-hover-color:var(--ht-ink);--bs-btn-hover-bg:#fff;--bs-btn-active-color:var(--ht-ink);--bs-btn-active-bg:#fff;
  white-space:nowrap;transition:transform .15s,background .25s,color .25s}
.ht .cta:hover{transform:translateY(-1px)}
.ht a:focus-visible,.ht button:focus-visible{outline:2px solid var(--ht-focus);outline-offset:2px;box-shadow:none}
.ht .navbar-toggler{width:44px;height:44px;padding:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  border:1px solid rgba(255,255,255,.45);border-radius:10px;transition:border-color .25s}
.ht .navbar-toggler i{display:block;width:20px;height:2px;border-radius:2px;background:#fff;transition:transform .2s,opacity .2s,background .25s}
.ht .navbar-toggler[aria-expanded="true"] i:nth-child(1){transform:translateY(7px) rotate(45deg)}
.ht .navbar-toggler[aria-expanded="true"] i:nth-child(2){opacity:0}
.ht .navbar-toggler[aria-expanded="true"] i:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
/* solid state */
.ht.solid .navbar{--bs-navbar-color:var(--ht-muted);--bs-navbar-hover-color:var(--ht-ink);--bs-navbar-active-color:var(--ht-ink);
  --bs-navbar-brand-color:var(--ht-ink);--bs-navbar-brand-hover-color:var(--ht-ink);--ht-soft:#f2f4f8;--ht-focus:#0f766e;
  min-height:62px;background:#fff;box-shadow:0 6px 24px -12px rgba(15,20,40,.2)}
.ht.solid .cta{--bs-btn-color:#fff;--bs-btn-bg:var(--ht-ink);--bs-btn-hover-color:#fff;--bs-btn-hover-bg:var(--ht-ink);--bs-btn-active-color:#fff;--bs-btn-active-bg:var(--ht-ink)}
.ht.solid .navbar-toggler{border-color:#d7dbe3}
.ht.solid .navbar-toggler i{background:var(--ht-ink)}
@media (min-width:992px){.ht .navbar-toggler{display:none}}
@media (max-width:991.98px){
  .ht .navbar{--bs-navbar-padding-x:16px;padding-top:15px;padding-bottom:15px}
  .ht.solid .navbar{padding-top:9px;padding-bottom:9px}
  .ht .container-fluid{gap:0}
  .ht .navbar-nav{gap:2px;padding:10px 0 6px}
  .ht .navbar-nav .nav-link{padding-left:14px;padding-right:14px}
}
@media (prefers-reduced-motion:reduce){.ht *{transition:none!important}}
JavaScript
/* .solid past 40px of scroll or while the collapsed menu is open; Esc closes the menu and returns focus. */
(() => {
  const hd = document.getElementById('ht'); if (!hd) return;
  const panel = hd.querySelector('.navbar-collapse'), toggler = hd.querySelector('.navbar-toggler');
  let open = false;
  const paint = () => hd.classList.toggle('solid', scrollY > 40 || open);
  addEventListener('scroll', paint, { passive: true }); paint();
  panel.addEventListener('show.bs.collapse', () => { open = true; paint(); });
  panel.addEventListener('hidden.bs.collapse', () => { open = false; paint(); });
  document.addEventListener('keydown', e => {
    if (e.key !== 'Escape' || !panel.classList.contains('show')) return;
    bootstrap.Collapse.getOrCreateInstance(panel).hide(); toggler.focus();
  });
})();

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<header class="group fixed inset-x-0 top-0 z-20 flex min-h-[74px] items-center justify-between gap-5 px-9 transition-[background-color,box-shadow,min-height,padding] duration-[250ms] motion-reduce:transition-none max-lg:flex-wrap max-lg:gap-x-3 max-lg:gap-y-0 max-lg:px-4 max-lg:py-[15px] [&.solid]:min-h-[62px] [&.solid]:bg-white [&.solid]:shadow-[0_6px_24px_-12px_rgba(15,20,40,.2)] max-lg:[&.solid]:py-[9px]" id="ht">
  <a class="rounded-md text-[1.1rem] font-extrabold tracking-[-.01em] text-white transition-colors duration-[250ms] group-[.solid]:text-ht-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white group-[.solid]:focus-visible:outline-ht-accent motion-reduce:transition-none" href="#">Alpine Trails</a>
  <nav class="hidden data-open:block lg:block max-lg:order-9 max-lg:basis-full max-lg:pt-2.5 max-lg:pb-1.5" id="ht-panel" aria-label="Main">
    <ul class="flex gap-1 max-lg:flex-col max-lg:gap-0.5">
      <li><a class="block rounded-[9px] bg-white/14 px-3.5 py-2.5 text-[.9rem] font-semibold text-white group-[.solid]:bg-[#f2f4f8] group-[.solid]:text-ht-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white group-[.solid]:focus-visible:outline-ht-accent" href="#" aria-current="page">Routes</a></li>
      <li><a class="block rounded-[9px] px-3.5 py-2.5 text-[.9rem] font-semibold text-white/90 transition-colors duration-200 hover:bg-white/14 hover:text-white group-[.solid]:text-ht-muted group-[.solid]:hover:bg-[#f2f4f8] group-[.solid]:hover:text-ht-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white group-[.solid]:focus-visible:outline-ht-accent motion-reduce:transition-none" href="#">Guides</a></li>
      <li><a class="block rounded-[9px] px-3.5 py-2.5 text-[.9rem] font-semibold text-white/90 transition-colors duration-200 hover:bg-white/14 hover:text-white group-[.solid]:text-ht-muted group-[.solid]:hover:bg-[#f2f4f8] group-[.solid]:hover:text-ht-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white group-[.solid]:focus-visible:outline-ht-accent motion-reduce:transition-none" href="#">Gear</a></li>
      <li><a class="block rounded-[9px] px-3.5 py-2.5 text-[.9rem] font-semibold text-white/90 transition-colors duration-200 hover:bg-white/14 hover:text-white group-[.solid]:text-ht-muted group-[.solid]:hover:bg-[#f2f4f8] group-[.solid]:hover:text-ht-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white group-[.solid]:focus-visible:outline-ht-accent motion-reduce:transition-none" href="#">Journal</a></li>
    </ul>
  </nav>
  <a class="rounded-[10px] bg-white px-[18px] py-2.5 text-[.85rem] font-bold whitespace-nowrap text-ht-ink transition-[transform,background-color,color] duration-[250ms] hover:-translate-y-px group-[.solid]:bg-ht-ink group-[.solid]:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white group-[.solid]:focus-visible:outline-ht-accent motion-reduce:transition-none max-lg:ml-auto" href="#">Book a trek</a>
  <button class="toggle group/t flex size-11 cursor-pointer flex-col items-center justify-center gap-[5px] rounded-[10px] border border-white/45 transition-colors duration-[250ms] group-[.solid]:border-[#d7dbe3] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white group-[.solid]:focus-visible:outline-ht-accent motion-reduce:transition-none lg:hidden" type="button" aria-expanded="false" aria-controls="ht-panel" aria-label="Menu">
    <i class="block h-0.5 w-5 rounded-sm bg-white transition-transform duration-200 group-[.solid]:bg-ht-ink group-aria-expanded/t:translate-y-[7px] group-aria-expanded/t:rotate-45 motion-reduce:transition-none"></i>
    <i class="block h-0.5 w-5 rounded-sm bg-white transition-opacity duration-200 group-[.solid]:bg-ht-ink group-aria-expanded/t:opacity-0 motion-reduce:transition-none"></i>
    <i class="block h-0.5 w-5 rounded-sm bg-white transition-transform duration-200 group-[.solid]:bg-ht-ink group-aria-expanded/t:-translate-y-[7px] group-aria-expanded/t:-rotate-45 motion-reduce:transition-none"></i>
  </button>
</header>
CSS
@theme {
  --breakpoint-lg: 62rem; /* 992px, the same collapse point as Bootstrap's navbar-expand-lg */
  --color-ht-ink: #1a1d26;
  --color-ht-muted: #4b5468;
  --color-ht-accent: #0f766e;
}
JavaScript
/* .solid past 40px of scroll or while the menu is open. The menu button toggles aria-expanded and data-open
   on the nav; Esc closes it and returns focus to the button. */
(() => {
  const hd = document.getElementById('ht'); if (!hd) return;
  const toggle = hd.querySelector('.toggle'), panel = document.getElementById(toggle.getAttribute('aria-controls'));
  const isOpen = () => toggle.getAttribute('aria-expanded') === 'true';
  const paint = () => hd.classList.toggle('solid', scrollY > 40 || isOpen());
  const set = open => { toggle.setAttribute('aria-expanded', open); panel.toggleAttribute('data-open', open); paint(); };
  addEventListener('scroll', paint, { passive: true }); paint();
  toggle.addEventListener('click', () => set(!isOpen()));
  document.addEventListener('keydown', e => { if (e.key === 'Escape' && isOpen()) { set(false); toggle.focus(); } });
})();

About this set

A fixed header that sits transparent over a full-height hero, with white text on the dark teal gradient, and turns into a compact white bar with dark text and a soft shadow as soon as the page scrolls more than 40px. The logo, the four links (Routes, Guides, Gear, Journal) and the Book a trek button all swap colours, and the bar shrinks from 74px to 62px, with each change animated by CSS transitions. A short scroll listener toggles a .solid class, so the styling for both states lives in the stylesheet. On screens narrower than 992px the links move into a panel behind a menu button; opening it also makes the header solid so the list stays readable over the photo or gradient underneath. Use it for travel, hospitality, agency and product pages that open with a large hero image. Without JavaScript the header stays transparent, so keep the script if the page scrolls onto a light background. The Bootstrap version is a .navbar.fixed-top with the Collapse plugin, and the Tailwind version styles the solid state with group-[.solid] variants.

What’s included

  • Transparent over the hero, solid and shorter after 40px of scroll
  • Colours, height and shadow change with CSS transitions
  • Opening the phone menu turns the header solid
  • Book a trek button stays visible at every width
  • Scroll listener is passive and only toggles one class

Accessibility

The links are in a nav labelled Main with aria-current="page" on Routes. The menu button carries aria-expanded and aria-controls, and Esc closes the menu and returns focus to it. Focus outlines are white over the hero and teal once the header is solid, and all transitions switch off under prefers-reduced-motion.

Customise it

Edit --ht-ink and --ht-muted and the .solid rules for the scrolled colours; the 40 in the script is the scroll distance. Bootstrap maps both states onto --bs-navbar-* variables; in Tailwind change the --color-ht-* theme colours and the group-[.solid] utilities.