Jekyll: resalta automáticamente la pestaña actual en la barra de menú


81

Estoy usando github para alojar un sitio estático y Jekyll para generarlo.

Tengo una barra de menú (como <ul>) y me gustaría que a la <li>correspondiente a la página actual se le asigne una clase diferente para resaltar CSS.

Entonces, algo como un pseudocódigo:

<li class={(hrefpage==currentpage)?"highlight":"nothighlight"} ...>

O tal vez incluso generar el todo <ul>en Jekyll.

¿Cómo se puede hacer esto con cambios mínimos fuera de la infracción <ul>?


Respuestas:


116

Sí, usted puede hacer esto.
Para lograrlo aprovecharemos que la página actual siempre está representada por la variable líquida: pageen la plantilla, y además que cada publicación / página tiene un identificador único en su page.urlatributo.

Esto significa que solo tenemos que usar un bucle para construir nuestra página de navegación y, al hacerlo, podemos verificar page.urlcada miembro del bucle. Si encuentra una coincidencia, sabe resaltar ese elemento. Aquí vamos:

  {% for node in site.pages %}
    {% if page.url == node.url %}
      <li class="active"><a href="{{node.url}}" class="active">{{node.title}}</a></li>
    {% else %}
      <li><a href="{{node.url}}">{{node.title}}</a></li>
    {% endif %}
  {% endfor %}

Esto funciona como se esperaba. Sin embargo, probablemente no quieras que todas tus páginas estén en la barra de navegación. Para emular la "agrupación" de páginas, puede hacer algo como esto:

## Put the following code in a file in the _includes folder at: ./_includes/pages_list

{% for node in pages_list %}
  {% if group == null or group == node.group %}
    {% if page.url == node.url %}
      <li class="active"><a href="{{node.url}}" class="active">{{node.title}}</a></li>
    {% else %}
      <li><a href="{{node.url}}">{{node.title}}</a></li>
    {% endif %}
  {% endif %}
{% endfor %}
{% assign pages_list = nil %}
{% assign group = nil %}

Ahora las páginas se pueden "agrupar". Para asignar un grupo a una página, debe especificarlo en las páginas YAML Front Matter:

---
title: blah
categories: blah
group: "navigation"
---    

¡Finalmente puedes usar tu nuevo código! Donde sea que necesite que su navegación vaya en su plantilla, simplemente "llame" a su archivo de inclusión y páselo algunas páginas y el grupo que desea mostrar:

<ul>
  {% assign pages_list = site.pages %}
  {% assign group = 'navigation' %}
  {% include pages_list %}
</ul>

Ejemplos

Esta funcionalidad es parte del marco Jekyll-Bootstrap . Puede ver la documentación exacta del código que se describe aquí: http://jekyllbootstrap.com/api/bootstrap-api.html#jbpages_list

Finalmente puedes verlo en acción dentro del propio sitio web. Solo mire la navegación de la derecha y verá que la página actual está resaltada en verde: Ejemplo de enlace de navegación resaltado


1
Gran pregunta, gran respuesta, gracias. También fue sencillo modificar esto para una lista de pestañas seleccionada manualmente. tomó un momento para darse cuenta de que page.url incluye la '/', por ejemplo. "/index.html", no "index.html"
cboettig

Este enfoque resulta en un error de Jekyll para mí. jekyll 2.4.0 | Error: The included file '/Users/joelglovier/project/jekyllsite/_includes/pages_list' should exist and should not be a symlink
Joel Glovier

Demasiado complejo para algo que debería estar integrado en Jekyll.
Cameronroe

@cameronjroe intente agregar la .htmlextensión a pages_list e incluirla en su lugar
HotelCalifornia

48

Creo que para el requisito de navegación más simple, las soluciones enumeradas son demasiado complejas. Aquí hay una solución que no implica nada frontal, javascript, bucles, etc.

Dado que tenemos acceso a la URL de la página, podemos normalizar y dividir la URL y probar contra los segmentos, así:

{% assign current = page.url | downcase | split: '/' %}

<nav>
  <ul>
    <li><a href='/about' {% if current[1] == 'about' %}class='current'{% endif %}>about</a></li>
    <li><a href='/blog' {% if current[1] == 'blog' %}class='current'{% endif %}>blog</a></li>
    <li><a href='/contact' {% if current[1] == 'contact' %}class='current'{% endif %}>contact</a></li>
  </ul>
</nav>

Por supuesto, esto solo es útil si los segmentos estáticos proporcionan los medios para delinear la navegación. Algo más complicado, y tendrás que usar la parte delantera como demostró @RobertKenny.


Esto es lo que estaba buscando, pero ¿no debería ser así classs="active"?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

@CiroSantilli 六四 事件 法轮功 si su CSS tiene el estilo .active, entonces sí. En la respuesta anterior, el autor dice que la clase para llamar en su hoja de estilo es .current. No es gran cosa.
Brian Zelip

3
@BrianZ es oficial: demasiado Bootstrap derrite tu cerebro :)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

para la página de inicio tuve que configurar {% if current [1] == null%}
GorvGoyl

17

Similar a la solución de @ ben-foster pero sin usar jQuery

Necesitaba algo simple, esto es lo que hice.

En mi asunto principal agregué una variable llamada active

p.ej

---
layout: generic
title:  About
active: about
---

Tengo una navegación incluida con la siguiente sección

    <ul class="nav navbar-nav">
        {% if page.active == "home" %}
            <li class="active"><a href="#">Home</a></li>
        {% else %}
            <li><a href="https://stackoverflow.com/">Home</a></li>
        {% endif %}
        {% if page.active == "blog" %}
            <li class="active"><a href="#">Blog</a></li>
        {% else %}
            <li><a href="../blog/">Blog</a></li>
        {% endif %}
        {% if page.active == "about" %}
            <li class="active"><a href="#">About</a></li>
        {% else %}
            <li><a href="../about">About</a></li>
        {% endif %}
    </ul>

Esto funciona para mí ya que la cantidad de enlaces en la navegación es muy limitada.


Gracias @SurenderLohia Me gusta mantener las cosas lo más sencillas posible.
RobertKenny

16

Aquí está mi solución, que creo que es la mejor manera de resaltar la página actual:

Defina una lista de navegación en su _config.yml como esta:

navigation:
  - title: blog
    url: /blog/
  - title: about
    url: /about/
  - title: projects
    url: /projects/

Luego, en su archivo _includes / header.html , debe recorrer la lista para verificar si la página actual ( page.url ) se parece a algún elemento de la lista de navegación, si es así, simplemente configure la clase activa y agréguela a la <a>etiqueta:

<nav>
  {% for item in site.navigation %}
      {% assign class = nil %}
      {% if page.url contains item.url %}
          {% assign class = 'active' %}
      {% endif %}
      <a href="{{ item.url }}" class="{{ class }}">
          {{ item.title }}
      </a>
  {% endfor %}
</nav>

Y debido a que está utilizando el operador contiene en lugar del operador igual = , no tiene que escribir código adicional para que funcione con URL como '/ blog / post-name /' o 'projects / project-name / ' . Funciona muy bien.

PD: No olvide establecer la variable de enlace permanente en sus páginas.


Esta es mi solución favorita, ya que significa que puedo elegir el orden de las páginas.

Me gusta esta solución, pero no funciona si tiene un enlace de navegación con URL /porque todas las URL de página contienen la barra inclinada. Las siguientes obras: {% for link in site.navigation %} {% assign class = nil %} {% if page.url == link.url %} {% assign class = 'active' %} {% elsif page.url != '/' and page.url contains link.url %} {% assign class = 'active parent' %} {% endif %} <a href="{{link.url}}" class="{{class}}">{{link.title}}</a> {% endfor %}
JamesWilson

6

Usé un poco de JavaScript para lograr esto. Tengo la siguiente estructura en el menú:

<ul id="navlist">
  <li><a id="index" href="index.html">Index</a></li>
  <li><a href="about.html">About</a></li>
  <li><a href="projects.html">Projects</a></li>
  <li><a href="videos.html">Videos</a></li>
</ul>

Este fragmento de JavaScript destaca la página correspondiente actual:

$(document).ready(function() {
    var pathname = window.location.pathname;

    $("#navlist a").each(function(index) {
        if (pathname.toUpperCase().indexOf($(this).text().toUpperCase()) != -1)
            $(this).addClass("current");
    });

    if ($("a.current").length == 0)
        $("a#index").addClass("current");
});

Personalmente, creo que esto es más limpio que el método anterior. El método anterior comienza a ponerse feo si desea ordenar las páginas en su navegador o si desea tener "Índice" resaltado de forma predeterminada.
Verhogen

Esto es simple y fácil de comenzar agregando una clase al elemento de la página actual. La respuesta "aceptada" tardó aproximadamente una hora en averiguar cómo y por qué. Gracias por compartir
Ashwin

4

Mi enfoque es definir una variable personalizada en la parte frontal de YAML de la página y generarla en el <body>elemento:

<body{% if page.id %} data-current-page="{{ page.id }}"{% endif %}> 

Mis enlaces de navegación incluyen el identificador de la página a la que enlazan:

<nav>
    <ul>
        <li><a href="artists.html" data-page-id="artists">artists</a></li>
        <li><a href="#" data-page-id="contact">contact</a></li>
        <li><a href="#" data-page-id="about">about</a></li>
    </ul>
</nav>

En la portada de la página, configuramos la identificación de la página:

---
layout: default
title: Our artists
id: artists
---

Y finalmente un poco de jQuery para establecer el enlace activo:

// highlight current page
var currentPage = $("body").data("current-page");
if (currentPage) {
    $("a[data-page-id='" + currentPage + "']").addClass("active");
}

Pensé que este método era muy fácil de seguir y permite ordenar fácilmente los elementos del menú. Soy muy nuevo en Jekyll, por lo que los otros métodos me intimidaron un poco, pero me siento muy cómodo con jQuery. Puede que no sea 100% perfecto para los puristas, pero funciona y funciona bien.
TheBrockEllis

Si desea una solución solo líquida, puede probar esto: stackoverflow.com/a/46984009/2397550
JoostS

2

La navegación de su sitio web debe ser una lista desordenada. Para que los elementos de la lista se iluminen cuando están activos, el siguiente script líquido les agrega una clase 'activa'. Esta clase debe tener un estilo con CSS. Para detectar qué enlace está activo, el script usa 'contiene', como puede ver en el código siguiente.

<ul>
  <li {% if page.url contains '/getting-started' %}class="active"{% endif %}>
    <a href="https://stackoverflow.com/getting-started/">Getting started</a>
  </li>
  ...
  ...
  ...
</ul>

Este código es compatible con todos los estilos de enlaces permanentes de Jekyll. La declaración 'contiene' resalta con éxito el primer elemento del menú en las siguientes URL:

  • empezando/
  • Getting-started.html
  • Getting-started / index.html
  • empezar / subpágina /
  • Getting-started / subpage.html

Fuente: http://jekyllcodex.org/without-plugin/simple-menu/


2

Muchas respuestas confusas aquí. Simplemente uso un if:

{% if page.name == 'limbo-anim.md' %}active{% endif %} 

Me refiero directamente a la página y la pongo dentro de la clase que quiero

<li><a class="pr-1 {% if page.name == 'limbo-anim.md' %}activo{% endif %} " href="limbo-anim.html">Animación</a></li>

Hecho. Rápido.


¿Podrías explicar dónde pones cada uno de esos elementos? header.html o?
Georges

1

He estado usando page.pathy saliendo del nombre de archivo.

<a href="https://stackoverflow.com/" class="{% if page.path == 'index.html' %}active{% endif %}">home</a>

0

Ya hay muchas buenas respuestas.

Prueba esto.

Altero ligeramente las respuestas anteriores.

_data/navigation.yaml

- name: Home
  url: /
  active: home
- name: Portfolio
  url: /portfolio/
  active: portfolio
- name: Blog
  url: /blog/
  active: blog

En una página -> portfolio.html(Lo mismo para todas las páginas con un nombre de página activo relativo)

---
layout: default
title: Portfolio
permalink: /portfolio/
active: portfolio
---

<div>
  <h2>Portfolio</h2>
</div>

Navigation html part

<ul class="main-menu">
  {% for item in site.data.navigation %}
    <li class="main-menu-item">
      {% if {{page.active}} == {{item.active}} %}
        <a class="main-menu-link active" href="{{ item.url }}">{{ item.name }}</a>
      {% else %}
        <a class="main-menu-link" href="{{ item.url }}">{{ item.name }}</a>
      {% endif %}
    </li>
  {% endfor %}
</ul>

0

si está utilizando el tema Minima para jekyll, solo necesita agregar un ternario en el atributo de clase en header.html:

 <a {% if my_page.url == page.url %} class="active"{% endif %} href="{{ my_page.url | relative_url }}">

el extracto completo:

        <div class="trigger">
        {%- for path in page_paths -%}
          {%- assign my_page = site.pages | where: "path", path | first -%}
          {%- if my_page.title -%}
          <a {% if my_page.url == page.url %} class="active"{% endif %} href="{{ my_page.url | relative_url }}">{{ my_page.title | escape }}</a>
          {%- endif -%}
        {%- endfor -%}
      </div>

agregue esto a su _config.yml

header_pages:
  - classes.markdown
  - activities.markdown
  - teachers.markdown

Y luego, por supuesto, su css:

   a.active {
                color: #e6402a;
            }

-2

Aquí hay un método jQuery para hacer lo mismo

  var pathname = window.location.pathname;

  $(".menu.right a").each(function(index) {
    if (pathname === $(this).attr('href') ) {
      $(this).addClass("active");
    }
  });
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.