Build a Ready-To-Use Jekyll Setup — Part 3: Dynamic Navigation Menu

Photo by Timothy Muza on Unsplash

Intro

In This Part

Prerequisites

Current State

/
_de/
impressum.html
index.html
_en/
index.html
legal.html
_includes/
footer.html
head.html
header.html
nav.html
scripts.html
_layouts/
default.html
_sass/
base.scss
css/
main.scss
js/
main.js
_config.yml
Gemfile
Gemfile.lock

Additional Pages

In the _de/ directory create the following files with the corresponding content. The Front Matter attributes follow the same structure as described in the second part of this guide.

leistungen.html:

moebel.html:

tueren.html:

In the _en/ directory create the corresponding counterparts with the respective contents.

services.html:

furniture.html:

doors.html:

Note that each new file in the _en/ collection has a corresponding counterpart in the _de/ collection with the same name attribute as described in part two of this guide.

Navigation Menu

A comfortable way of doing this is by defining the structure of the navigation menu in some kind of list. We can use a YAML file for this. By default, Jekyll provides an optional folder, _data/, to host YAML and other file formats which will be accessible during the build process without further configuration.

We will make use of this feature and create a _data folder in the project root directory. Inside the folder create a new YAML file navigation.yml with the following content:

This file defines the structure of the navigation menu. In line 1 we define a name, main, under which the German and the English menus will be available (you can choose a different name if you want). Wrapping the configuration for the navigation menu this way gives us the opportunity to configure multiple navigation menus in the same file.

Within main we create two lists, de and en. Their naming must follow the definition of the collections in _config.yml, i.e. de and en. Otherwise, the next step won’t work.

The items in de and en will define the structure for the German and the English navigation menu. Every item within one of the two lists will represent a navigation item of the respective language. The order of the items is important since the order of the navigation items in the rendered HTML document will be the same.

Each item itself consists of a label and a url variable. The value of the label will be used as the label of the navigation item and can be freely selected. The value of the url will be used to build the reference to the related file. It therefore must match with respective file name within the corresponding collection, plus a leading forward slash (e.g. /doors.html when referencing doors.html from the English collection _en/).

That way we can simply add to or remove pages from the navigation menu, as well as specifying the order of the navigation items.

If we want an item to host a submenu, we can add a third attribute submenu which in turn holds a list of items containing a label and a url, similar as before.

We can now bring everything together in the nav.html file — our HTML template for the navigation menu. What we want is to generate an unordered list <ul> of items based on the pre-defined structure in navigation.yml. When an item contains a submenu, we want the submenu to be an unordered list within the current list <li> element, too.

Therefore, change nav.html as following:

The two links from the previous part are removed. Instead we loop over the list of navigation items as defined in navigation.yml, which corresponds to the language of the current page. We do that with a for-loop in line 3.

site.data.navigation.main[page.lang] can be interpreted as following: site is a Jekyll variable that gives us access to the _data/ folder and the navigaton.yml file. In navigation.yml we access the main variable which we used to wrap the German and the English navigation menu. We then use the language code defined in the Front Matter of the current page, page.lang, to access the list of menu items that corresponds to the current language.

For each item of the selected list we create an anchor element <a> within a list element <li> (line 4 to 7). The value of the href attribute is build by concatenating the baseurl from the _config.yml, the language code of the current page (page.lang) and the file name of the current item as defined in the url attribute within navigation.yml. The label is also taken from label attribute of the current item.

If any item contains a submenu (checked in line 9) a second unordered list is generated by looping the nested list of submenu items, similar as before.

In addition, we add an additional CSS class for the item that contains a submenu in order to give it a different styling or behavior if needed (line 4).

Result

/
_data/
navigation.yml
_de/
impressum.html
index.html
leistungen.html
moebel.html
tueren.html
_en/
doors.html
furniture.html
index.html
legal.html
services.html
_includes/
footer.html
head.html
header.html
nav.html
scripts.html
_layouts/
default.html
_sass/
base.scss
css/
main.scss
js/
main.js
_config.yml
Gemfile
Gemfile.lock

Running bundle exec jekyll serve in your terminal now builds and serves the website under http://127.0.0.1:4000.

Illustration: Result of part 3

The navigation is now dynamically generated according our pre-defined list in navigation.yml and works as expected. Regardless on which page the language is toggled, the same page is loaded in the alternative language.

Source Code

In the Next Part

MOVE TO PART 4

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store