PostCSS & 11ty

Publié le 19/12/2021
Tag(s) : 11ty sass postcss

Introduction

Dans l'article précédent, nous avons vu comment intégrer SASS dans 11ty en passant par les templates JavaScript. La méthode présentée ne permet pas de gérer certaines règles CSS. Par exemple, display:flex doit être remplacée par display:-webkit-box ou display:-ms-flexbox pour certaines versions de navigateurs. L'API SASS ne nous donne pas les outils pour le faire, mais PostCSS dispose du plugin autoprefixer qui réalise cette tâche. Nous allons donc voir comment les intégrer à 11ty.

L'ensemble du code présenté dans cet article est disponible ici.

Quelques éléments de code

Avant de commencer, voici un petit rappel des différents éléments que nous avions dans le dernier article.

Fichier _colors.scss :

$bg-color: #2e3440;
$text-color: #eceff4;

Fichier styles.scss :

@import "colors";

html {
height: 100%;
width: 100%
}

html {
background-color: $bg-color;
color: $text-color;
display: flex; // on verra plus tard pourquoi
}

Fichier scss.11ty.js :

const path = require('path');
const sass = require('sass');

/*
* Il n'est pas nécessaire de garder le nom de la classe.
* On peut directement l'exporter.
*/

module.exports = class {

data() {
const scssDir = path.join(__dirname, '.');
const rawFilepath = path.join(scssDir, 'styles.scss');

return {
permalink: '/css/styles.css',
rawFilepath: rawFilepath
}
}

render({ rawFilepath }) {
var sassRenderResult = sass.renderSync({
file: rawFilepath,
outputStyle: "compressed",
});

return sassRenderResult.css.toString();
}
}

Intégration de PostCSS

Comme SASS, PostCSS possède une API JavaScript. La fonction principale de cette API est postcss() et prend en paramètre un tableau de plugins :

postcss(plugins)
.process(css, { from, to })
.then(result => {
console.log(result.css)
});

Comme le montre l'exemple ci-dessus, il est possible d'enchaîner les appels de fonction à partir du premier appel de postcss(). C'est ce qu'on appelle le methode chaining. process() s'occupe de transformer le CSS et retourne une Promise qui est ensuite gérée par then() avec le résultat de la transformation.

Pour intégrer PostCSS dans notre projet, il suffit de l'installer puis de l'intégrer dans notre template JS :

const path = require('path');
const sass = require('sass');
const postcss = require('postcss');

module.exports = class {

data() {
const scssDir = path.join(__dirname, '.');
const rawFilepath = path.join(scssDir, 'styles.scss');

const sassRenderResult = sass.renderSync({
file: rawFilepath,
outputStyle: "compressed",
});

const rawCss = sassRenderResult.css.toString();

return {
permalink: '/css/styles.css',
rawFilepath: rawFilepath,
rawCss: rawCss
}
}

render({ rawCss }) {
// ici
return postcss()
.process(rawCss)
.then((result) => result.css);
}
}

Dans ce code, j'ai fait le choix de déplacer sass.renderSync dans la méthode data parce que je considère le CSS produit par cette fonction comme une donnée à fournir lors de la génération de ma page. Mais il est tout à fait possible de laisser sass.renderSync dans la méthode render.

Pour ajouter autoprefixer, il suffit de l'installer puis de l'ajouter dans l'appel de la fonction :

...
render({ rawCss }) {
return postcss([require('autoprefixer')]) // ici
.process(rawCss)
.then((result) => result.css);
}
...

Ce qui nous donne le résultat suivant :

html{height:100%;width:100%}html{background-color:#2e3440;color:#eceff4;display:-webkit-box;display:-ms-flexbox;display:flex}

On y retrouve bien les règles display:-webkit-box et display:-ms-flexbox qui ont été ajoutées par le plugin.
Pour indiquer à celui-ci la liste des versions de navigateurs à prendre en charge, il faut configurer l'une des dépendances d'autoprefixer : browserslist.

browserslist est un outil JavaScript qui permet d'indiquer les navigateurs ciblés pour un projet. Il y a plusieurs méthodes pour le configurer.
Par exemple, il est possible de l'ajouter dans le package.json :

...
"browserslist": "last 5 version"
...

Ou bien en paramètre d'autoprefixer :

...
postcss([require('autoprefixer')({ overrideBrowserslist: "last 5 version" })])
...

On peut ajouter d'autres plugins comme cssnano pour remplacer la ligne outputStyle: "compressed" ou ajouter la syntaxe scss directement dans la configuration de PostCSS et ainsi éviter l'utilisation de l'API SASS dans le template.

Maintenant, vous savez comment utiliser PostCSS dans un template JS d'11ty !
Dans l'article suivant, nous allons voir comment gérer le cache du fichier de styles.