Basic Usage
This guide covers the essentials of CSSX: writing styles and applying them to components.
Quick Start
import { styl } from 'cssxjs'
import { Pressable, Text } from 'react-native'
function Button({ children, variant, disabled }) {
return (
<Pressable styleName={['button', variant, { disabled }]}>
<Text styleName="text">{children}</Text>
</Pressable>
)
styl`
.button
padding 12px 24px
border-radius 8px
&.primary
background #007bff
&.disabled
opacity 0.5
.text
color white
`
}
Writing Styles
CSSX provides two template literals:
styl — Stylus syntax (recommended)
css — Plain CSS syntax
styl (Stylus)
Clean, indentation-based syntax without braces or semicolons:
styl`
.card
padding 16px
background white
border-radius 8px
`
css (Plain CSS)
Standard CSS syntax:
css`
.card {
padding: 16px;
background: white;
border-radius: 8px;
}
`
See styl Template and css Template for full syntax reference.
Applying Styles with styleName
The styleName prop connects elements to CSS classes. For simple cases, use a string:
<View styleName="card" />
The Recommended Pattern
For dynamic styling, use the array pattern — it's the cleanest and most maintainable approach:
<View styleName={['card', variant, { highlighted, compact }]} />
This pattern has three parts, in order:
- Base class — the main class name (
'card')
- Variant variables — string variables that map to class names (
variant)
- Boolean modifiers — an object where keys become classes when values are truthy (
{ highlighted, compact })
Example breakdown:
import { View, Text } from 'react-native'
function Card({ variant = 'default', highlighted, compact, children }) {
// If variant='featured', highlighted=true, compact=false
// Results in: styleName="card featured highlighted"
return (
<View styleName={['card', variant, { highlighted, compact }]}>
<Text>{children}</Text>
</View>
)
styl`
.card
background white
padding 16px
&.featured
border-width 2px
border-color gold
&.highlighted
shadow-color gold
shadow-radius 10px
&.compact
padding 8px
`
}
Why this pattern works:
- Readable — clear separation between base, variants, and modifiers
- Clean — no verbose
{ card: true, [variant]: true } syntax
- Flexible — add as many variants or modifiers as needed
- Maintainable — easy to see what classes are applied
Tip: Name your variables to match class names for clean shorthand: use { active } instead of { active: isActive }. This makes the code self-documenting.
Modifier Classes
Use the & parent selector for variants:
import { View, Text } from 'react-native'
function Card({ variant, highlighted, compact, children }) {
return (
<View styleName={['card', variant, { highlighted, compact }]}>
<Text>{children}</Text>
</View>
)
styl`
.card
background white
padding 16px
&.featured
border-width 2px
border-color gold
&.highlighted
shadow-color gold
shadow-radius 10px
&.compact
padding 8px
`
}
Dynamic Values
For truly dynamic values, combine styleName with the style prop:
import { View } from 'react-native'
function ProgressBar({ progress }) {
return (
<View styleName="bar" style={{ width: `${progress}%` }} />
)
styl`
.bar
height 20px
background #4caf50
`
}
Or use CSS Variables for runtime theming.
Style Placement
Inside a function — styles are scoped to that component:
import { View } from 'react-native'
function Card() {
return <View styleName="card">...</View>
styl`
.card
background white
`
}
At module level — styles are shared across the file:
import { Pressable, Text } from 'react-native'
styl`
.shared-button
padding 12px 24px
`
function ButtonA() {
return (
<Pressable styleName="shared-button">
<Text>A</Text>
</Pressable>
)
}
The u Unit
CSSX includes a custom unit where 1u = 8px (Material Design grid):
.card
padding 2u // 16px
margin 1u // 8px
gap 0.5u // 4px
CSS Support
CSSX runs on React Native, so not all CSS features are available.
Supported
Note: Animations and transitions require Reanimated v4 components (Animated.View, Animated.Text, etc.). See Animations guide for details.
Not Supported
Example: Replacing :hover
Instead of :hover, track state and use a modifier:
import { useState } from 'react'
import { Pressable, Text } from 'react-native'
function Button({ children, onPress }) {
const [pressed, setPressed] = useState(false)
return (
<Pressable
styleName={['button', { pressed }]}
onPressIn={() => setPressed(true)}
onPressOut={() => setPressed(false)}
onPress={onPress}
>
<Text styleName="text">{children}</Text>
</Pressable>
)
styl`
.button
background #007bff
&.pressed
background #0056b3
.text
color white
`
}
Best Practices
Use semantic class names:
// Good
.submit-button
.error-message
// Avoid
.blue-box
.margin-16
Keep styles close to components — place styl blocks in the same file.
Group related properties:
.card
// Layout
display flex
flex-direction column
// Spacing
padding 2u
gap 1u
// Appearance
background white
border-radius 1u
Next Steps