Eleventy での Sass の使用と CSS の軽量化
やること
静的サイトジェネレーター Eleventy で CSS の環境を構築する方法です。以下の 2 つを行います。
- Sass を使えるようにする
- CSS の軽量化
CSS の軽量化では、以下のことを行います。
- ページ内の全ての
<style>
タグを取得し、1 つの<style>
タグにまとめる - ページで未使用の CSS を削除する
- CSS を縮小する
下準備
今回は Eleventy 公式のスタータープロジェクト eleventy-base-blog を使って説明します。尚、必要な Node.js のバージョンは、Getting Started で確認できます。
eleventy-base-blog を使用するために、GitHub リポジトリをクローンします。
git clone https://github.com/11ty/eleventy-base-blog.git my-blog-name
プロジェクトに移動します。
cd my-blog-name
依存関係のパッケージをインストールします。
npm i
あとはローカルでサーバーを立てます。
npm run serve
これで http://localhost:8080
でサイトを開けます。
Sass を使えるようにする
まずは、Sass を使えるようにします。使用するパッケージは以下の 2 つです。
この 2 つをインストールします。
npm i -D sass npm-run-all
そして、package.json の scripts を書き換えます。11ty Sass Skeleton を参考にしました。
"scripts": { "watch:sass": "sass --no-source-map --watch sass:_includes", "watch:eleventy": "npx @11ty/eleventy --serve", "build:sass": "sass --no-source-map sass:_includes", "build:eleventy": "npx @11ty/eleventy", "start": "npm-run-all build:sass --parallel watch:*", "build": "npm-run-all build:eleventy" }
次に、プロジェクトディレクトリの直下に sass フォルダを作り、フォルダ内に style.scss ファイルを作ります。
そして、ローカルサーバーを立てます。
npm start
これで style.scss に何かを書けば、コンパイルされた style.css が _includes フォルダに出力されます。
最後に、コンパイル後の style.css をサイトに反映させます。_includes/layouts/base.njk にある <link rel="stylesheet">
を全て削除し、代わりに include
を使い style.css をインラインで読み込みます。
{# <link rel="stylesheet" href="{{ '/css/index.css' | url }}"> #} <style>{% include 'style.css' %}</style>
これで Sass が使えるようになりました。
尚、インラインで CSS を読み込むのは、この後の CSS の軽量化が関係しています。
CSS の軽量化
次は、表示速度の観点から、ページ内で未使用の CSS の削除を行います。また、CSS の縮小も行います。
この削除と縮小を行うにあたって頭に浮かんだのが、Eleventy プラグインの Eleventy AMP Plugin です。この AMP プロジェクト公式プラグインは、ページ内にある全ての <style>
タグを取得し、1 つの <style>
タグにまとめた後に縮小します。これがコンポーネント化などに便利だったため、同じ動作になるようにしたいと思いました。
未使用の CSS の削除、そして縮小するために使用するパッケージは以下のものです。
4 つのパッケージをインストールします。
npm i -D clean-css jsdom purge-from-html purgecss
そして、プロジェクトディレクトリの直下に minify.js ファイルを作り、以下を追加します。
const { JSDOM } = require('jsdom'); const { PurgeCSS } = require('purgecss'); const PurgeFromHTML = require('purge-from-html').extract; const CleanCSS = require('clean-css'); module.exports = async (rawContent, outputPath) => { if (outputPath && outputPath.endsWith('.html')) { const dom = new JSDOM(rawContent); const document = dom.window.document; const styles = document.querySelectorAll('style'); let rawCSS = ''; if (styles.length) { for (const style of styles) { rawCSS = rawCSS + style.textContent; style.remove(); } } rawCSS = await new PurgeCSS().purge({ content: [{ raw: rawContent, extension: 'html' }], css: [{ raw: rawCSS }], // 未使用の CSS が削除されず残るため purge-from-html を使用する extractors: [{ extractor: PurgeFromHTML, extensions: ['html'] }], fontFace: true, keyframes: true, }); rawCSS = new CleanCSS({ level: { 2: { all: true, // 他のプロジェクトにてマークダウンのコードの挿入でエラーが出たため念の為に false にする removeUnusedAtRules: false, }, }, }).minify(rawCSS[0].css).styles; const tag = document.createElement('style'); rawCSS = document.createTextNode(rawCSS); tag.appendChild(rawCSS); document.head.appendChild(tag); return dom.serialize(); } return rawContent; };
そして、.eleventy.js の module.exports
で addTransform
を使い minify.js を読み込みます。
module.exports = function (eleventyConfig) { eleventyConfig.addTransform('minify', require('./minify')); // 以下省略 };
これで未使用の CSS の削除と CSS の縮小の完成です。
試してみます。とりあえず、以下の CSS を style.scss に書いてみます。
h1 { color: red; font-size: 48px; } .sample { display: flex; }
<style>
タグには、このように出力されます。
<style> h1 { color: red; font-size: 48px; } </style>

eleventy-base-blog には class="sample"
の要素はないため、.sample
のスタイルは PurgeCSS により全てのページで削除されます。
続いて、posts/firstpost.md に <style>
タグを追加し、h1
を上書きしてみます。
<style> h1 { color: green; } </style>
すると、http://localhost:8080/posts/firstpost/
でのみ、以下の <style>
タグが出力されます。
<style> h1 { font-size: 48px; color: green; } </style>

firstpost.md に書いた color: green;
が <head>
タグの <style>
タグに出力されます。また、本来 h1
は 2 つあるはずですが、clean-css が 1 つにまとめています。さらに、style.scss に書いた color: red;
は適用されなくなったため、clean-css により削除されます。尚、他のページでは color: red;
のままです。
CDN から読み込む場合
CDN で配信されているスタイルシートを使う場合も CSS の軽量化の対象にできます。
使用するのは、Eleventy 公式プラグインの eleventy-fetch です。
使用するために、まずはインストールします。
npm i -D @11ty/eleventy-fetch
今回はショートコードで eleventy-fetch を使ってみます。.eleventy.js に以下を追加します。
const EleventyFetch = require('@11ty/eleventy-fetch'); module.exports = function (eleventyConfig) { eleventyConfig.addAsyncShortcode('stylesheet', async (url) => { return `<style> ${await EleventyFetch(url, { duration: '1w', type: 'text', })} </style>`; }); // 以下省略 };
そして、ショートコードを使います。引数にはスタイルシートの URL を指定します。試しに、.njk ファイルに以下を追加し、CSS リセットの A modern CSS reset を読み込みます。
{% stylesheet 'https://unpkg.com/modern-css-reset/dist/reset.min.css' %}
ショートコードは、どこで使っても構いません。ただ、<style>
タグを 1 つにまとめる際に、HTML の上から順にページ内の <style>
タグを取得します。CSS の最初にあって欲しい CSS リセットは、<head>
タグの上部に書くのがいいかもしれません。読み込み順を気にしたくない場合は、@layer
を使うのがいいと思います。
これで A Modern CSS Reset をサイトに読み込みながら、未使用の CSS を削除し、そして縮小もできます。

1 つの <style>
タグにまとめられ、PurgeCSS により A Modern CSS Reset の未使用の CSS が削除されます。
Google Fonts を読み込む場合は、Fetch Google Fonts CSS に書かれているようにオプションの fetchOptions
を使いユーザーエージェントを伝えられます。
尚、eleventy-fetch を使用すると .cache フォルダが作成されます。この .cache フォルダは、.gitignore に追加するように強く推奨されています。