← Back

Active class astro

Highlighting the current header link in Astro

Highlighting the current header link in Astro

Within this post, I aim to guide you through the steps to effectively highlight the navigation link associated with the current page in Astro. By the end of this article, you’ll have a clear understanding of how to enhance user navigation by ensuring the active page’s link stands out prominently.

Various methods exist, and I will delve into three of them. It’s essential to note that the code examples provided are crafted specifically for Astro Components, with a file extension of .astro.

1. The JavaScript Way

The following code shows you, how to incorporate plain JavaScript within a script tag. This instructs Astro to deliver this code block directly to the browser, allowing it to function in a conventional manner.

// src/components/Header.astro

<nav>
  <a class="active" href="/">Home</a>
  <a href="/posts">Blog</a>
  <a href="/works">Works</a>
  <a href="/about">About</a>
</nav>

<script>
  const navAnchors = document.querySelectorAll('nav a')

  navAnchors.forEach((anchor) => {
    // remove active class from all anchors
    anchor.classList.remove('active')

    // remove the first `/` in pathname using slice method
    const currentPath = window.location.pathname.slice('1')

    // we split the href by `/` and get the last item in the array
    const hrefArray = link.href.split('/')
    const thisPath = hrefArray[hrefArray.length - 1]

    // add active class if the currentPath is the same as thisPath
    if (currentPath === thisPath) {
      anchor.classList.add('active')
    }
  })
</script>

2. The Astro Way

We take advantage of Astro’s Runtime API and get the pathname in Astro components’ component script

// src/components/Header.astro

---
const pathname = new URL(Astro.request.url).pathname;
const currentPath = pathname.slice(1); // remove the first "/"
---

<nav>
  <a class={currentPath === "" ? "active" : ""} href="/">Home</a>
  <a class={currentPath === "portfolio" ? "active" : ""} href="/posts">Blog</a>
  <a class={currentPath === "works" ? "active" : ""} href="/works">Works</a>
  <a class={currentPath === "about" ? "active" : ""} href="/about">About</a>
</nav>

3. Combining components

// src/components/HeaderLink.astro

---
import type { HTMLAttributes } from 'astro/types'
type Props = HTMLAttributes<'a'>
const { href, class: className, ...props } = Astro.props

const { pathname } = Astro.url
const isActive = href === pathname || href === pathname.replace(/\/$/, '') //
grep replace the first '/'
---

<a href={href} class:list={[className, { active: isActive }]} {...props}>
  <slot /> <!-- This is where the content of the component is rendered -->
</a>
<style>
  a {
    display: inline-block;
    text-decoration: none;
  }

  a.active {
    font-weight: bolder;
    text-decoration: underline;
  }
</style>

then

// src/components/HeaderLink.astro --- import HeaderLink from
'./HeaderLink.astro' // the above component ---

<div class="internal-links">
  <HeaderLink href="/">Home</HeaderLink>
  <HeaderLink href="/posts">Blog</HeaderLink>
  <HeaderLink href="/works">Works</HeaderLink>
  <HeaderLink href="/about">About</HeaderLink>
</div>
the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never the end is never