If you are new to vue-cli and its webpack template, you are probably in a situation where you do not really know how to declare global style rules for your project. This article will show you how to do this with standard CSS, but also with a preprocessor. We will use Stylus with stylus-loader.
One big strength of Vue.js is its modular nature. Just like the pieces of a puzzle, Vue allows you to build complex applications using components. Each component is ideally represented in a
.vue file which contains its own template, script and style. A single file component is a convenient way to encapsulate all the code of a specific building block. But what if we need some global CSS rules, for instance to set the default font family, background image or general media queries?
Style rules declared in
.vue files are processed by Webpack thanks to vue-loader and PostCSS. When a style section is scoped, these rules only apply to the component in which they are defined. This means that you will not be able to style the body element from a scoped style section.
<body> is actually defined in your
index.html and is not part of any component template.
Suppose we are in
App.vue. This will not have any effect:
Now if we remove the
scoped attribute, the background color will be set! An unscoped style section for
App.vue is therefore a nice place to put some global CSS rules that are not specific to a component. However,
App.vue is a component itself, which may be a bit counterintuitive…
We have seen that style sections from single file components are processed by Webpack. But in fact, you do not really need a style section in a
.vue file to give some work to Webpack. You can simply import your CSS as a dependency in your
It works, but it looks weird. Moreover, in a Vue.js project, Webpack is mostly used to compile single file components. So when a stylesheet is not related to any specific component, it might be interesting to put it in the
static folder to distinguish it easily.
static folder, resources are not processed by Webpack. If you put a
style.css in there, you will have to reference it manually in your
index.html like so:
Webpack relies on loaders to process resources. If you use a CSS preprocessor like Sass, Less or Stylus, you will need the corresponding loader for Webpack:
stylus-loader. For this particular example, we will use Stylus which is the most flexible and easiest to configure in a Vue.js project.
First of all, install Stylus and its loader in your project:
npm i stylus stylus-loader -D. We put these packages in dev dependencies because, of course, they will not be required in production.
If CSS preprocessors are part of your ordinary workflow, you probably like to create global files that contain some variables or mixins. For example, a common use case is to have all colors from a design in a single file using variables. It is useful since you can then use clear variable names in your code instead of a more obscure hexadecimal notation. In your Vue.js project, you may want to create such a file, named
colors.styl (in a
stylus folder), with the following content:
So far so good! There is still an important question, though: how do you include and use that file in your project?
The most basic approach is to import your
colors.styl in the style section of each component using the following syntax:
Problem: it strongly violates the DRY (Don’t Repeat Yourself) principle because you will have to write this rule again and again… In large projects where there are lots of components, this is not a viable solution. If you move your file, you will have to modify your import everywhere.
A better approach is to use a Webpack alias to avoid repetitive modifications in case you move your
styl file. If you installed vue-router through vue-cli, you probably saw some
@ in import paths. This is actually an alias that corresponds to
src. We can then apply the same logic to reference some global Stylus files!
resolve.alias section of your
build/webpack.base.conf.js, add this code:
In your components, you should now be able to import your
colors.styl like so:
This is undoubtedly better, but what happens if you rename
variables.styl? You will have to modify your imports in all components…
The best solution, by far, is to add a
plugins section at the end of your
webpack.base.conf.js (right after
module) with appropriate configuration to enable auto-import.
Restart your dev server.
You are now ready for the next battle!