Advanced Customization
aliascss.config.js is the control center for advanced AliasCSS workflows. With it, you can change how classes are parsed, extend or replace compilers, define reusable utility bundles, control media prefixes, support extraction helpers, and even shape AliasCSS into a custom design system instead of using it as a fixed utility framework.
At a basic level, the config file already supports custom media prefixes, CSS Module integration, extractor helpers, prebuilt class names, grouping, ignore rules, global statements, and custom colors. The official npm guide also shows that extend can add new compilers or override existing ones, which is the foundation for deeper customization.
This part of AliasCSS is not just about adding shortcuts. It is the layer where you define your own styling language, your own utility API, and your own design-system conventions.
Why this matters
Most utility frameworks give you a closed vocabulary. AliasCSS is different because the config file lets you redefine how that vocabulary works.
That means you can:
- Keep the default AliasCSS syntax and only add project-specific utilities.
- Override built-in behavior to match your own naming or token system.
- Create custom grouped utilities that behave more like semantic component primitives.
- Build a hybrid system where atomic utilities, reusable groups, and component contracts all work together.
For a growing product or design system, this is powerful because your utility layer no longer needs to stay generic. It can evolve into an internal style compiler tailored to your team.
Config structure
A typical config includes input, output, and optional advanced keys such as media, extractorFunction, importModuleAs, custom, extend, prebuild, statement, group, and ignore.
const config = {
input: ['app/**/*.(tsx|jsx)', 'components/**/*.(tsx|jsx)', 'public/*.html'],
output: {
location: './public/css/acss.css',
'--file': true,
},
media: {
prefix: {
xs: '@media (max-width : 600px)',
},
},
'--module': true,
importModuleAs: 'x',
extractorFunction: 'x',
custom: {
colors: {
main: 'rgb(12,23,45)',
theme: '#c6c6c6',
},
},
extend: {},
prebuild: {},
statement: '',
group: {},
ignore: [],
}
export default configThe npm guide also documents running AliasCSS from the config file with npx aliascss --config, plus watch mode with npx aliascss --config --watch.
extend: create your own compiler
extend is the most advanced part of the configuration system. It lets you override an existing compiler or define a new one.
When the compiler key matches a valid CSS property, it can replace or customize the default behavior for that property. When the key is custom, you provide property to tell AliasCSS which real CSS property should receive the output.
Example: overriding and adding compilers
const config = {
extend: {
'background-color': {
alias: 'bgc',
values: ['transparent:t:no-color'],
compiler: (value) => value.replace(/^-/, ''),
},
shadow: {
property: 'box-shadow',
compiler: (value) => {
value = value.slice(1)
const values = {
'3xl': '0px 32px 64px -12px var(--shadow-color,rgba(16, 24, 40, 0.14))',
'2xl': '0px 24px 48px -12px var(--shadow-color,rgba(16, 24, 40, 0.14))',
xl: '0px 20px 24px -4px var(--shadow-color,rgba(16, 24, 40, 0.14))',
lg: '0px 12px 16px -4px var(--shadow-color,rgba(16, 24, 40, 0.14))',
md: '0px 4px 8px -2px var(--shadow-color,rgba(16, 24, 40, 0.14))',
sm: '0px 1px 3px var(--shadow-color,rgba(16, 24, 40, 0.14))',
xs: '0px 1px 2px var(--shadow-color,rgba(16, 24, 40, 0.14))',
}
if (values.hasOwnProperty(value)) return values[value]
},
},
},
}
export default configHow to think about extend
Use extend when you want to change the meaning of a property, normalize custom naming, or map design tokens into your own utility API.
A few practical examples:
- Map a utility prefix to internal tokens such as
bgc-surface,bgc-panel, orbgc-elevated. - Create a design-system shadow compiler so developers use
shadow-smorshadow-xlinstead of raw values. - Replace default value parsing to support organization-specific naming patterns.
Developer notes
aliascreates a short utility prefix.valuesdefines preset values or shorthand aliases.compilerreceives the value portion and returns the final CSS value.propertyis required when the compiler name is not a native CSS property.
Compiler names cannot contain numbers or uppercase letters other than the first character.
Group compilers
By default, one AliasCSS class typically maps to one property and one value. Group compilers let one class generate multiple CSS declarations.
This is useful when you want a class to act like a compound primitive rather than a single-property utility.
Example: token import groups
import { getCompiler } from 'aliascss'
const config = {
extend: {
background: {
alias: 'bg',
values: ['transparent:t:no-color'],
compiler: (value) => value,
},
'import-var': {
type: 'group',
groups: {
spacing: `
--space-1:4px;
--space-2:8px;
--space-3:12px;
--space-4:16px;
--space-5:24px;
--space-6:32px;
--space-7:40px;
--space-8:48px;
--space-9:64px;
`,
theme: `
`,
},
},
},
}
export default configIn this pattern, a single class can inject a named block of CSS variables or declarations. That makes it useful for tokens, themes, spacing presets, and environment-level setup.
Example: text group compiler
const config = {
extend: {
text: {
type: 'group',
compiler: (value) => {
let result = ''
const match = /-([-]?[\w\.]+)/
const property = ['font-size', 'line-height', 'letter-spacing', 'font-weight']
value.match(new RegExp(match, 'g')).forEach((e, i) => {
if (i < property.length) {
result += `${property[i]}:${e
.replace(match, '$1')
.replace(/(\d)d(\d)/, '$1.$2')
.replace(/([\d])p([\s]|$)/, '$1%$2')};`
}
})
return result
},
groups: {
'1': 'font-size:12px;letter-spacing:0.0025em;line-height:16px;',
'2': 'font-size:14px;letter-spacing:0em;line-height:20px;',
'3': 'font-size:16px;letter-spacing:0em;line-height:24px;',
'4': 'font-size:18px;letter-spacing:-0.0025em;line-height:26px;',
'5': 'font-size:20px;letter-spacing:-0.005em;line-height:28px;',
'6': 'font-size:24px;letter-spacing:-0.00625em;line-height:30px;',
'7': 'font-size:28px;letter-spacing:-0.0075em;line-height:36px;',
'8': 'font-size:35px;letter-spacing:-0.01em;line-height:40px;',
'9': 'font-size:60px;letter-spacing:-0.025em;line-height:60px;',
xs: 'font-size:12px;letter-spacing:0.0025em;line-height:16px;',
sm: 'font-size:14px;letter-spacing:0em;line-height:20px;',
md: 'font-size:16px;letter-spacing:0em;line-height:24px;',
lg: 'font-size:18px;letter-spacing:-0.0025em;line-height:26px;',
xl: 'font-size:20px;letter-spacing:-0.005em;line-height:28px;',
'2xl': 'font-size:24px;letter-spacing:-0.00625em;line-height:30px;',
'3xl': 'font-size:28px;letter-spacing:-0.0075em;line-height:36px;',
'4xl': 'font-size:35px;letter-spacing:-0.01em;line-height:40px;',
'5xl': 'font-size:60px;letter-spacing:-0.025em;line-height:60px;',
},
},
},
}
export default configThis is a strong example of turning AliasCSS into a typography API. Instead of composing font-size, line-height, and letter-spacing separately, one utility can generate a full text scale contract.
Example: box, placement, colorize, container, section
import { getCompiler } from 'aliascss'
const config = {
extend: {
box: {
type: 'group',
compiler: (value) => {
let result = ''
const match = /-([-]?[\w\.]+)/
const property = ['width', 'height', 'padding']
value.match(new RegExp(match, 'g')).forEach((e, i) => {
if (i < property.length) {
result += `${property[i]}:${e
.replace(match, '$1')
.replace(/(\d)d(\d)/, '$1.$2')
.replace(/([\d])p([\s]|$)/, '$1%$2')};`
} else {
result = result.replace(
/;$/,
` ${e.replace(match, '$1').replace(/(\d)d(\d)/, '$1.$2').replace(/([\d])p([\s]|$)/, '$1%$2')};`
)
}
})
return result
},
},
placement: {
type: 'group',
compiler: (value) => {
let result = ''
const match = /-([-]?[\w\.]+)/
const property = ['position', 'top', 'right', 'bottom', 'left']
value.match(new RegExp(match, 'g')).forEach((e, i) => {
if (i < property.length) {
result += `${property[i]}:${e
.replace(match, '$1')
.replace(/(\d)d(\d)/, '$1.$2')
.replace(/([\d])p([\s]|$)/, '$1%$2')};`
}
})
return result
},
},
colorize: {
type: 'group',
compiler: (value, custom) => {
let result = ''
const match = /-([-]?[\w\.]+)/
const property = ['background-color', 'border-color', 'color']
value.match(new RegExp(match, 'g')).forEach((e, i) => {
if (i < property.length) {
if (e.match(/^--[a-zA-Z]/)) {
result += `${property[i]}:var(${e});`
} else {
result += `${property[i]}:${getCompiler('color').compiler(e, custom)};`
}
}
})
return result
},
},
container: {
type: 'group',
compiler: (value) => value,
groups: {
'1': 'display:block;margin:auto;width:var(--container-1,448px)',
'2': 'display:block;margin:auto;width:var(--container-2,688px)',
'3': 'display:block;margin:auto;width:var(--container-3,880px)',
'4': 'display:block;margin:auto;width:var(--container-4,1136px)',
xs: 'display:block;margin:auto;width:var(--container-xs,448px)',
sm: 'display:block;margin:auto;width:var(--container-sm,688px)',
md: 'display:block;margin:auto;width:var(--container-md,880px)',
lg: 'display:block;margin:auto;width:var(--container-lg,1136px)',
},
},
section: {
type: 'group',
compiler: (value) => value,
groups: {
'1': 'display:block;padding:var(--section-padding-1,24px) auto',
'2': 'display:block;padding:var(--section-padding-2,40px) auto',
'3': 'display:block;padding:var(--section-padding-3,64px) auto',
'4': 'display:block;padding:var(--section-padding-4,80px) auto',
xs: 'display:block;padding:var(--section-padding-xs,24px) auto',
sm: 'display:block;padding:var(--section-padding-sm,40px) auto',
md: 'display:block;padding:var(--section-padding-md,64px) auto',
lg: 'display:block;padding:var(--section-padding-lg,80px) auto',
},
},
},
}
export default configThese examples show four different directions group compilers can take:
boxbuilds multi-property layout primitives.placementcreates positional shorthand contracts.colorizecoordinates multiple color-related properties through one utility.containerandsectiondefine higher-level layout primitives tied to design tokens.
Group compiler patterns
Once you start using type: 'group', AliasCSS stops feeling like a strict single-property utility engine and starts behaving more like a CSS DSL for your design system.
A good mental model is this:
| Pattern | Role |
|---|---|
| Single-property compiler | Atomic utility |
| Group compiler | Compound primitive |
prebuild | Static utility bundle |
group | Global class alias |
--as- inline grouping | Local semantic abstraction |
This layered model is what makes AliasCSS well-suited for a hybrid design system. You can move between raw utilities and reusable semantic patterns without leaving the framework.
Compiler properties
The official config examples and your extended examples together establish the main compiler properties below.
| Property | Type | Description |
|---|---|---|
values | Array | Default or predefined values. |
alias | string | Short alias for the property or compiler. |
compiler | function | Receives the value portion, and optionally custom config, and returns the final CSS output. |
property | string | Real CSS property to use when the compiler key is not itself a CSS property. |
groups | object | Static named groups of multiple CSS declarations. |
type | string | When set to 'group', the compiler is treated as a group compiler. |
media: customize media prefixes
The config file can override default media prefixes by defining your own prefix-to-media-query mapping.
const config = {
media: {
prefix: {
xs: '@media (max-width : 600px)',
},
},
}
export default configThis is useful when your team has its own breakpoint system. MDN describes @media as the CSS at-rule used to apply styles only when a media query matches, which aligns with how AliasCSS maps prefix names to media conditions.
When to customize media
Use custom media prefixes when:
- Your design system already defines breakpoint tokens.
- You want naming like
mobile,tablet,desktop, or2xlinstead of generic defaults. - You need organization-specific responsive contracts across multiple apps.
extractorFunction
By default, AliasCSS looks for class names in class and className. extractorFunction lets you declare an additional wrapper function so AliasCSS can still find class strings when they are nested inside expressions or conditional helpers.
const config = {
extractorFunction: 'x',
}
export default configNow you can use a helper that simply returns the string:
import { useState } from 'react'
const x = (y: string) => y
export default function Button() {
const [isActive, setActive] = useState(false)
return (
<div>
<button
onClick={() => setActive(!isActive)}
className={
isActive
? x('bgc-primary100 border-1px-s-primary700 c-primary700')
: x('bgc-gray200 c-gray700 b1px-s-gray700')
}
>
Button
</button>
</div>
)
}This keeps dynamic class composition readable while still allowing the compiler to extract the strings.
importModuleAs: use AliasCSS with CSS Modules
The npm guide documents built-in support for module-style workflows with --module and importModuleAs. CSS Modules export a mapping object from local class names to generated scoped names, which is why the pattern works naturally in component files.
const config = {
'--module': true,
importModuleAs: 'x',
}
export default configThen in the component:
import { useState } from 'react'
import x from './Button.tsx.module.css'
export default function Button() {
const [isActive, setActive] = useState(false)
return (
<div>
<button
onClick={() => setActive(!isActive)}
className={
isActive
? x['bgc-primary100 border-1-s-primary700 c-primary700']
: x['bgc-gray200 c-gray700 b-1px-s-gray700']
}
>
Button
</button>
</div>
)
}Why this is valuable
This mode lets you keep the speed of AliasCSS utilities while also gaining scoped CSS behavior for component-level isolation. That is helpful when large teams want to reduce naming conflicts and avoid global ordering issues.
Custom colors
Custom colors are registered under custom.colors in the config file. The npm guide notes that custom color keys should not use - or _ if you want them to work reliably, so camelCase is the safer naming convention.
const config = {
custom: {
colors: {
themeTextColor: 'var(--theme-text-color,#c3c3c3)',
themeBgcolor: 'var(--theme-bg-color,#0e0e0e)',
primary: 'rgba(124,143,234,1)',
},
},
}
export default configThis is useful when you want utilities to resolve against design tokens, CSS variables, or brand-specific color names instead of raw palette values.
prebuild: predefined class names
prebuild lets you define static utility bundles that compile into ready-to-use class names.
const config = {
prebuild: {
'text-xl': 'font-size:20px;line-height:30px',
'text-lg': 'font-size:18px;line-height:28px',
'text-md': 'font-size:16px;line-height:24px',
'text-sm': 'font-size:14px;line-height:20px',
'text-xs': 'font-size:12px;line-height:18px',
'radius-xs': 'border-radius:4px',
'flex-center': 'display:flex;align-items:center;justify-content:center',
},
}
export default configAnd then use them directly:
<h1 class="text-sm lg-text-xl --hover-text-md">Hello World</h1>When to use prebuild
Use prebuild for patterns that are static, repeat often, and do not need dynamic parsing. Good examples are typography scale utilities, layout helpers, radius tokens, and alignment shorthands.
group: global grouped AliasCSS classes
group lets you bundle valid AliasCSS class names into global reusable class names. The npm guide explicitly notes that grouped names can be used as predefined bundles, while your note adds an important limitation: group cannot be used with selector.
const config = {
group: {
container: 'df fdc bsbb aic flex-shrink-1 flex-grow-1',
section: 'flex-shrink0 bsbb',
'button-base': 'bgc-gray300 oln --hover-bgc-gray400 bn --focus-outline-none',
},
}
export default configgroup vs --as-
A useful distinction is:
groupis global and config-driven.--as-is local and authored inline.
Use group for framework-level or project-wide primitives. Use --as- when a pattern is being shaped close to component markup or when you want semantic reuse without pushing everything into global config.
ignore: tell AliasCSS to skip classes
ignore is for collision control. The official docs show that ignored class names are simply skipped, which is useful when working alongside other CSS frameworks or a legacy stylesheet.
const config = {
ignore: ['color-primary', 'fs-xl'],
}
export default configThis is especially important in migration projects where Tailwind, Bootstrap, handwritten CSS, or third-party UI libraries may use class names that overlap with AliasCSS patterns.
statement: inject global CSS
statement injects global CSS into compiled output. The npm guide shows this as a way to add shared variables or base styles across all compiled CSS files.
const config = {
statement: `
:root {
--bg-dark-color: rgba(111,111,111,1);
--bg-light-color: rgba(21,21,21,1);
--outline-color: blue;
}
body {
font-family: BlinkMacSystemFont, -apple-system;
}
`,
}
export default configYour note is important here: avoid relying too heavily on statement when compiling file-by-file with --file. In that workflow, a shared root stylesheet is often cleaner for long-term maintenance.
Building your own AliasCSS dialect
This advanced layer is best understood as a spectrum of abstraction.
Level 1: utility extension
Add a few custom colors, one shadow compiler, and some prebuilt helpers.
Level 2: token-driven utilities
Replace raw values with token-aware compilers for spacing, colors, text, and layout.
Level 3: compound primitives
Use group compilers for text scales, color systems, layout containers, and component shells.
Level 4: hybrid design system
Blend:
- Atomic utilities for local control.
prebuildfor stable utility bundles.groupfor global semantic primitives.--as-for inline component extraction.- Group compilers for higher-level API design.
At this level, AliasCSS is no longer just a compiler for shorthand classes. It becomes a design-system authoring tool.
Suggested architecture
A practical team setup could look like this:
const config = {
custom: {
colors: {
surface: 'var(--color-surface)',
panel: 'var(--color-panel)',
primary: 'var(--color-primary)',
danger: 'var(--color-danger)',
},
},
prebuild: {
'text-body': 'font-size:16px;line-height:24px',
'text-title': 'font-size:20px;line-height:30px;font-weight:600',
'flex-center': 'display:flex;align-items:center;justify-content:center',
},
group: {
card: 'bgc-surface radius-lg shadow-sm p-16px',
'button-base': 'radius-md px-16px py-10px fw-600',
},
extend: {
shadow: {
property: 'box-shadow',
compiler: (value) => value,
},
text: {
type: 'group',
compiler: (value) => value,
groups: {
body: 'font-size:16px;line-height:24px;',
title: 'font-size:20px;line-height:30px;font-weight:600;',
},
},
},
}
export default configThis kind of configuration gives your team a controlled vocabulary that still feels lightweight in markup.
The more powerful your config becomes, the more important naming consistency becomes. If utility names, group names, and compiler behavior drift without a shared convention, your custom AliasCSS layer can become harder to learn than plain CSS.
Documentation strategy
If you expose advanced customization to other developers, document it in layers:
- Start with simple
extendexamples. - Show how
property,alias, andvalueswork together. - Introduce
type: 'group'only after single-property compilers are clear. - Separate static patterns (
prebuild,group) from dynamic compilers. - End with a full design-system example that combines colors, typography, layout, and component primitives.
This progression helps developers understand not just what each config key does, but how the whole system fits together.