blazor-menus-links-navlink

Menús y enlaces en Blazor con NavLink

  • 3 min

Un NavLink es un componente de enlace que añade una clase CSS cuando su destino coincide con la URL actual.

Para navegar podemos usar una etiqueta <a> normal:

<a href="/home">Inicio</a>
Copied!

El enlace funciona, pero no indica por sí mismo si su destino es la ubicación actual.

NavLink resuelve ese estado activo sin que tengamos que comparar manualmente la URL.

NavLink es un componente que envuelve a la etiqueta <a> estándar. De hecho, cuando Blazor renderiza la página, en el HTML final verás un <a>.

Sin embargo, NavLink tiene una lógica interna que monitoriza constantemente la URL del navegador. Si la URL actual coincide con el href del enlace, NavLink añade automáticamente una clase CSS al elemento (por defecto, la clase active).

Uso básico

<nav>
    <NavLink class="nav-link" href="/">
        🏠 Inicio
    </NavLink>

    <NavLink class="nav-link" href="/contador">
        ➕ Contador
    </NavLink>
</nav>
Copied!

Gracias a esto, podemos escribir una regla CSS muy sencilla para resaltar la sección actual:

/* En tu archivo CSS */
.nav-link.active {
    background-color: rgba(255, 255, 255, 0.1);
    font-weight: bold;
    color: white;
}
Copied!

Estrategias de coincidencia con Match

Supongamos que estás en /productos/detalles.

  • Tu enlace a “Productos” (href="/productos") debería estar activo.
  • Pero, ¿tu enlace a “Inicio” (href="/") debería estar activo?

Técnicamente, /productos/detalles empieza por /. Si Blazor usara una coincidencia simple, el enlace de “Inicio” estaría siempre iluminado, porque todas las rutas empiezan por la raíz.

Para controlar esto, NavLink tiene la propiedad Match.

Esta es la opción predeterminada. El enlace se activa si la URL actual empieza por el valor del href.

Es ideal para agrupaciones o menús desplegables.

  • Enlace: <NavLink href="/admin">
  • URL actual: /admin/usuarios/crear
  • Resultado: ACTIVO (porque empieza por /admin).

Esta opción fuerza una coincidencia exacta. La URL debe ser idéntica al href.

Es la opción habitual para el enlace de inicio, porque evita que la raíz aparezca seleccionada al visitar otras rutas. En .NET 10, la comparación All ignora por defecto la query string y el fragmento si coincide el path.

<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
    Inicio
</NavLink>

<NavLink class="nav-link" href="productos">
    Productos
</NavLink>
Copied!

Regla mnemotécnica: ¿El enlace apunta a la raíz (/)? Usa Match="NavLinkMatch.All". ¿Apunta a cualquier otro sitio? Probablemente te sirva el defecto (Prefix).

Personalizar la clase activa

Por defecto, Blazor añade la clase active. Esto es genial porque frameworks como Bootstrap ya tienen estilos definidos para esa clase.

Si usas una librería CSS diferente, como Tailwind o Bulma, quizá necesites una clase distinta, por ejemplo is-selected o bg-blue-500. También puedes personalizarla.

Tenemos dos opciones:

1. Globalmente (para todo el NavLink): Usando el parámetro ActiveClass.

<NavLink class="boton-menu" ActiveClass="is-selected" href="/perfil">
    Mi Perfil
</NavLink>
Copied!

2. Heredando y creando tu propio componente: Si no quieres escribir ActiveClass="..." cincuenta veces, crea tu propio componente MyLink.razor que herede de NavLink y cambie el valor por defecto.

Ejemplo de menú lateral

Vamos a ver cómo queda un menú de navegación típico (como el que genera la plantilla de Visual Studio en NavMenu.razor).

<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">Mi App Blazor</a>
    </div>
</div>

<div class="nav-scrollable">
    <nav class="flex-column">

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="bi bi-house-door-fill"></span> Home
            </NavLink>
        </div>

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="bi bi-plus-square-fill"></span> Counter
            </NavLink>
        </div>

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="bi bi-list-nested"></span> Fetch data
            </NavLink>
        </div>

    </nav>
</div>
Copied!

Enlaces dinámicos

Por supuesto, el atributo href de un NavLink acepta expresiones de C#, igual que vimos en el One-Way Binding.

@foreach (var categoria in Categorias)
{
    <NavLink class="nav-link" href="@($"catalogo/{categoria.Slug}")">
        @categoria.Nombre
    </NavLink>
}
Copied!