Search code examples
htmlcssnunjuckseleventy

Several CSS files for 11ty with Nunjucks


So I have an 11ty site structured like this

.
└── app/
    ├── public
    ├── src /
    │   ├── _includes/
    │   │   ├── base.njk
    │   │   ├── header.njk
    │   │   └── footer.njk
    │   ├── css/
    │   │   ├── about.css
    │   │   ├── contact.css
    │   │   ├── core.style.css
    │   │   ├── index.css
    │   ├── images
    │   ├── about.njk
    │   ├── contact.njk
    │   ├── index.njk

And base.njk file for styling the layout

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="/css/core.style.css" />
    <title>{{ title }}</title>
</head>
<body>
    {% include 'header.njk' %}
    {{ content | safe }}
    {% include 'footer.njk' %}
</body>
</html>

With this, I can style all njk files:

index.njk

---
title: My App - Homepage
layout: base.njk
---

<div class="container">
    <img
        src="/images/image.png"
    />
</div>

So far, everything is working. My question is there is a way I can use different CSS files to style each njk file, eg: about.css for about.njk? Right now, I can style all njk files under one file which is base.njk.


Solution

  • There are several methods to achieve this with different advantages and drawbacks.

    Page Variables

    The simplest way would probably be to set the path to the CSS file in your front matter. This method is fairly flexible and works well.

    ---
    title: About
    layout: base.njk
    cssFile: "about.css"
    ---
    <!-- ... -->
    
    <!-- base.njk -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <!-- ... -->
        <link rel="stylesheet" href="/css/core.style.css" />
        <link rel="stylesheet" href="/css/{{ cssFile }}" />
        <title>{{ title }}</title>
        <!-- ... -->
    

    Automatic Linking From Filename

    If you know for sure that there is a CSS file for every page, and that the filenames match, you can find the CSS file automatically based on the template name using the page variable. However, this may cause issues if there isn't a CSS file for that page or your filenames become out of sync.

    <!-- base.njk -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <!-- ... -->
        <link rel="stylesheet" href="/css/core.style.css" />
        <link rel="stylesheet" href="/css{{ page.filePathStem }}.css" />
        <title>{{ title }}</title>
        <!-- ... -->
    

    Blocks

    The most flexible way to achieve this is by using Nunjucks blocks. However, blocks cannot be used with Eleventy layouts, so layouts must be defined through Nunjucks by extending another template.

    Create a block in the <head> of base.njk.

    <!-- base.njk -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <!-- ... -->
        <link rel="stylesheet" href="/css/core.style.css" />
        {% block head %}{% endblock %}
        <title>{{ title }}</title>
        <!-- ... -->
    

    Then in your about.njk, inject your <link> tag into the head block. Use {% extends "item.html" %} instead of layout.

    ---
    title: About
    ---
    {% extends "base.njk" %}
    
    {% block head %}
    <link rel="stylesheet" href="about.css" />
    {% endblock %}