CSS Processing
Comprehensive CSS, Sass, Less, Stylus, PostCSS, and CSS Modules support in Packem
CSS Processing
Packem provides first-class support for CSS and all major CSS preprocessors. From vanilla CSS to advanced CSS Modules, Packem handles all your styling needs with optimized bundling and processing.
Supported CSS Technologies
CSS
Standard CSS with PostCSS processing and optimization
Sass/SCSS
Sass and SCSS preprocessing with Dart Sass or Embedded Sass
Less
Less preprocessing with full feature support
Stylus
Stylus preprocessing with expressive syntax
PostCSS
PostCSS with autoprefixer and plugin ecosystem
CSS Modules
Scoped CSS with automatic class name generation
Lightning CSS
Fast CSS parsing, transformation, and minification
cssnano
Advanced CSS minification and optimization
Basic CSS Support
Packem automatically processes CSS files imported in your JavaScript/TypeScript code:
// src/index.ts
import './styles.css'
export function createButton() {
const button = document.createElement('button')
button.className = 'btn btn-primary'
button.textContent = 'Click me'
return button
}/* src/styles.css */
.btn {
padding: 0.5rem 1rem;
border: none;
border-radius: 0.25rem;
cursor: pointer;
}
.btn-primary {
background-color: #007bff;
color: white;
}Configuration
Configure CSS processing in your packem.config.ts:
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
import lessLoader from '@visulima/packem/css/loader/less'
export default defineConfig({
transformer,
rollup: {
css: {
mode: 'extract',
loaders: [lessLoader],
less: {
options: {
math: 'parens-division',
paths: ['node_modules', 'src/styles'],
sourceMap: {}
}
}
}
}
})Sass/SCSS
Packem supports both Sass and SCSS syntax with Dart Sass or Embedded Sass.
Installation
npm install --save-dev sassnpm install --save-dev sass-embeddedUsage
// src/styles.scss
$primary-color: #007bff;
$border-radius: 0.25rem;
@mixin button-style($bg-color) {
background-color: $bg-color;
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: $border-radius;
cursor: pointer;
&:hover {
background-color: darken($bg-color, 10%);
}
}
.btn-primary {
@include button-style($primary-color);
}Configuration
export default defineConfig({
css: {
preprocessors: {
sass: {
implementation: 'sass', // or 'sass-embedded'
options: {
outputStyle: 'compressed',
sourceMap: true,
includePaths: ['node_modules', 'src/styles']
}
}
}
}
})Less
Less preprocessing with full feature support.
Installation
npm install --save-dev lessUsage
// src/styles.less
@primary-color: #007bff;
@border-radius: 0.25rem;
.button-style(@bg-color) {
background-color: @bg-color;
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: @border-radius;
cursor: pointer;
&:hover {
background-color: darken(@bg-color, 10%);
}
}
.btn-primary {
.button-style(@primary-color);
}Configuration
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
import lessLoader from '@visulima/packem/css/loader/less'
export default defineConfig({
transformer,
rollup: {
css: {
mode: 'extract',
loaders: [lessLoader],
less: {
options: {
math: 'parens-division',
paths: ['node_modules', 'src/styles'],
sourceMap: {}
}
}
}
}
})Stylus
Stylus preprocessing with expressive syntax.
Installation
npm install --save-dev stylusUsage
// src/styles.styl
primary-color = #007bff
border-radius = 0.25rem
button-style(bg-color)
background-color bg-color
color white
padding 0.5rem 1rem
border none
border-radius border-radius
cursor pointer
&:hover
background-color darken(bg-color, 10%)
.btn-primary
button-style(primary-color)Configuration
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
import stylusLoader from '@visulima/packem/css/loader/stylus'
export default defineConfig({
transformer,
rollup: {
css: {
mode: 'extract',
loaders: [stylusLoader],
stylus: {
options: {
compress: true,
paths: ['node_modules', 'src/styles'],
sourcemap: true
}
}
}
}
})PostCSS
PostCSS processing with plugin ecosystem support.
Installation
npm install --save-dev postcss postcss-load-configConfiguration
Create a postcss.config.js file:
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'),
require('postcss-custom-properties'),
require('cssnano')({
preset: 'default'
})
]
}Or configure directly in Packem:
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
import postcssLoader from '@visulima/packem/css/loader/postcss'
export default defineConfig({
transformer,
rollup: {
css: {
mode: 'extract',
loaders: [postcssLoader],
postcss: {
plugins: [
'autoprefixer',
['postcss-custom-properties', { preserve: false }],
['cssnano', { preset: 'default' }]
]
}
}
}
})Popular PostCSS Plugins
- autoprefixer - Add vendor prefixes automatically
- postcss-custom-properties - CSS custom properties support
- postcss-nested - Nested CSS rules
- postcss-import - Inline @import rules
- tailwindcss - Utility-first CSS framework
CSS Modules
CSS Modules provide locally scoped CSS to avoid naming conflicts.
Enable CSS Modules
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
transformer,
rollup: {
css: {
mode: 'extract',
autoModules: true,
// or with options
postcss: {
modules: {
scopeBehaviour: 'local',
generateScopedName: '[name]__[local]___[hash:base64:5]',
hashPrefix: 'prefix',
exportGlobals: true
}
}
}
}
})Usage
/* src/Button.module.css */
.button {
padding: 0.5rem 1rem;
border: none;
border-radius: 0.25rem;
cursor: pointer;
}
.primary {
background-color: #007bff;
color: white;
}
.secondary {
background-color: #6c757d;
color: white;
}// src/Button.ts
import styles from './Button.module.css'
export function createButton(variant: 'primary' | 'secondary' = 'primary') {
const button = document.createElement('button')
button.className = `${styles.button} ${styles[variant]}`
button.textContent = 'Click me'
return button
}CSS Modules with TypeScript
Generate type definitions for CSS Modules:
// src/Button.module.css.d.ts (auto-generated)
declare const styles: {
readonly button: string
readonly primary: string
readonly secondary: string
}
export default stylesLightning CSS
Lightning CSS provides fast CSS parsing, transformation, and minification.
Installation
npm install --save-dev lightningcssConfiguration
export default defineConfig({
css: {
transformer: 'lightningcss',
lightningcss: {
minify: true,
targets: {
chrome: 80,
firefox: 75,
safari: 13
},
drafts: {
nesting: true,
customMedia: true
}
}
}
})Features
- Fast parsing - Written in Rust for maximum performance
- Modern CSS - Support for CSS nesting, custom media queries, etc.
- Browser targets - Automatic feature detection based on targets
- Minification - Built-in CSS minification
CSS Optimization
cssnano
Advanced CSS minification and optimization.
export default defineConfig({
css: {
minimize: true,
minimizer: 'cssnano',
cssnano: {
preset: ['default', {
discardComments: { removeAll: true },
normalizeWhitespace: true,
colormin: true,
convertValues: true
}]
}
}
})Bundle Analysis
Analyze your CSS bundle size:
packem build --analyzeThis generates a report showing:
- CSS file sizes
- Unused CSS rules
- Optimization opportunities
- Dependency tree
CSS Injection Strategies
Control how CSS is injected into your application:
Extract CSS Files
export default defineConfig({
css: {
extract: true, // Extract CSS to separate files
filename: '[name].[contenthash].css'
}
})Inline CSS
export default defineConfig({
css: {
extract: false, // Inline CSS in JavaScript bundles
inject: 'style-tag' // or 'css-variables'
}
})Runtime Injection
Use the CSS style inject utility:
import { injectStyles } from '@visulima/css-style-inject'
const css = `
.dynamic-styles {
color: red;
font-weight: bold;
}
`
injectStyles(css, {
id: 'dynamic-styles',
prepend: false
})Advanced Features
CSS Custom Properties
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--border-radius: 0.25rem;
}
.btn {
background-color: var(--primary-color);
border-radius: var(--border-radius);
}CSS Nesting (with PostCSS or Lightning CSS)
.card {
padding: 1rem;
border: 1px solid #dee2e6;
.title {
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.content {
color: #6c757d;
p {
margin-bottom: 1rem;
&:last-child {
margin-bottom: 0;
}
}
}
}Container Queries
.card {
container-type: inline-size;
}
@container (min-width: 400px) {
.card-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
}Framework Integration
React
// React with CSS Modules
import styles from './Button.module.css'
interface ButtonProps {
variant?: 'primary' | 'secondary'
children: React.ReactNode
}
export function Button({ variant = 'primary', children }: ButtonProps) {
return (
<button className={`${styles.button} ${styles[variant]}`}>
{children}
</button>
)
}Vue
<template>
<button :class="[styles.button, styles[variant]]">
<slot />
</button>
</template>
<script setup lang="ts">
import styles from './Button.module.css'
interface Props {
variant?: 'primary' | 'secondary'
}
withDefaults(defineProps<Props>(), {
variant: 'primary'
})
</script>Troubleshooting
CSS Not Loading
- Check imports - Ensure CSS files are imported in your JavaScript/TypeScript
- Verify file paths - Check that CSS file paths are correct
- Check configuration - Verify CSS processing is enabled
Preprocessor Errors
- Install dependencies - Make sure preprocessor packages are installed
- Check syntax - Verify preprocessor syntax is correct
- Update paths - Check include paths and import statements
CSS Modules Not Working
- Enable CSS Modules - Set
css.modules: truein configuration - File naming - Use
.module.csssuffix for CSS Modules files - Import syntax - Use
import styles from './file.module.css'
Performance Issues
- Enable minification - Use
css.minimize: true - Extract CSS - Use
css.extract: truefor better caching - Optimize imports - Remove unused CSS imports
- Use Lightning CSS - Switch to Lightning CSS for better performance
Use packem build --verbose to see detailed CSS processing information and identify issues.
Examples
Check out our CSS examples:
- Basic CSS Processing
- Sass/SCSS Integration
- CSS Modules
- PostCSS Configuration
- Lightning CSS
- React with CSS Modules
Need more help? Check the CSS troubleshooting guide or explore CSS examples.