Skip to content

Latest commit

 

History

History

eleventy-plugin-styles

eleventy-plugin-styles 🍭

code style: prettier

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:

  1. Automatically reaches your styles, even from node_modules!

    In order to import style from package, simply write @(import|use) 'package_name/path/to/style'; 👐

  2. Compiles less, sass and scss.

    Plugin uses new sass package and less preprocessor, that allow you to use your favourite language for the CSS.

  3. Normalizes compiled CSS with PostCSS, autoprefixer, gets rid of unused style rules with PurgeCSS and minifies CSS with cssnano. And you can add much more plugins!

  4. Sets correct paths between HTML and CSS.

  5. 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 and scss. 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 🎉 And after all procedures will put compiled file to _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 override includePaths property, then make sure you add node_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 and css, 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 and cssnano 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! ✌️

Developed in Halo lab