🍭
eleventy-plugin-styles
Compiles and normalizes styles of your site
Intention
Why should we use third-party tools like gulp
, webpack
or whatever you know for processing stylesheets if we can delegate it to Eleventy
? Cool, right
Get started
What this plugin can do:
-
Automatically reaches your styles, even from
node_modules
!In order to import style from package, simply write
@(import|use) 'package_name/path/to/style';
👐 -
Compiles
less
,sass
andscss
.Plugin uses new
sass
package andless
preprocessor, that allow you to use your favourite language for the CSS. -
Normalizes compiled CSS with
PostCSS
,autoprefixer
, gets rid of unused style rules withPurgeCSS
and minifies CSS withcssnano
. And you can add much more plugins! -
Sets correct paths between HTML and CSS.
-
Separates critical styles and uncritical ones. Thanks to critical package.
Installation
At first do:
npm i -D eleventy-plugin-styles
and then you can include it into .eleventy.js
:
const { styles } = require('eleventy-plugin-styles');
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
/* Optional options. */
});
};
Options
Plugin can accept the following options:
interface StylesPluginOptions {
/**
* Options that will be passed to [critical](https://github.com/addyosmani/critical)
* package.
*/
readonly criticalOptions?: CriticalOptions | PluginState.Off;
/**
* Path to directory with all styles.
* Should be relative to _current working directory_.
*/
readonly inputDirectory?: string;
/**
* Directory inside _output_ folder to be used as
* warehouse for all compiled styles. Will be
* prepended to public style urls in HTML.
*/
readonly publicDirectory?: string;
/**
* Options that can be passed to [`sass`](https://www.npmjs.com/package/sass)
* module.
*/
readonly sassOptions?: SassCompilerOptions | PluginState.Off;
/**
* Options that can be passed to [`less`](https://www.npmjs.com/package/less)
* module.
*/
readonly lessOptions?: Less.Options | PluginState.Off;
/** Options to be passed to [`PurgeCSS`](https://purgecss.com/). */
readonly purgeCSSOptions?: PurgeCSSOptions | PluginState.Off;
/** Options to be passed to [`CSSNano`](https://cssnano.co/). */
readonly cssnanoOptions?: CssNanoOptions | PluginState.Off;
/** Array of plugins that can be passed to [`PostCSS`](https://postcss.org). */
readonly postcssPlugins?: ReadonlyArray<AcceptedPlugin>;
/**
* Indicates whether should Eleventy watch on files
* under _inputDirectory_ or not.
*/
readonly addWatchTarget?: boolean;
}
Explanation
inputDirectory
Plugin extracts links to stylesheet files from HTML. Therefore, your templates should have links to source style files.
For example:
<!-- Note that we wrote `styles.scss` 👇 -->
<link rel="stylesheet" href="style.scss" />
Plugin recognizes followed extensions:
css
,less
,sass
andscss
. In future may be added much more if you will need it🤓
After links extraction plugin will search for these files inside inputDirectory from options. So given above example:
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
inputDirectory: 'src/styles',
});
};
Plugin will assume that path style file is src/styles/style.scss
_site/style-[hash].css
and link in HTML will be changed to:
<!-- If HTML file is in the same directory if style.css -->
<link rel="stylesheet" href="/style-[hash].css" />
_site
is used just for example. Actually name of the directory will be up to you - plugin will know about it.
You can write relative path to styles if you prefer such style. For example, if your template path is src/templates/template.11ty.js
and path to style file is src/styles/style.scss
, then:
<link rel="stylesheet" href="../styles/style.scss" />
If path starts with leading slash (
/
), then it will be removed.
publicDirectory
If you want to customize output path of compiled style inside output directory, then you can provide publicDirectory option.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
inputDirectory: 'src/styles',
publicDirectory: 'styles',
});
};
Given above example, stylesheet file will be placed into _site/styles
directory, and its public path will be styles/style-[hash].css
.
Pretty convenient, yes?
addWatchTarget
By default, Eleventy will watch for changes inside inputDirectory. You have an opportunity to disable it:
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
// Now Eleventy will not trigger rebuild process
// if any style changes.
addWatchTarget: false,
});
};
sassOptions
Plugin supports sass
preprocessor.
If you want to customize its behavior then options need to be passed to plugin.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
sassOptions: {
/* Some useful options. */
},
});
};
Plugin uses this preprocessor as the default language for CSS. You can disable it by providing off
value instead of options.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
sassOptions: 'off',
});
};
Avoid changing
file
property, because provided stylesheet will be inserted into all your HTML pages, instead of referenced ones. Bad situation☹️ . Also if you want to overrideincludePaths
property, then make sure you addnode_modules
to array (this is a default value).
lessOptions
Plugin supports less
preprocessor.
If you want to customize its behavior then options need to be passed to plugin.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
lessOptions: {
/* Some useful options. */
},
});
};
Or disable it by providing the off
value.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
lessOptions: 'off',
});
};
If you want to use this preprocessor, then you should disable
sass
preprocessor at first.
purgeCSSOptions
PurgeCSS is included as a plugin to PostCSS.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
purgeCSSOptions: {
/* Some useful options. */
},
});
};
You can disable the plugin by passing 'off'
as an option, like this:
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
purgeCSSOptions: 'off',
});
};
Avoid overriding
content
property andcss
, because they are used internally and that may cause unexpected results.
cssnanoOptions
cssnano is included as a plugin to PostCSS.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
cssnanoOptions: {
/* Some useful options. */
},
});
};
You can disable the plugin by passing 'off'
as an option, like this:
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
cssnanoOptions: 'off',
});
};
By default it uses default preset
for CSS optimization.
postcssPlugins
cssnano is included as a plugin to PostCSS.
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
postcssPlugins: [
/* Some useful plugins. */
],
});
};
By providing additional plugins
purgeCSS
andcssnano
plugins will not be removed, so if you want to change their behavior provide according options as described above☝️ .
criticalOptions
critical is included. By default, it works in production
mode and if criticalOptions
property is not equal to 'off'
value (that disables the plugin).
// .eleventy.js
module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(styles, {
criticalOptions: {
/* Some useful options. */
},
});
};
By default, it inlines critical styles into HTML and defers loading uncritical styles. It extracts critical styles from linked stylesheets, so you can safely import the same stylesheet file into multiple templates.
Tip:
critical
tries its best to rebase assets in styles, but it won't touch assets that have absolute public URL🤗 .
Word from author
Have fun!