Skip to main content

CSS Inline Styling

The css helper allows you to write CSS styles directly in the style prop without creating styled components.

Basic usage

Use css template literal directly in the style prop:

import { css } from 'kstyled';
import { View, Text } from 'react-native';

function MyComponent() {
return (
<View
style={css`
padding: 20px;
background-color: #f0f0f0;
border-radius: 12px;
`}
>
<Text
style={css`
font-size: 18px;
font-weight: 600;
color: #000;
`}
>
Hello World
</Text>
</View>
);
}

Dynamic styles with props

You can use JavaScript expressions inside css for dynamic styling:

import { css } from 'kstyled';
import { Text } from 'react-native';

function DynamicText({ isActive }: { isActive: boolean }) {
return (
<Text
style={css`
font-size: 18px;
font-weight: 600;
padding: 12px;
color: ${isActive ? 'red' : 'yellow'};
background-color: ${isActive ? '#FFE5E5' : '#FFF9E5'};
`}
>
Status: {isActive ? 'Active' : 'Inactive'}
</Text>
);
}

Complex expressions

Use any JavaScript expression for dynamic values:

function Card({
size,
variant,
}: {
size: 'small' | 'large';
variant: 'primary' | 'secondary';
}) {
return (
<View
style={css`
padding: ${size === 'small' ? '8px' : '16px'};
border-radius: ${size === 'small' ? '4px' : '8px'};
background-color: ${variant === 'primary' ? '#007AFF' : '#5856D6'};
border-width: 1px;
border-color: ${variant === 'primary' ? '#0051D5' : '#3634A3'};
`}
>
<Text
style={css`
font-size: ${size === 'small' ? '14px' : '16px'};
color: white;
`}
>
{variant} {size} button
</Text>
</View>
);
}

Combining with StyleSheet

You can mix css with regular StyleSheet styles using arrays:

import { StyleSheet } from 'react-native';
import { css } from 'kstyled';

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});

function MyComponent({ highlighted }: { highlighted: boolean }) {
return (
<View
style={[
styles.container,
css`
border-width: ${highlighted ? '2px' : '1px'};
border-color: ${highlighted ? '#007AFF' : '#ccc'};
`,
]}
>
<Text>Content</Text>
</View>
);
}

Conditional styles

Apply styles conditionally:

function StatusBadge({ status }: { status: 'success' | 'warning' | 'error' }) {
return (
<View
style={css`
padding: 4px 8px;
border-radius: 4px;
background-color: ${status === 'success'
? '#34C759'
: status === 'warning'
? '#FF9500'
: '#FF3B30'};
`}
>
<Text
style={css`
font-size: 12px;
font-weight: 600;
color: white;
`}
>
{status.toUpperCase()}
</Text>
</View>
);
}

Using with state

Inline CSS works great with React state:

import { useState } from 'react';
import { css } from 'kstyled';

function InteractiveButton() {
const [pressed, setPressed] = useState(false);

return (
<Pressable
onPressIn={() => setPressed(true)}
onPressOut={() => setPressed(false)}
style={css`
padding: 16px 24px;
border-radius: 8px;
background-color: ${pressed ? '#005BBB' : '#007AFF'};
transform: scale(${pressed ? 0.95 : 1});
`}
>
<Text
style={css`
color: white;
font-weight: 600;
opacity: ${pressed ? 0.8 : 1};
`}
>
Press Me
</Text>
</Pressable>
);
}

Animations and transforms

Use CSS for dynamic transforms and animations:

import { useState } from 'react';
import { css } from 'kstyled';

function RotatingBox() {
const [rotation, setRotation] = useState(0);

return (
<Pressable
onPress={() => setRotation((prev) => prev + 45)}
style={css`
width: 100px;
height: 100px;
background-color: #007aff;
border-radius: 8px;
transform: rotate(${rotation}deg);
`}
/>
);
}

Common patterns

Flex layouts

<View
style={css`
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 16px;
`}
>
<Text>Left</Text>
<Text>Right</Text>
</View>

Centered content

<View
style={css`
flex: 1;
justify-content: center;
align-items: center;
`}
>
<Text>Centered</Text>
</View>

Cards with shadows

<View
style={css`
background-color: white;
border-radius: 12px;
padding: 16px;
shadow-color: #000;
shadow-opacity: 0.1;
shadow-radius: 8px;
elevation: 3;
`}
>
<Text>Card Content</Text>
</View>

Performance notes

The css helper is optimized at build-time by Babel, similar to styled components:

Static styles are pre-compiled

// This:
<View style={css`
padding: 16px;
border-radius: 8px;
`} />

// Is transformed to:
<View style={styles.s0} /> // ✅ StyleSheet.create() at build time

Dynamic values are computed per render

// This:
<Text style={css`
font-size: 16px;
color: ${isActive ? 'red' : 'blue'};
`} />

// Is transformed to:
<Text style={[styles.s0, { color: isActive ? 'red' : 'blue' }]} />
// ✅ Static part cached, only color changes

Optimization for arrays

// Multiple css calls in arrays are flattened:
<View style={[
css`padding: 16px`,
css`margin: 8px`,
{ backgroundColor }
]} />

// Becomes:
<View style={[styles.s0, styles.s1, { backgroundColor }]} />
// ✅ No nested arrays

Automatic memoization

kstyled automatically memoizes dynamic values - you don't need useMemo:

function MyComponent({ color, size }) {
// ✅ Automatically memoized!
// Same color + size = same style object (no re-render)
return (
<View
style={css`
background-color: ${color};
padding: ${size}px;
`}
/>
);
}

How it works:

  • Dynamic values are hashed and cached internally
  • If values don't change, the same style object is returned
  • No manual useMemo needed - it's automatic!

Best for:

  • Quick prototyping
  • One-off styles
  • Dynamic styles based on props/state

Use styled instead when:

  • Creating reusable component libraries
  • Styles are completely static
  • You need TypeScript prop type inference

When to use CSS inline vs styled

Use css inline when:

// ✅ Highly dynamic styles
<View style={css`
background-color: ${theme.colors[colorKey]};
transform: translate(${x}px, ${y}px) rotate(${rotation}deg);
`} />

// ✅ One-off components
<Text style={css`font-size: 14px; color: #666;`}>
Footer text
</Text>

Use styled when:

// ✅ Reusable components with static styles
const Card = styled.View`
padding: 16px;
border-radius: 12px;
background-color: white;
`;

// ✅ Component library
const PrimaryButton = styled.Pressable`
padding: 12px 24px;
background-color: #007aff;
border-radius: 8px;
`;

Best practices

1. Keep it simple

// Good - simple and readable
<Text style={css`
font-size: 16px;
color: ${isActive ? 'red' : 'gray'};
`}>
{label}
</Text>

// Avoid - too complex, use styled instead
<View style={css`
/* 50+ lines of CSS */
`} />

2. Extract complex logic

// Good - logic is clear
function getStatusColor(status: string) {
switch (status) {
case 'success':
return '#34C759';
case 'warning':
return '#FF9500';
case 'error':
return '#FF3B30';
default:
return '#8E8E93';
}
}

<View
style={css`
background-color: ${getStatusColor(status)};
padding: 8px;
`}
/>;

3. Combine with StyleSheet for static styles

const staticStyles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
});

// Only use css for dynamic parts
<View
style={[
staticStyles.container,
css`
border-color: ${theme.borderColor};
`,
]}
/>;