Skip to content

Stylus Basics — Complete Guide

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Stylus Basics. We cover key concepts, practical examples, and best practices to help you master this topic.

Stylus is an expressive CSS preprocessor with optional braces, indentation-based syntax, and powerful built-in functions for concise stylesheets.

What You'll Learn

  • Installing and compiling Stylus
  • Indentation-based syntax (no braces, no semicolons)
  • Variables without prefixes
  • Mixins and functions
  • Built-in functions
  • Key differences from Sass and Less

Why It Matters

  • Stylus offers the most concise syntax
  • Used in some Node.js projects and frameworks
  • Understanding multiple preprocessors is valuable
  • Unique features like transparent mixins

Real-World Use

  • A Node.js API project uses Stylus for its admin panel
  • A developer prefers Stylus for its minimal syntax
  • A legacy project uses Stylus with Express
  • A framework uses Stylus for its component library
flowchart LR
  A[Stylus] --> B[Indentation Syntax]
  A --> C[Prefix-free Variables]
  A --> D[Transparent Mixins]
  A --> E[Property Lookup]
  B --> F[No {} or ;]
  C --> G[color = #0066CC]
  D --> H[Mixin looks like property]
  E --> I[@prop = 'blue']

Stylus Basics

Code Example: Installation and Syntax

# Install Stylus globally
npm install -g stylus

# Install as dev dependency
npm install --save-dev stylus

# Compile
stylus styles.styl styles.css

# Compile directory
stylus src/stylus/ dist/css/

# Watch mode
stylus --watch src/stylus/ dist/css/

# Compress output
stylus --compress styles.styl styles.min.css
// Stylus syntax - no braces, no semicolons, no colons
// Just indentation

// Variables (no prefix)
primary = #0066CC
secondary = #6c757d
font-stack = 'Inter', system-ui, sans-serif
spacing-unit = 8px

// Nesting (indentation-based)
.card
    background #fff
    border 1px solid #eee
    border-radius 8px
    padding 1.5rem

    &__title
        font-size 1.25rem
        color primary

    &__text
        color secondary
        line-height 1.6

    &:hover
        box-shadow 0 4px 12px rgba(primary, 0.15)

// Properties can use ":" or just space
// Both work:
.element
    color: #333
    padding 1rem

// Mix of CSS and Stylus syntax
.element
    font-family font-stack

Expected output: Stylus uses indentation instead of braces. Variables have no prefix. Property values can be separated by spaces (no colon required). The syntax is the most minimal of the preprocessors.

Code Example: Variables and Interpolation

// Variables (no prefix, just name = value)
primary = #0066CC
secondary = #6c757d
base-font = 16px
border-radius = 4px

// Variable assignment with operators
double-spacing = spacing-unit * 2
half-spacing = spacing-unit / 2

// Interpolation (using {} syntax)
vendor = 'webkit'
property = 'margin'
size = 16px

.element
    // Property interpolation
    {property} size
    {property}-left size

    // Selector interpolation
    .{vendor}-app
        display flex

    // Variable in values (no interpolation needed)
    color primary

// Block-scoped variables
.card
    card-padding = 24px  // Local scope
    padding card-padding

.other
    // padding card-padding  // Error: undefined

// Property lookup (access another property's value)
.element
    width 200px
    height @width  // Uses the value of width (200px)
    line-height @width  // Not a reference, just a lookup

Expected output: Variables need no prefix. Interpolation uses {} syntax. Property lookup with @ accesses another property in the same block, which is a unique Stylus feature.

Code Example: Mixins and Functions

// Mixin (no keyword, just indentation)
button-base()
    display inline-flex
    align-items center
    padding 8px 16px
    border none
    border-radius 4px
    font-size 1rem
    cursor pointer
    min-height 44px

// Mixin with parameters
button-variant(bg, color = #fff)
    button-base()  // Include another mixin
    background bg
    color color

    &:hover
        background darken(bg, 10%)

// Transparent mixin (mixin has same name as property)
border-radius()
    -webkit-border-radius arguments
    -moz-border-radius arguments
    border-radius arguments

.element
    border-radius(4px)

// Function (returns a value)
fluid-type(min-size, max-size, min-vw = 320px, max-vw = 1200px)
    slope = (max-size - min-size) / (max-vw - min-vw)
    intercept = min-size - slope * min-vw
    return 'clamp(%s, %s + %s, %s)' % (min-size intercept slope * 100vw max-size)

// Usage
h1
    font-size fluid-type(2rem, 4rem)

// Conditional in mixin
button-size(size)
    if size == 'small'
        padding 4px 8px
        font-size 0.75rem
    else if size == 'large'
        padding 12px 24px
        font-size 1.25rem
    else
        padding 8px 16px
        font-size 1rem

// Usage
.btn-small
    button-size('small')

// Rest parameter
box-shadow(shadows...)
    box-shadow shadows

.element
    box-shadow(0 2px 4px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.05))

Expected output: Mixins and functions both use indentation. Transparent mixins have the same name as CSS properties. Functions use the return keyword to output a value.

Code Example: Built-in Functions

// Color functions
primary = #0066CC

.element
    background darken(primary, 10%)
    color lighten(primary, 60%)
    border-color saturate(primary, 20%)
    opacity alpha(primary)
    background rgba(primary, 0.5)
    color contrast(primary)  // Auto text color

// Math functions
.element
    width unit(33.33, '%')     // 33.33%
    width ceil(33.33%)         // 34%
    height floor(33.33%)       // 33%
    opacity round(0.555)       // 1
    z-index abs(-100)          // 100

// Math operations
.element
    width 100% / 3
    padding 16px * 2
    margin 16px + 8px

// Type checking
check(n)
    if typeof(n) == 'unit'
        n * 1px
    else
        error('Not a number')

.element
    width check(100)

// String functions
.element
    content 'Hello ' + 'World'
    content s('Hello %s!', 'Stylus')

// JSON support
// Stylus can import JSON files
// json('data.json')
// Then access: json.primary-color

// Lookup
primary = #0066CC
.element
    color lookup('primary')  // Variable lookup by name

Expected output: Stylus has comprehensive built-in functions for color, math, strings, and Type Checking. The s() function creates format strings. lookup() accesses variables by name at runtime.

Common Mistakes

  1. Inconsistent indentation — Stylus relies on indentation. Mixing tabs and spaces causes compilation errors.
  2. Forgetting that functions need return — Functions must use the return keyword. Without it, they output CSS instead of returning a value.
  3. Confusing mixins and functions — Mixins output CSS rules. Functions return values. The syntax looks similar but behavior differs.
  4. Not understanding transparent mixins — A mixin named border-radius() overrides the CSS property. This is intentional for vendor prefixing.
  5. Missing parentheses for parameterless mixins — button-base calls the mixin, button-base without parens references the mixin object.
  6. Overusing property lookup — @property uses the current block's property value. It is not a CSS variable or reference.
  7. Smaller ecosystem — Stylus has fewer plugins and community resources than Sass. Check plugin availability before committing.

Practice Questions

  1. What is the variable syntax in Stylus? No prefix: primary = #0066CC (just name = value).
  2. How do you return a value from a Stylus function? Use the return keyword inside the function body.
  3. What is a transparent mixin? A mixin with the same name as a CSS property that intercepts property calls for vendor prefixing.
  4. How does property lookup work in Stylus? @property-name accesses the value of another property in the same block.

FAQ

Is Stylus faster than Sass?

Compilation speed is comparable. Stylus syntax is simpler to parse, but Sass has a more mature ecosystem.

Can I use Stylus with React or Vue?

Yes. Both Vite and Webpack support Stylus via stylus-loader or built-in preprocessor options.

Should I learn Stylus in 2026?

Sass is the dominant preprocessor. Stylus is valuable for maintaining legacy projects or if its minimal syntax appeals to you.

Mini Project

Set up a Stylus project and build a component library. Install Stylus, create a directory structure with components/, a main.styl entry point, and _variables.styl for design tokens. Build 3 components (button with variants using conditions, card with BEM-style nesting, nav with responsive breakpoints). Use transparent mixins for border-radius and vendor prefixes. Use property lookup for related dimensions. Compile with --compress. Compare the Stylus source size and syntax conciseness with the equivalent Sass code from earlier lessons.

What's Next

Continue with Lesson 25: PostCSS Introduction to learn the PostCSS ecosystem.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro