Properties
A property is the layer that converts a utility into real CSS.
if intent decides where, utility decides what, then property decides how it becomes actual CSS.
Every utility must eventually map to a property configuration.
Property Config
A property config is a configuration object that defines:
- Which CSS property to generate
- What values are allowed
- How values are resolved
- Whether variants are supported
- Whether special behavior applies
All property configs live inside shilpConfig.properties grouped by intent.
From the Utilities Config page, we know:
- Root level keys of properties objects is called intent
- Utility is split into property and value tokens
- Tokens are used to traverse
shilpConfig.properties[intentName] - Object with key
propertyis known as Property Config
Example config:
shilp.config.jsconst shilpConfig = { source: "react", properties: { // layout: { is: { property: "display: <v><i>;", values: { flex: "flex", grid: "grid", }, }, }, }, }; export default shilpConfig;
For intent @layout is-flex;, various parts are identified as:
- Intent name:
"layout" - Utility:
"is-flex" - Property tokens:
["is"] - Value tokens:
["flex"] - Property config path:
shilpConfig.properties.layout.is
Property Configconst propertyConfig = { property: "display: <v><i>;", values: { flex: "flex", grid: "grid", }, };
This value tokens are further used to traverse propertyConfig.values object to
find the exact value for propertyConfig.property.
Now, if value will be found using value tokens, then we can generate
actual css property by replacing <v> with values and <i> with important
flag.
Basic Shape of a Property Config
Property Configconst propertyConfig = { property: "<property-name>: <n><v><i>;", resolve: string, // optional themeKey: string, // optional variant: boolean, // optional special: boolean, // optional values: object, // optional if `themeKey` defined };
Each part has meaning.
property
Defines how final CSS is generated.
For example:
property: "display: <v><i>;"property: "margin-left: <n><v><i>;"property: "background-image: linear-gradient(<v>)<i>;"
Placeholders:
<v>→ resolved value (mandatory placeholder)<i>→ important flag (mandatory placeholder, may resolve to empty)<n>→ negative sign (optional placeholder, may resolve to empty)
Rules:
;at the end is mandatory- You can define multiple properties
<v><i>must resolve consistently- For
@space mx-4;→property: "margin-left: <n><v><i>; margin-right: <n><v><i>;" - Both left and right receive the same value.
- For
values
Defines allowed values for that property.
Values for display propertyconst propertyConfig.values = { flex: "flex", grid: "grid", // other values }
Keys become utility suffixes. Values can be nested and become actual CSS values.
Global Values
Every CSS property supports global keywords as value: inherit, initial,
unset, revert and revert-layer
These are stored at shilpConfig.values.globalValues and can be accessed
through shilpConfig.theme.globalValues.
During processing:
- Global values are deep merged with
propertyConfig.values - Final result assigned back to
propertyConfig.values
So, global values are always available.
themeKey
It used to inject values from structured dataset (shilpConfig.theme). So,
values are defined once and re-used efficiently.
Updated processing order will be:
shilpConfig.theme.colorsdeep merged withshilpConfig.theme.globalValuespropertyConfig.valuesdeep merged with the result of the previous step- Final result assigned back to
propertyConfig.values
Example config:
shilp.config.jsconst shilpConfig = { source: "react", properties: { text: { color: { property: "color: <v><i>;", resolve: "color", themeKey: "colors", variant: true, values: {}, }, }, }, }; export default shilpConfig;
This allows utilities like @text color-orange-600; without manually defining
every color by using values directly from the pre-defined structured dataset.
variant
Variant support must be enabled per property (variant: true) explicitely.
This allows utilities like @text color-orange-600/80; to be handleded
separately.
Know More: Utility Variant
resolve
Defines how values are resolved from tokens.
Shilp provides pre-defined resolvers:
| Resolver | Description |
|---|---|
"rawColor" | Returns only raw value L% C H as it is defined without processing |
"color" | Return full color oklch(L% C H) with optional opacity support |
"rawSpacing" | Return only raw value px as it is defined without processing |
"spacing" | Returns numeric values px processed to rem values |
"default" | Returns raw value as it is defined without processing |
special
Marks property as special and executes special behaviour.
It is used when one utility maps to multiple CSS properties.
Example config:
Property config (special)const propertyConfig = { property: "<v>", special: true, values: { DEFAULT: ` <property-1>: <value1><i>; <property-2>: <value2><i>; `, }, };
Important Differencies
propertyConfig.propertymust only contain<v>propertyConfig.valuesmust include all CSS properties- You can also use inline
theme(...)function for any property value - Each property rule must end with
; <i>must be present insidepropertyConfig.values- Global values are NOT merged
propertyConfig.themeKeyis NOT merged automaticallypropertyConfig.variantis ignored
If you need themeKey and/or variant behavior here:
- Do not rely on pre-defined resolvers
- Use custom value resolver
propertyConfig.resolvewithshilpConfig.extend.valueResolvers
See:
When Errors Happen
An error is thrown if:
- Property config not found
- Value not found
- Invalid
themeKey - Invalid value resolver key
resolve
Property Config Patterns
There is no single way to write a property config. Depending on your use case, you may structure it differently.
| Index | Pattern | Description | Reference |
|---|---|---|---|
| 1 | One Utility, One Property | One utility generates one CSS property with one resolved value | Read |
| 2 | One Utility, Multiple Properties, Same Value | One utility applies the same resolved value to multiple CSS properties | Read |
| 3 | One Utility, Multiple Properties, May Have Different Values | One utility outputs multiple CSS properties which may have different values, using special: true flag | Read |
| 4 | Single Word Utility | A single word utility, using DEFAULT key | Read |
| 5 | One Utility, Multiple Variants | Nested property structure allows extended variations like axis or direction | Read |
| 6 | preset-* Utility, Shorthand + Individual | Provide a complete shorthand preset while allowing individual utilities | Read |
| 7 | preset-* Utility, Multi-Part Value | Explicitly group multi-part combinations to avoid unpredictable value stacking | Read |
| 8 | Multiple Utilities With CSS Variables | Use utilities to control CSS variables and compose the final property indirectly | Read |
High-Level Properties Processing
At the beginning of processing:
- Internal default properties are created and loaded at
shilpConfig.properites - Root-level properties
shilpConfig.propertiesoverride them completely (if provided)- This is not recommended. Avoid this.
shilpConfig.extend.propertiesis deep merged toshilpConfig.properties
This defines which properties are available.
Once property config is found:
- Value tokens are resolved
- Processing is handled by the Values
- Returns resolved value
- Negative (
<n>) applied (if exists) - Important (
<i>) applied - Final CSS string generated
For example:
@layout is-flex;→display: flex;@space -ml-4;→margin-left: -1rem;
At this stage, property processing is done and we get the actual css.
Available Built-in Properties
All built-in property configurations are documented separately.
You can explore the full list in the PROPERTIES section of the documentation.
Properties are grouped and listed inside each intent section of the documentation.
Each property has its own page:
/docs/properties/<intent-name>/<properties-name>
Example:
/docs/properties/layout/overflow/docs/properties/bg/color/docs/properties/text/size
Those pages show exact property config structure with usage example.