Agent skill
css-variables
Implements CSS custom properties for theming, component styling, and runtime customization. Use when building theme systems, dynamic styling, or configurable components.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/css-variables
SKILL.md
CSS Variables (Custom Properties)
Native CSS custom properties for dynamic theming and component customization.
Quick Start
Define variables:
:root {
--color-primary: #3b82f6;
--color-secondary: #6b7280;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--radius: 8px;
}
Use variables:
.button {
padding: var(--spacing-sm) var(--spacing-md);
background: var(--color-primary);
border-radius: var(--radius);
}
.card {
padding: var(--spacing-lg);
border-radius: var(--radius);
}
Syntax
Declaration
/* Global scope */
:root {
--variable-name: value;
}
/* Component scope */
.component {
--component-bg: white;
--component-padding: 16px;
}
/* Media query scope */
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #1f2937;
--color-text: #f9fafb;
}
}
Usage
.element {
/* Basic usage */
color: var(--color-text);
/* With fallback */
background: var(--color-bg, white);
/* Nested fallbacks */
border-color: var(--border-color, var(--color-primary, blue));
}
Theme System
Light/Dark Mode
:root {
/* Light mode (default) */
--color-bg: #ffffff;
--color-text: #1f2937;
--color-text-muted: #6b7280;
--color-border: #e5e7eb;
--color-primary: #3b82f6;
--color-primary-hover: #2563eb;
}
/* Dark mode via class */
.dark {
--color-bg: #1f2937;
--color-text: #f9fafb;
--color-text-muted: #9ca3af;
--color-border: #374151;
--color-primary: #60a5fa;
--color-primary-hover: #93c5fd;
}
/* Dark mode via media query */
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #1f2937;
--color-text: #f9fafb;
}
}
Complete Token System
:root {
/* Spacing scale */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
/* Font sizes */
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
/* Font weights */
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
/* Border radius */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
/* Transitions */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;
}
Component Variables
Scoped Variables
.button {
/* Define component variables */
--button-padding-x: var(--space-4);
--button-padding-y: var(--space-2);
--button-bg: var(--color-primary);
--button-color: white;
--button-radius: var(--radius-md);
/* Use them */
padding: var(--button-padding-y) var(--button-padding-x);
background: var(--button-bg);
color: var(--button-color);
border-radius: var(--button-radius);
border: none;
cursor: pointer;
transition: background var(--transition-fast);
}
.button:hover {
--button-bg: var(--color-primary-hover);
}
/* Variant via CSS */
.button.secondary {
--button-bg: var(--color-secondary);
--button-color: var(--color-text);
}
/* Size variant */
.button.small {
--button-padding-x: var(--space-3);
--button-padding-y: var(--space-1);
}
.button.large {
--button-padding-x: var(--space-6);
--button-padding-y: var(--space-3);
}
Customizable Components
.card {
--card-padding: var(--space-4);
--card-bg: white;
--card-border: 1px solid var(--color-border);
--card-radius: var(--radius-lg);
--card-shadow: var(--shadow-md);
padding: var(--card-padding);
background: var(--card-bg);
border: var(--card-border);
border-radius: var(--card-radius);
box-shadow: var(--card-shadow);
}
/* Override anywhere */
.featured-card {
--card-shadow: var(--shadow-lg);
--card-padding: var(--space-6);
}
React Integration
Setting Variables
// Inline styles
function ThemedComponent({ accentColor }) {
return (
<div style={{ '--accent-color': accentColor } as React.CSSProperties}>
<button className="themed-button">Click me</button>
</div>
);
}
// CSS
.themed-button {
background: var(--accent-color, #3b82f6);
}
Theme Provider
// ThemeProvider.tsx
interface Theme {
colors: {
primary: string;
secondary: string;
background: string;
text: string;
};
spacing: {
sm: string;
md: string;
lg: string;
};
}
const lightTheme: Theme = {
colors: {
primary: '#3b82f6',
secondary: '#6b7280',
background: '#ffffff',
text: '#1f2937',
},
spacing: {
sm: '8px',
md: '16px',
lg: '24px',
},
};
const darkTheme: Theme = {
colors: {
primary: '#60a5fa',
secondary: '#9ca3af',
background: '#1f2937',
text: '#f9fafb',
},
spacing: lightTheme.spacing,
};
function ThemeProvider({
theme,
children,
}: {
theme: Theme;
children: React.ReactNode;
}) {
const style = {
'--color-primary': theme.colors.primary,
'--color-secondary': theme.colors.secondary,
'--color-bg': theme.colors.background,
'--color-text': theme.colors.text,
'--space-sm': theme.spacing.sm,
'--space-md': theme.spacing.md,
'--space-lg': theme.spacing.lg,
} as React.CSSProperties;
return <div style={style}>{children}</div>;
}
// Usage
function App() {
const [isDark, setIsDark] = useState(false);
return (
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<main className="app">
<button onClick={() => setIsDark(!isDark)}>
Toggle Theme
</button>
</main>
</ThemeProvider>
);
}
Reading Variables in JS
// Get computed value
const element = document.documentElement;
const primaryColor = getComputedStyle(element)
.getPropertyValue('--color-primary')
.trim();
// Set variable
element.style.setProperty('--color-primary', '#ff0000');
// React hook
function useCSSVariable(name: string) {
const [value, setValue] = useState('');
useEffect(() => {
const computed = getComputedStyle(document.documentElement)
.getPropertyValue(name)
.trim();
setValue(computed);
}, [name]);
const setVariable = useCallback((newValue: string) => {
document.documentElement.style.setProperty(name, newValue);
setValue(newValue);
}, [name]);
return [value, setVariable] as const;
}
Calculations
.element {
/* Basic calc */
padding: calc(var(--space-4) / 2);
/* Combining variables */
margin: calc(var(--space-2) + var(--space-4));
/* With fixed values */
width: calc(100% - var(--space-8));
/* Multiplication */
font-size: calc(var(--text-base) * 1.5);
/* Complex expressions */
height: calc(100vh - var(--header-height) - var(--footer-height));
}
Responsive Variables
:root {
--container-padding: var(--space-4);
--heading-size: var(--text-2xl);
}
@media (min-width: 768px) {
:root {
--container-padding: var(--space-6);
--heading-size: var(--text-3xl);
}
}
@media (min-width: 1024px) {
:root {
--container-padding: var(--space-8);
--heading-size: var(--text-4xl);
}
}
.container {
padding: var(--container-padding);
}
h1 {
font-size: var(--heading-size);
}
Animation with Variables
.animated-element {
--animation-distance: 20px;
--animation-duration: 0.3s;
transition: transform var(--animation-duration) ease;
}
.animated-element:hover {
transform: translateY(calc(var(--animation-distance) * -1));
}
/* Keyframes with variables */
@keyframes slide-in {
from {
transform: translateX(var(--slide-distance, 100%));
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.slide-in {
--slide-distance: 50px;
animation: slide-in 0.3s ease-out;
}
Best Practices
- Use semantic names -
--color-primarynot--blue-500 - Define at :root - Global tokens at document level
- Component scope - Component-specific vars in component
- Provide fallbacks -
var(--color, fallback) - Document variables - Comment what each does
Common Patterns
Color Opacity
:root {
--color-primary-rgb: 59, 130, 246;
}
.overlay {
background: rgb(var(--color-primary-rgb) / 0.5);
}
.backdrop {
background: rgb(var(--color-primary-rgb) / 0.1);
}
Conditional Styling
.component {
--is-active: 0;
opacity: calc(0.5 + (var(--is-active) * 0.5));
transform: scale(calc(0.95 + (var(--is-active) * 0.05)));
}
.component.active {
--is-active: 1;
}
Reference Files
- references/theming.md - Theme patterns
- references/tokens.md - Token organization
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?