Preprocessor Project — Complete Guide
In this tutorial, you will learn about Preprocessor Project. We cover key concepts, practical examples, and best practices to help you master this topic.
Build a complete design system component library using Sass with the 7-1 architecture, BEM naming, responsive mixins, theming, and automated build pipeline.
What You'll Learn
- Planning a design system architecture
- Implementing all preprocessor techniques
- Building a component library
- Setting up the build pipeline
- Documentation generation
- Publishing and distribution
Why It Matters
- A portfolio project demonstrates all your Sass skills
- Design systems are in high demand
- Component libraries are reusable across projects
- Automated pipelines are production-ready
Real-World Use
- A design team ships a component library with Sass
- A startup creates a UI kit for multiple products
- A developer includes a component library in their portfolio
- An enterprise standardizes on a shared design system
flowchart LR A[Design System] --> B[Design Tokens] A --> C[Components] A --> D[Utilities] A --> E[Build Pipeline] B --> F[_variables.scss] C --> G[Button, Card, Form...] D --> H[Spacing, Typography] E --> I[Vite + PostCSS]
Project Overview
Build a complete design system component library with the following components and features:
Components
- Button (5 variants, 3 sizes, icon support)
- Card (with image, body, footer, featured modifier)
- Form elements (input, select, textarea, checkbox, radio)
- Navigation (horizontal, vertical, dropdown, mobile off-canvas)
- Alert (4 variants: success, error, warning, info)
- Badge (with position modifier)
- Modal (with overlay, animations, focus trap)
- Grid (responsive grid system)
Features
- Design tokens (colors, spacing, typography, breakpoints)
- Responsive mixins (respond-to, respond-until, respond-between)
- Theme support (light, dark)
- BEM naming convention
- 7-1 architecture
- Vite build with PostCSS
- Stylelint configuration
- Documentation generation
Code Example: Project Structure
design-system/
src/
scss/
abstracts/
_variables.scss // Design tokens
_mixins.scss // Responsive, variants
_functions.scss // Fluid-type, contrast
_placeholders.scss // %focus-ring, %sr-only
base/
_reset.scss // CSS reset
_typography.scss // Type scale
components/
_button.scss // Button system
_card.scss // Card component
_form.scss // Form elements
_nav.scss // Navigation
_alert.scss // Alert variants
_badge.scss // Badge component
_modal.scss // Modal dialog
layout/
_grid.scss // Grid system
_container.scss // Container
utilities/
_spacing.scss // Spacing classes
_display.scss // Display classes
themes/
_light.scss // Light theme
_dark.scss // Dark theme
main.scss // Entry point
dist/
css/
design-system.css // Expanded (dev)
design-system.min.css // Compressed (prod)
docs/ // Documentation
package.json
vite.config.js
postcss.config.js
.stylelintrc.json
Code Example: Entry Point
// main.scss - Design System Entry Point
// 1. Abstracts (no CSS output)
@use 'abstracts/variables';
@use 'abstracts/mixins';
@use 'abstracts/functions';
@use 'abstracts/placeholders';
// 2. Base styles
@use 'base/reset';
@use 'base/typography';
// 3. Layout
@use 'layout/container';
@use 'layout/grid';
// 4. Components
@use 'components/button';
@use 'components/card';
@use 'components/form';
@use 'components/nav';
@use 'components/alert';
@use 'components/badge';
@use 'components/modal';
// 5. Utilities
@use 'utilities/spacing';
@use 'utilities/display';
// 6. Themes
@use 'themes/light';
@use 'themes/dark';
Code Example: Button Component
// components/_button.scss
@use '../abstracts/variables' as v;
@use '../abstracts/mixins' as m;
.button {
$block: &;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
border: 2px solid transparent;
border-radius: 4px;
font-size: 1rem;
font-weight: 500;
line-height: 1;
cursor: pointer;
min-height: 44px;
text-decoration: none;
transition: all 0.2s ease;
&:focus-visible {
@extend %focus-ring;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
}
&--primary {
background: v.$color-primary;
color: #fff;
border-color: v.$color-primary;
&:hover {
background: v.$color-primary-hover;
border-color: v.$color-primary-hover;
}
}
&--secondary {
background: transparent;
color: v.$color-primary;
border-color: v.$color-primary;
&:hover {
background: v.$color-primary;
color: #fff;
}
}
&--small {
padding: 0.5rem 1rem;
font-size: 0.875rem;
min-height: 36px;
}
&--large {
padding: 1rem 2rem;
font-size: 1.125rem;
min-height: 52px;
}
&--full {
width: 100%;
}
&__icon {
width: 1em;
height: 1em;
flex-shrink: 0;
}
&__text {
order: 1;
}
&--icon-right {
#{$block}__icon {
order: 2;
}
#{$block}__text {
order: 1;
}
}
@include m.respond-to('md') {
&--full\@md {
width: 100%;
}
}
}
Code Example: Build Configuration
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: 'src/scss/main.scss',
formats: ['css'],
name: 'design-system'
},
outDir: 'dist/css',
cssMinify: true,
sourcemap: true
},
css: {
preprocessorOptions: {
scss: {
api: 'modern-compiler',
silenceDeprecations: ['import']
}
},
postcss: {
plugins: [
require('autoprefixer'),
require('cssnano')({
preset: ['default', {
discardComments: { removeAll: true }
}]
})
]
}
}
});
// package.json
{
"name": "design-system",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"build:css": "sass src/scss/main.scss dist/css/design-system.css --style expanded --source-map",
"build:css:min": "sass src/scss/main.scss dist/css/design-system.min.css --style compressed --no-source-map",
"lint": "stylelint 'src/**/*.scss'",
"lint:fix": "stylelint 'src/**/*.scss' --fix",
"prepublish": "npm run build"
},
"devDependencies": {
"sass": "^1.77.0",
"vite": "^5.4.0",
"autoprefixer": "^10.4.0",
"cssnano": "^6.0.0",
"postcss": "^8.4.0",
"stylelint": "^16.0.0",
"stylelint-config-standard-scss": "^13.0.0"
}
}
// .stylelintrc.json
{
"extends": "stylelint-config-standard-scss",
"rules": {
"max-nesting-depth": 3,
"selector-max-specificity": "0,3,0",
"scss/at-mixin-pattern": "^[a-z]+([a-z0-9]-?[a-z0-9]+)*$",
"scss/dollar-variable-pattern": "^[a-z]+([a-z0-9]-?[a-z0-9]+)*$",
"selector-class-pattern": "^[a-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*(__[a-zA-Z0-9]+)*(--[a-zA-Z0-9]+)*$"
}
}
Common Mistakes
- Skipping the planning phase — Define your component API, token names, and file structure before writing code.
- Not testing compiled output — Verify that scoped variables, extends, and mixins compile correctly.
- Ignoring Accessibility — All components must include focus indicators, aria attributes, and keyboard support.
- No size budget — Without monitoring output size, component libraries bloat. Set and enforce a budget.
- Inconsistent naming — Use the same patterns across all components. BEM + kebab-case is reliable.
- Not publishing documentation — A component library without usage docs is unusable. Include examples for each component.
- Locking into a specific build tool — Write portable Sass that works with any build tool (Vite, Webpack, Gulp).
Practice Questions
- What is the first step in building a design system? Define design tokens (colors, spacing, typography) before building components.
- Why use the 7-1 architecture for a component library? It separates concerns logically, scales with component count, and follows community conventions.
- How do you ensure components are accessible? Include focus indicators, proper aria attributes, keyboard support, 44px touch targets, and color contrast.
- What should be included in component documentation? Usage examples, code snippets, variant previews, configuration options, and accessibility notes.
FAQ
Mini Project
This lesson is the final project. Build the complete design system component library as described above. Include all 7 components with BEM naming, responsive mixins, light/dark theme support, 7-1 architecture, Stylelint configuration, Vite build with PostCSS (autoprefixer + cssnano), and npm scripts for dev/build/lint. Create an HTML demo page that showcases every component in all variants. Verify: (1) linting passes, (2) production CSS is under 50KB compressed, (3) all components are responsive, (4) dark theme works via data-theme attribute, (5) source maps work in development, (6) focus indicators are visible on all interactive elements.
What's Next
You have completed all 30 lessons of the CSS Preprocessors module. Continue with What Is Mobile-First Design in the next topic.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro