Free
Navbar
Brassmoor Navbar
A navbar block extracted from the Brassmoor template, available in Tailwind CSS and Bootstrap.
0
1
A navbar block extracted from the Brassmoor 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>Brassmoor Navbar | Tailwind CSS UI Block</title>
<meta name="description" content="A navbar block extracted from the Brassmoor template, available in Tailwind CSS and Bootstrap.">
<meta name="keywords" content="Brassmoor, Tailwind CSS template, HTML website template, business template, barbershop website, barber template, grooming salon, haircut prices, booking form, men's hair studio">
<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="Brassmoor | Tailwind CSS Business Template">
<meta property="og:description" content="A dark Tailwind CSS barbershop template with a hero slider, a price list with opening hours, a team slider, a gallery and an appointment form.">
<meta property="og:image" content="">
<meta property="og:image:alt" content="Brassmoor template preview">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="">
<meta name="twitter:title" content="Brassmoor | Tailwind CSS Business Template">
<meta name="twitter:description" content="A dark Tailwind CSS barbershop template with a hero slider, a price list with opening hours, a team slider, a gallery and an appointment form.">
<meta name="twitter:image" content="">
<meta name="twitter:image:alt" content="Brassmoor 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=Teko:wght@400;500;600&family=Hind:wght@400;500;600&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: { coal: { DEFAULT: '#121416', card: '#1e2023', soft: '#26292d', line: '#34383d' }, ember: { DEFAULT: '#e85a3d', dark: '#c9452b' }, gold: '#f2a541' },
fontFamily: { sans: ['Hind', 'sans-serif'], display: ['Teko', '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; }
.mark { background: linear-gradient(transparent 58%, #e85a3d 58%, #e85a3d 92%, transparent 92%); padding: 0 .1em; }
.slide { transition: opacity .6s 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; }
.slide { transition: none; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
</style>
</head>
<body class="bg-coal font-sans text-white antialiased">
<% active_page = "index" %>
<% nav = { "index" => "Home", "about" => "About Us", "services" => "Services", "gallery" => "Gallery", "contact" => "Contact" } %>
<!-- block:start navbar -->
<header class="relative z-40">
<div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between gap-3 px-5 pt-4 text-xs text-white/70 md:px-10">
<p class="flex flex-wrap gap-6"><span><i class="fa-solid fa-clock mr-2 text-ember" aria-hidden="true"></i>09:00 – 19:00</span><span class="hidden sm:inline"><i class="fa-solid fa-calendar-days mr-2 text-ember" aria-hidden="true"></i>Tuesday – Saturday</span></p>
<a href="tel:+16175550142" class="hover:text-ember"><i class="fa-solid fa-phone mr-2 text-ember" aria-hidden="true"></i>(617) 555-0142</a>
</div>
<nav class="mx-auto flex max-w-7xl items-center justify-between gap-4 px-5 py-5 md:px-10" aria-label="Main">
<a href="index.html" class="font-display text-3xl font-semibold uppercase leading-none tracking-wide">Brass<span class="text-ember">moor</span>.</a>
<ul class="hidden items-center gap-8 text-sm md:flex">
<% nav.each do |slug, label| %>
<% active = active_page == slug %>
<li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="transition <%= active ? 'font-semibold text-white' : 'text-white/70 hover:text-ember' %>"><%= label %></a></li>
<% end %>
</ul>
<button type="button" data-menu-toggle aria-controls="mobile-menu" aria-expanded="false" class="grid h-10 w-10 place-items-center border border-white/30 md:hidden" aria-label="Open menu"><i class="fa-solid fa-bars" aria-hidden="true"></i></button>
</nav>
<div id="mobile-menu" class="hidden border-y border-coal-line bg-coal-card px-5 py-4 md:hidden">
<ul class="grid gap-1 font-display text-3xl">
<% nav.each do |slug, label| %>
<% active = active_page == slug %>
<li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="block py-1 <%= active ? 'text-ember' : 'hover:text-ember' %>"><%= label %></a></li>
<% end %>
</ul>
</div>
</header>
<!-- block:end navbar -->
<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-hero]').forEach((root) => {
const slides = [...root.querySelectorAll('[data-slide]')];
const dots = [...root.querySelectorAll('[data-slide-dot]')];
let current = 0;
const show = (index) => {
current = (index + slides.length) % slides.length;
slides.forEach((slide, i) => {
const on = i === current;
slide.classList.toggle('opacity-100', on); slide.classList.toggle('opacity-0', !on); slide.classList.toggle('pointer-events-none', !on);
slide.setAttribute('aria-hidden', String(!on));
slide.querySelectorAll('a').forEach((link) => { link.tabIndex = on ? 0 : -1; });
});
dots.forEach((dot, i) => dot.setAttribute('aria-pressed', String(i === current)));
root.querySelector('[data-slide-index]').textContent = String(current + 1).padStart(2, '0');
};
dots.forEach((dot, i) => dot.addEventListener('click', () => show(i)));
root.addEventListener('keydown', (event) => { if (event.key === 'ArrowDown') show(current + 1); if (event.key === 'ArrowUp') show(current - 1); });
});
document.querySelectorAll('[data-team]').forEach((root) => {
const members = [...root.querySelectorAll('[data-member]')];
const photos = [...root.querySelectorAll('[data-member-photo]')];
let current = 0;
const show = (index) => {
current = (index + members.length) % members.length;
members.forEach((member, i) => { member.hidden = i !== current; });
photos.forEach((photo, i) => { photo.classList.toggle('opacity-100', i === current); photo.classList.toggle('opacity-0', i !== current); });
};
root.querySelector('[data-member-prev]').addEventListener('click', () => show(current - 1));
root.querySelector('[data-member-next]').addEventListener('click', () => show(current + 1));
});
document.querySelectorAll('[data-carousel]').forEach((root) => {
const slides = [...root.querySelectorAll('[data-slide]')];
const dots = [...root.querySelectorAll('[data-carousel-dot]')];
let current = 0;
const show = (index) => {
current = (index + slides.length) % slides.length;
slides.forEach((slide, i) => { slide.hidden = i !== current; });
dots.forEach((dot, i) => dot.setAttribute('aria-current', String(i === current)));
};
root.querySelector('[data-carousel-prev]').addEventListener('click', () => show(current - 1));
root.querySelector('[data-carousel-next]').addEventListener('click', () => show(current + 1));
dots.forEach((dot, i) => dot.addEventListener('click', () => show(i)));
});
document.querySelectorAll('[data-lightbox-root]').forEach((root) => {
const dialog = root.querySelector('[data-lightbox]');
root.querySelectorAll('[data-lightbox-open]').forEach((button) => button.addEventListener('click', () => {
const image = dialog.querySelector('[data-lightbox-image]');
image.src = `https://images.unsplash.com/photo-${button.dataset.lightboxOpen}?auto=format&fit=crop&w=1400&h=900&q=80`;
image.alt = button.dataset.alt;
dialog.querySelector('[data-lightbox-caption]').textContent = button.dataset.alt;
dialog.showModal();
}));
dialog.querySelector('[data-lightbox-close]').addEventListener('click', () => dialog.close());
dialog.addEventListener('click', (event) => { if (event.target === dialog) dialog.close(); });
});
document.querySelectorAll('[data-booking]').forEach((form) => {
const status = form.parentElement.querySelector('[data-form-status]');
const date = form.querySelector('[name="date"]');
if (date) date.min = new Date().toISOString().slice(0, 10);
form.addEventListener('submit', (event) => {
event.preventDefault();
const missing = [...form.querySelectorAll('[required]')].find((input) => !input.checkValidity());
if (missing) { status.textContent = 'Please add your name, phone and a date from today onwards.'; missing.focus(); return; }
status.textContent = `Thanks, ${form.elements.name.value}! Your chair is held for ${new Date(date.value).toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })}.`;
form.reset();
});
});
document.querySelectorAll('[data-subscribe]').forEach((form) => {
const status = form.parentElement.querySelector('[data-subscribe-status]');
form.addEventListener('submit', (event) => {
event.preventDefault();
if (!form.elements.email.checkValidity()) { status.textContent = 'Please enter a valid email.'; return; }
status.textContent = 'Subscribed — see you next month.';
form.reset();
});
});
document.querySelectorAll('[data-count]').forEach((el) => {
if (!watchMotion) return;
const target = Number(el.dataset.count);
const pad = el.dataset.count.length;
const observer = new IntersectionObserver(([entry]) => {
if (!entry.isIntersecting) return;
observer.disconnect();
const start = performance.now();
const tick = (now) => { const t = Math.min(1, (now - start) / 700); el.textContent = String(Math.round(target * t)).padStart(pad > 2 ? 0 : pad, '0'); if (t < 1) requestAnimationFrame(tick); };
requestAnimationFrame(tick);
});
observer.observe(el);
});
if (watchMotion) {
document.documentElement.classList.add('reveal-ready');
const observer = new IntersectionObserver((entries) => entries.forEach((entry) => {
if (entry.isIntersecting) { entry.target.classList.add('is-visible'); observer.unobserve(entry.target); }
}), { threshold: 0.15 });
document.querySelectorAll('[data-reveal]').forEach((el) => observer.observe(el));
}
</script>
</body>
</html>
Business
Unlock the entire library of premium templates and blocks. Renews automatically, cancel anytime.