Lesson 43-CSS Preprocessor Stylus

Stylus is an efficient CSS preprocessor that provides a concise and flexible syntax to help developers write and manage CSS code more efficiently. Here are some basic to advanced Stylus code tutorials, covering core features such as variables, nesting, mixing, inheritance, operators, etc.

1. Install Stylus

Before using Stylus in your project, you need to install the Stylus compiler first. If you are using Node.js, you can install it through npm:

npm install -D stylus

2. Basic Use

Variables
Stylus allows you to define variables to store commonly used values ​​such as color and font size to improve the maintainability of the code.

$primary-color = #3498db
body
  background $primary-color

3. Nesting

Stylus supports nesting of CSS rules, making the code structure clearer.

body
  font-size 14px
  color #333
  a
    color $primary-color
    &:hover
      text-decoration underline

4. Mixins

Mixins allow you to define a set of properties and reuse them anywhere like a function.

border-radius()
  -webkit-border-radius arguments
  -moz-border-radius arguments
  border-radius arguments

.button
  border-radius 5px

5. Inheritance

Stylus provides the extends keyword to implement selector inheritance.

.base
  font-family Arial, sans-serif
  font-size 14px

.button
  extends .base
  background-color $primary-color
  padding 10px 20px

5. Operators

Stylus supports mathematical operations and can perform calculations directly in attribute values.

width = 100%
padding = 10px

.box
  width width - (padding * 2)

6. Function and logic control

Stylus supports custom functions and conditional statements to increase the flexibility of the code.

is-mobile($width)
  if $width < 600px
    return true
  false

@media (max-width 600px)
  body
    if is-mobile(480px)
      font-size 12px

7. Import

You can import other Stylus files to facilitate code organization and reuse.

@import 'variables'
@import 'mixins'

8. Interpolation and string concatenation

Stylus provides interpolation function for dynamically generating CSS code.

device = 'mobile'
@import 'styles.' + device + '.css'

9. Modularity and namespaces

Stylus supports modular programming. You can use the namespace keyword to create namespaces to avoid global style conflicts.

namespace 'app'
  button
    display inline-block
    padding 10px 20px
  header
    background-color #333
    color #fff

This will generate:

.app-button {
  display: inline-block;
  padding: 10px 20px;
}

.app-header {
  background-color: #333;
  color: #fff;
}

10. References

The & symbol can be used to reference a parent selector, which is useful for creating complex CSS selectors.

.list
  li
    &.active
      background-color #f00
    &::before
      content '•'

This will generate:

.list li.active {
  background-color: #f00;
}
.list li::before {
  content: '';
}

11. Property Sets

Property sets allow you to define a group of shared properties that can then be used in multiple selectors.

shared-props
  font-size 14px
  font-weight bold

button primary
  shared-props
  background-color blue

button secondary
  shared-props
  background-color gray

This will generate:

button.primary,
button.secondary {
  font-size: 14px;
  font-weight: bold;
}
button.primary {
  background-color: blue;
}
button.secondary {
  background-color: gray;
}

12. Selector Combinators

Stylus supports all CSS selector combinations, such as +, ~, >, + >, etc.

.parent
  color red
  child
    color blue
  & + sibling
    color green

This will generate:

.parent {
  color: red;
}
.parent child {
  color: blue;
}
.parent + sibling {
  color: green;
}

13. Conditional Statements

Stylus supports if, unless, and when statements to apply styles conditionally.

dark-theme
  $color = #333
  if $color == #333
    body
      color $color
  else
    body
      color #fff

14. Loops

Stylus also supports loops, which can be used to create repeating patterns.

for i in 1 2 3 4 5
  .item:nth-child(i)
    margin-right (i * 10px)

This will generate:

.item:nth-child(1) {
  margin-right: 10px;
}
.item:nth-child(2) {
  margin-right: 20px;
}
.item:nth-child(3) {
  margin-right: 30px;
}
.item:nth-child(4) {
  margin-right: 40px;
}
.item:nth-child(5) {
  margin-right: 50px;
}

15. Blocks & Block Extending

Blocks in Stylus are similar to CSS rule sets and can be used to create more complex structures.

.card
  display flex
  &__content
    flex 1
  &__actions
    margin-left auto

This will generate:

.card {
  display: flex;
}
.card__content {
  flex: 1;
}
.card__actions {
  margin-left: auto;
}

16. Comments

In Stylus, single-line comments use //, and multi-line comments use /* */.

// Single-line comment
body
// Here is another single-line comment
color #333 /* This is a multi-line
comment */

17. Automatic Semicolons

Stylus automatically inserts semicolons by default, but this feature can be turned off to keep a cleaner syntax.

no-semicolons
body
  color #333
  font-size 14px
This will generate:

css
body {
  color: #333;
  font-size: 14px;
}

18. Parsing error handling

Stylus will give clear error messages when encountering syntax errors to help developers locate and fix the problem.

Error: expected "}", got "}"
  line 3, column 1:
  ...
  1: body
  2:   color #333
  3:   foobar
  ...

19. Compile and use

Use the Stylus compiler to convert the .styl file to a .css file:

npx stylus input.styl -o output/

Or compile in a Node.js application:

const stylus = require('stylus');

stylus('input.styl')
  .set('filename', 'input.styl')
  .render((err, css) => {
    if (err) throw err;
    console.log(css);
  });

20. Deployment and build tool integration

Stylus can be easily integrated into various build tools, such as Gulp, Grunt or Webpack, to achieve automated compilation.

In Gulp:

const gulp = require('gulp');
const stylus = require('gulp-stylus');

gulp.task('stylus', () =>
  gulp.src('src/stylus/*.styl')
    .pipe(stylus())
    .pipe(gulp.dest('dist/css'))
);

In Grunt:

npm install grunt --save-dev
npm install grunt-contrib-stylus --save-dev

Then configure the stylus task in your Gruntfile.js:

module.exports = function(grunt) {
  grunt.initConfig({
    stylus: {
      compile: {
        options: {
          compress: true // Whether to enable compression
        },
        files: {
          'path/to/output.css': 'path/to/input.styl' // A simple input and output example
          // Or you can use an array to map multiple pairs of files
          // 'path/to/output.css': ['path/to/input1.styl', 'path/to/input2.styl']
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-stylus');

  grunt.registerTask('default', ['stylus']);
};

In Webpack:

npm install stylus stylus-loader --save-dev

Then configure the loader in your webpack.config.js:

const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              sourceMap: true, // Whether to enable sourcemaps
            },
          },
        ],
      },
    ],
  },
};

In Vite:

npm install vite-plugin-stylus stylus --save-dev

Create or update the vite.config.js file and add the plugin configuration:

import { defineConfig } from 'vite';
import stylus from 'vite-plugin-stylus';

export default defineConfig({
  plugins: [stylus()],
});
Share your love