Jekyll - Automatycznie podświetl bieżącą kartę na pasku menu

81

Używam github do hostowania witryny statycznej i Jekyll do jej generowania.

Mam pasek menu (as <ul>) i chciałbym, aby <li>odpowiadający bieżącej stronie miał przypisaną inną klasę do podświetlania CSS.

Więc coś w rodzaju pseudokodu:

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

A może nawet wygeneruj całość <ul>w Jekyll.

Jak można to zrobić przy minimalnych zmianach poza przestępstwem <ul>?

zakleszczenie papieru
źródło
1
Aby wybrać strony, których chcesz użyć, skopiuj wklej z: stackoverflow.com/a/17215331/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

116

Tak, możesz to zrobić.
Aby to osiągnąć, wykorzystamy fakt, że bieżąca strona jest zawsze reprezentowana przez zmienną ciecz: pagew szablonie, a także, że każdy post / strona ma unikalny identyfikator w swoim page.urlatrybucie.

Oznacza to, że musimy po prostu użyć pętli do zbudowania naszej strony nawigacyjnej, a robiąc to, możemy sprawdzić page.urlkażdy element pętli. Jeśli znajdzie dopasowanie, wie, jak podświetlić ten element. No to ruszamy:

  {% 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 %}

Działa to zgodnie z oczekiwaniami. Jednak prawdopodobnie nie chcesz, aby cała strona była na pasku nawigacyjnym. Aby emulować "grupowanie" stron, możesz coś takiego:

## 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 %}

Teraz strony można „grupować”. Aby nadać stronie grupę, musisz określić ją na stronach YAML Front Matter:

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

Wreszcie możesz użyć nowego kodu! Gdziekolwiek potrzebujesz nawigacji w szablonie, po prostu „wywołaj” swój plik nagłówkowy i przekaż mu kilka stron oraz grupę, którą chcesz wyświetlić:

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

Przykłady

Ta funkcja jest częścią struktury Jekyll-Bootstrap . Możesz zobaczyć dokładną dokumentację opisanego kodu tutaj: http://jekyllbootstrap.com/api/bootstrap-api.html#jbpages_list

Wreszcie możesz zobaczyć to w akcji w samej witrynie. Wystarczy spojrzeć na nawigację po prawej stronie, a zobaczysz, że bieżąca strona jest podświetlona na zielono: Przykład podświetlonego łącza nawigacyjnego

superjadex12
źródło
1
Świetne pytanie, świetna odpowiedź, dzięki. Łatwo było zmodyfikować to również dla ręcznie wybranej listy kart. chwilę zajęło uświadomienie sobie, że page.url zawiera znak „/”, np. „/index.html”, a nie „index.html”
cboettig,
Takie podejście skutkuje dla mnie błędem Jekyll. 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
Zbyt skomplikowane na coś, co powinno być wbudowane w Jekyll.
cameronroe
@cameronjroe spróbuj dodać .htmlrozszerzenie do pages_list i zamiast tego dołączyć to
HotelCalifornia
48

Mam ochotę na najprostsze wymagania nawigacyjne, wymienione rozwiązania są zbyt skomplikowane. Oto rozwiązanie, które nie obejmuje sprawy przedniej, JavaScript, pętli itp.

Ponieważ mamy dostęp do adresu URL strony, możemy znormalizować i podzielić adres URL oraz przetestować na segmentach, na przykład:

{% 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>

Oczywiście jest to przydatne tylko wtedy, gdy statyczne segmenty zapewniają środki do wytyczenia nawigacji. Coś bardziej skomplikowanego, a będziesz musiał użyć przedniej materii, jak zademonstrował @RobertKenny.

Jonplussed
źródło
To jest to, czego szukałem, ale czy nie powinno classs="active"?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
@CiroSantilli 六四 事件 法轮功 jeśli twój CSS ma styl .active, to tak. W powyższej odpowiedzi autor mówi, że klasą do przywołania w jej / jego arkuszu stylów jest .current. Nie ma sprawy.
Brian Zelip
3
@BrianZ to oficjalne: za dużo Bootstrap topi twój mózg :)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
dla strony głównej musiałem ustawić {% if current [1] == null%}
GorvGoyl
17

Podobne do rozwiązania @ ben-foster, ale bez użycia jQuery

Potrzebowałem czegoś prostego, oto co zrobiłem.

W mojej pierwszej sprawie dodałem zmienną o nazwie active

na przykład

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

Mam nawigację zawierającą następującą sekcję

    <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>

U mnie to działa, ponieważ liczba linków w nawigacji jest bardzo wąska.

RobertKenny
źródło
Dzięki @SurenderLohia lubię, aby wszystko było tak pojedyncze, jak tylko potrafię.
RobertKenny
16

Oto moje rozwiązanie, które moim zdaniem jest najlepszym sposobem na wyróżnienie bieżącej strony:

Zdefiniuj listę nawigacji w swoim _config.yml w następujący sposób:

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

Następnie w pliku _includes / header.html musisz przejrzeć listę w pętli, aby sprawdzić, czy bieżąca strona ( page.url ) przypomina dowolny element listy nawigacyjnej, jeśli tak, po prostu ustaw aktywną klasę i dodaj ją do <a>tagu:

<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>

A ponieważ używasz operatora zawiera zamiast operatora równa się = , nie musisz pisać dodatkowego kodu, aby działał z adresami URL, takimi jak „/ blog / nazwa-posta /” lub „projekty / nazwa-projektu / ” . Więc działa naprawdę dobrze.

PS: Nie zapomnij ustawić zmiennej permalink na swoich stronach.

chomba
źródło
To moje ulubione rozwiązanie, ponieważ oznacza, że ​​mogę wybrać kolejność stron.
Podoba mi się to rozwiązanie, ale nie działa, jeśli masz link nawigacyjny z adresem URL, /ponieważ wszystkie adresy URL stron zawierają początkowy ukośnik. Następujące prace: {% 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 %}
James Wilson
6

Aby to osiągnąć, użyłem trochę JavaScript. W menu mam następującą strukturę:

<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>

Ten fragment kodu javascript podkreśla aktualną odpowiednią stronę:

$(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");
});
stian
źródło
Osobiście uważam, że jest to czystsze niż powyższa metoda. Powyższa metoda zaczyna być brzydka, jeśli chcesz uporządkować strony w nawigacji lub jeśli chcesz, aby opcja „Indeks” była domyślnie podświetlona.
Verhogen,
Rozpoczęcie dodawania klasy do bieżącego elementu strony jest proste i łatwe. Odpowiedź „zaakceptowana” zajęła około godziny, aby dowiedzieć się, jak i dlaczego. Dzięki za udostępnienie
Ashwin,
4

Moje podejście polega na zdefiniowaniu zmiennej niestandardowej w przedniej części strony YAML i umieszczeniu jej w <body>elemencie:

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

Moje linki nawigacyjne zawierają identyfikator strony, do której prowadzą:

<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>

W kwestii pierwszej strony ustawiamy identyfikator strony:

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

I na koniec trochę jQuery do ustawienia aktywnego linku:

// highlight current page
var currentPage = $("body").data("current-page");
if (currentPage) {
    $("a[data-page-id='" + currentPage + "']").addClass("active");
}
Ben Foster
źródło
Pomyślałem, że ta metoda jest bardzo łatwa do naśladowania i pozwala na łatwe sortowanie pozycji menu. Jestem bardzo nowy w Jekyll, więc inne metody trochę mnie onieśmielają, ale czuję się bardzo dobrze z jQuery. Może nie być w 100% idealny dla purystów, ale działa i działa dobrze.
TheBrockEllis
Jeśli chcesz mieć tylko płynne rozwiązanie, możesz spróbować tego: stackoverflow.com/a/46984009/2397550
JoostS
2

Nawigacja w Twojej witrynie powinna być nieuporządkowaną listą. Aby elementy listy rozjaśniły się, gdy są aktywne, poniższy płynny skrypt dodaje do nich klasę „aktywną”. Ta klasa powinna być stylizowana za pomocą CSS. Aby wykryć, który link jest aktywny, skrypt używa wyrażenia „zawiera”, jak widać w poniższym kodzie.

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

Ten kod jest kompatybilny ze wszystkimi stylami permalinków w Jekyll. Oświadczenie „zawiera” pomyślnie podświetla pierwszą pozycję menu pod następującymi adresami URL:

  • pierwsze kroki /
  • Getting-started.html
  • Getting-started / index.html
  • wprowadzenie / podstrona /
  • pierwsze kroki / subpage.html

Źródło: http://jekyllcodex.org/without-plugin/simple-menu/

JoostS
źródło
2

Wiele mylących odpowiedzi. Po prostu używam if:

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

Odsyłam bezpośrednio do strony i umieszczam ją w klasie, którą chcę

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

Gotowe. Szybki.

świt
źródło
Czy mógłbyś wyjaśnić, gdzie umieściłeś każdy z tych elementów? header.html czy?
Georges,
1

Używałem page.pathi wychodziłem z nazwy pliku.

<a href="https://stackoverflow.com/" class="{% if page.path == 'index.html' %}active{% endif %}">home</a>
Pat Migliaccio
źródło
0

Istnieje już wiele dobrych odpowiedzi.

Spróbuj tego.

Nieznacznie zmieniam powyższe odpowiedzi.

_data/navigation.yaml

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

Na stronie -> portfolio.html(takie same dla wszystkich stron ze względną aktywną nazwą strony)

---
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>
Surender Lohia
źródło
0

jeśli używasz motywu Minima dla jekyll, wystarczy dodać trójnik do atrybutu class w header.html:

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

pełny fragment:

        <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>

dodaj to do swojego _config.yml

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

No i oczywiście twój css:

   a.active {
                color: #e6402a;
            }
raptoria7
źródło
-2

Oto metoda jQuery, która robi to samo

  var pathname = window.location.pathname;

  $(".menu.right a").each(function(index) {
    if (pathname === $(this).attr('href') ) {
      $(this).addClass("active");
    }
  });
niksmac
źródło