How to Create CSS Variables for a Website Color Palette: A Complete Guide
Creating a consistent color scheme is one of the most important steps in building a professional website. However, managing colors across multiple pages can quickly become complicated. You might use the same blue for buttons, links, headings, and icons, only to discover that changing the brand color requires editing dozens of CSS rules.
This is where CSS variables become useful.
CSS variables allow you to define reusable color values in one place and use them throughout your website. Instead of repeating hex codes in your stylesheet, you can create meaningful variables for your primary color, secondary color, background, text, borders, and other interface elements.
In this guide, you will learn how to create CSS variables for a website color palette, organize them effectively, build light and dark themes, improve color consistency, and maintain a scalable design system. You will also discover practical CSS examples that you can copy, customize, and use in your own projects.
Whether you are building a personal blog, a business website, a landing page, or a web application, these techniques will help you manage colors more efficiently.
What Are CSS Variables?
CSS variables, officially called CSS custom properties, are reusable values that you define in a stylesheet and reference elsewhere using the var() function.
For example, you might define your website's primary brand color like this:
:root {
--color-primary: #2563eb;
}
You can then use that variable wherever you need the same color:
button {
background-color: var(--color-primary);
}
a {
color: var(--color-primary);
}
h1 {
color: var(--color-primary);
}
If you decide to change your brand color later, you only need to update --color-primary in its original definition.
CSS variables work with many types of values, including colors, spacing, font sizes, border radii, and shadows. For a website color palette, they provide a convenient way to centralize and reuse color values.
Why Use CSS Variables for Website Colors?
Using CSS variables for your color palette offers several advantages:
- Consistency: Reuse the same colors across every page and component.
- Easy maintenance: Update a color in one place instead of searching through your entire stylesheet.
- Better organization: Give colors meaningful names that explain their purpose.
- Theme support: Switch between light and dark themes without rewriting component styles.
- Faster development: Create reusable design tokens for buttons, cards, forms, navigation, and other interface elements.
- Scalability: Manage larger websites with multiple pages, layouts, and components more easily.
For most modern websites, CSS custom properties are a practical foundation for a maintainable color system.
Step 1: Choose a Color Palette for Your Website
Before writing CSS, decide which colors your website needs. A well-organized palette helps you avoid random color choices and creates a more consistent visual experience.
A typical website color palette contains the following categories.
| Color Category | Purpose | Example |
|---|---|---|
| Primary | Main brand color and important actions | #2563EB |
| Secondary | Supporting brand elements | #7C3AED |
| Accent | Highlights and special elements | #F59E0B |
| Background | Main page background | #FFFFFF |
| Surface | Cards, panels, and input backgrounds | #F8FAFC |
| Text | Main content and headings | #0F172A |
| Muted Text | Descriptions and secondary information | #64748B |
| Border | Dividers and component outlines | #E2E8F0 |
| Success | Successful actions and confirmations | #15803D |
| Error | Validation errors and destructive actions | #DC2626 |
These values are examples, not universal design rules. Choose colors that suit your brand, content, audience, and accessibility requirements.
How Many Colors Should a Website Palette Have?
A useful starting point is a small set of core brand colors supported by neutral colors and a few status colors.
You do not need a unique color for every element. Instead, use a limited palette with clearly defined roles.
For example, a technology blog might use:
- Blue for primary buttons and links.
- White for the main background.
- Dark navy for headings.
- Gray for secondary text and borders.
- Green for successful actions.
- Red for errors and warnings.
You can explore different combinations with an online color palette generator before turning your selected colors into CSS variables.
The goal is to create a palette that is visually consistent, easy to maintain, and readable across different devices.
Step 2: Define CSS Color Variables in the :root Selector
The easiest way to create global CSS color variables is to define them inside the :root pseudo-class.
The :root selector represents the document's root element. For an HTML document, it refers to the element. Custom properties declared there are available throughout the document unless another applicable declaration overrides them.
Here is a complete example:
:root {
/* Brand colors */
--color-primary: #2563eb;
--color-secondary: #7c3aed;
--color-accent: #f59e0b;
/* Background colors */
--color-background: #ffffff;
--color-surface: #f8fafc;
/* Text colors */
--color-text: #0f172a;
--color-text-muted: #64748b;
/* Border and status colors */
--color-border: #e2e8f0;
--color-success: #15803d;
--color-error: #dc2626;
}
This creates a centralized collection of color variables for your website.
You can reference these variables in your other CSS rules without repeating their hex codes.
Why Use :root Instead of Defining Variables Everywhere?
Consider two approaches.
Without CSS variables:
.primary-button {
background-color: #2563eb;
}
.navigation-link {
color: #2563eb;
}
.feature-icon {
color: #2563eb;
}
With CSS variables:
:root {
--color-primary: #2563eb;
}
.primary-button {
background-color: var(--color-primary);
}
.navigation-link {
color: var(--color-primary);
}
.feature-icon {
color: var(--color-primary);
}
The second approach makes your stylesheet easier to maintain. If you change the primary color, every component using that variable automatically receives the updated value.
It also makes the purpose of the color clearer. A variable named --color-primary communicates more information than a repeated hex code.
Step 3: Use CSS Variables with the var() Function
After defining your color variables, use the var() function to apply them to website elements.
The basic syntax is:
property: var(--variable-name);
For example:
body {
background-color: var(--color-background);
color: var(--color-text);
}
h1,
h2,
h3 {
color: var(--color-text);
}
a {
color: var(--color-primary);
}
button {
background-color: var(--color-primary);
color: #ffffff;
border: none;
}
Notice that the button uses a white foreground color. You should verify that text and background combinations provide sufficient contrast rather than assuming every brand color works with white text.
Add Fallback Values to CSS Variables
The var() function can also accept a fallback value.
button {
background-color: var(--color-primary, #2563eb);
}
If --color-primary is missing or has an invalid value for the property, the browser can use the fallback.
Fallbacks are useful when building reusable components or working with stylesheets that might not define every custom property.
However, they do not automatically repair every invalid declaration. For example, a variable that exists but contains an unsuitable value can still cause the declaration to become invalid.
For a website you control, defining the required variables centrally is usually preferable to adding fallback values everywhere.
Step 4: Organize Your Website Color Palette into Semantic Variables
One of the most important decisions when creating CSS variables is how to name them.
You can name variables after their actual colors or after the roles they perform in your design.
For example:
:root {
--blue-600: #2563eb;
--gray-900: #0f172a;
--gray-100: #f1f5f9;
}
These names describe the colors themselves. This approach is useful for defining a collection of design tokens.
However, semantic names often work better when styling website components.
:root {
--color-primary: #2563eb;
--color-text: #0f172a;
--color-background: #ffffff;
--color-border: #e2e8f0;
}
The semantic version explains how each color should be used.
Semantic Names vs. Color-Based Names
| Naming Approach | Example | Best Use |
|---|---|---|
| Color-based | --blue-600 |
Defining raw palette values |
| Semantic | --color-primary |
Styling reusable components |
| Component-specific | --button-background |
Customizing a particular component |
| State-based | --color-error |
Communicating validation or status |
For a small website, semantic names alone may be enough. For a larger project, you can combine both approaches.
For example:
:root {
/* Raw palette */
--blue-600: #2563eb;
--blue-700: #1d4ed8;
--slate-900: #0f172a;
--slate-100: #f1f5f9;
/* Semantic design tokens */
--color-primary: var(--blue-600);
--color-primary-hover: var(--blue-700);
--color-text: var(--slate-900);
--color-surface: var(--slate-100);
}
Now you can adjust the underlying palette while keeping the meaning of your semantic variables unchanged.
This structure becomes especially valuable when multiple components share the same design system.
Step 5: Create a Complete Website Color Palette with CSS Variables
Let's combine the previous techniques into a practical example.
The following CSS creates a reusable color system for a modern website.
:root {
/* Primary brand palette */
--color-primary: #2563eb;
--color-primary-hover: #1d4ed8;
--color-secondary: #7c3aed;
--color-accent: #f59e0b;
/* Neutral palette */
--color-background: #ffffff;
--color-surface: #f8fafc;
--color-text: #0f172a;
--color-text-muted: #64748b;
--color-border: #e2e8f0;
/* Feedback colors */
--color-success: #15803d;
--color-warning: #b45309;
--color-error: #b91c1c;
--color-info: #0369a1;
/* Interactive states */
--color-focus: #2563eb;
}
body {
margin: 0;
background-color: var(--color-background);
color: var(--color-text);
font-family: Arial, sans-serif;
line-height: 1.6;
}
.card {
padding: 1.5rem;
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 0.75rem;
}
.button {
display: inline-block;
padding: 0.75rem 1.25rem;
background-color: var(--color-primary);
color: #ffffff;
border: none;
border-radius: 0.5rem;
cursor: pointer;
}
.button:hover {
background-color: var(--color-primary-hover);
}
a {
color: var(--color-primary);
}
.muted-text {
color: var(--color-text-muted);
}
.success-message {
color: var(--color-success);
}
.error-message {
color: var(--color-error);
}
:focus-visible {
outline: 3px solid var(--color-focus);
outline-offset: 3px;
}
You can place this code in your main CSS file and reuse the variables across your website.
The palette covers branding, backgrounds, text, borders, feedback messages, and interactive states. As your website grows, you can add variables for additional components or design requirements.
Step 6: Create Light and Dark Color Themes
CSS variables make it easier to support light and dark themes.
Instead of rewriting the styles for every component, define different values for the same semantic variables.
For example:
:root {
color-scheme: light;
--color-background: #ffffff;
--color-surface: #f8fafc;
--color-text: #0f172a;
--color-text-muted: #475569;
--color-border: #e2e8f0;
--color-primary: #2563eb;
}
[data-theme="dark"] {
color-scheme: dark;
--color-background: #0f172a;
--color-surface: #1e293b;
--color-text: #f8fafc;
--color-text-muted: #cbd5e1;
--color-border: #334155;
--color-primary: #93c5fd;
}
Your component styles can continue using the same variables:
body {
background-color: var(--color-background);
color: var(--color-text);
}
.card {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
}
a {
color: var(--color-primary);
}
To activate the dark theme, apply the data-theme attribute to the HTML element:
For the light theme, use:
A theme switcher can update this attribute with JavaScript.
The color-scheme property also informs the browser about the intended color scheme for browser-provided interface elements, such as certain form controls and scrollbars. It does not automatically recolor every component on your website.
Support the User's System Theme
If you want your website to follow the visitor's operating system preference, use the prefers-color-scheme media feature.
:root {
color-scheme: light;
--color-background: #ffffff;
--color-text: #0f172a;
--color-surface: #f8fafc;
}
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
--color-background: #0f172a;
--color-text: #f8fafc;
--color-surface: #1e293b;
}
}
This is a simple approach when you do not need a manual theme selector. If your site supports both automatic and manual themes, establish a clear precedence so the visitor's explicit choice is respected.
Step 7: Improve Accessibility with Color Variables
A good website color palette should look attractive and make content easy to read.
CSS variables simplify accessibility improvements because you can update a shared color without editing every component individually.
Check Text and Background Contrast
For normal-sized text, the Web Content Accessibility Guidelines (WCAG) generally recommend a contrast ratio of at least 4.5:1 for Level AA compliance. Large text generally requires at least 3:1.
For example, a light gray text color may look elegant on a white background but still be difficult for some visitors to read.
You can define a darker text variable:
:root {
--color-text: #1f2937;
--color-background: #ffffff;
--color-text-muted: #475569;
}
Then use the variables consistently:
body {
color: var(--color-text);
background-color: var(--color-background);
}
.description {
color: var(--color-text-muted);
}
Test the actual foreground and background combinations with a contrast checker. Do not assume that a color passes accessibility requirements simply because it appears dark enough.
Do Not Rely on Color Alone
Color should not be the only way to communicate information.
For example, a form should not indicate an error solely by changing an input border to red. Include an explanatory message or another suitable visual indicator.
Similarly, links should remain distinguishable from surrounding text, and keyboard users should be able to identify the currently focused element.
You can manage these styles through semantic variables:
:root {
--color-error: #b91c1c;
--color-success: #15803d;
--color-focus: #2563eb;
}
Remember that contrast must be evaluated for the actual color combinations and interface states in use.
Step 8: Use CSS Variables for Hover, Focus, and Other States
Interactive elements often need slightly different colors depending on their state.
Instead of scattering these values across your stylesheet, create dedicated variables.
:root {
--color-primary: #2563eb;
--color-primary-hover: #1d4ed8;
--color-primary-active: #1e40af;
--color-focus: #2563eb;
}
Apply them to buttons:
.button {
background-color: var(--color-primary);
color: #ffffff;
}
.button:hover {
background-color: var(--color-primary-hover);
}
.button:active {
background-color: var(--color-primary-active);
}
.button:focus-visible {
outline: 3px solid var(--color-focus);
outline-offset: 3px;
}
This approach creates a predictable system for interactive elements.
It also makes global adjustments easier. If your design changes, you can update the relevant state variables without modifying every button individually.
For larger projects, consider adding variables for disabled states, selected navigation items, form validation, and notification backgrounds.
Step 9: Manage CSS Variables Across Multiple Files
As a website grows, keeping every variable and component in one large stylesheet can become inconvenient.
You can organize your color variables into a dedicated CSS file.
For example, create a file named colors.css:
:root {
--color-primary: #2563eb;
--color-secondary: #7c3aed;
--color-background: #ffffff;
--color-surface: #f8fafc;
--color-text: #0f172a;
--color-text-muted: #64748b;
--color-border: #e2e8f0;
}
Then load it before the component styles:
@import url("colors.css");
/* Component styles */
Alternatively, import the file from your main stylesheet or include it through your build system.
The important point is to ensure that the file defining your variables is loaded and that the declarations are available where they are needed.
Use a Consistent Naming Convention
Choose a naming structure and follow it throughout the project.
For example:
--color-primary--color-primary-hover--color-background--color-surface--color-text--color-text-muted--color-border
Avoid mixing unrelated naming styles such as --mainBlue, --bg1, and --text-color-secondary without a clear convention.
Consistent names make your code easier to understand, especially when multiple developers maintain the same website.
Step 10: Common Mistakes to Avoid When Creating CSS Color Variables
CSS variables are straightforward, but a few mistakes can make a color system harder to maintain.
1. Using Too Many Similar Colors
Creating separate variables for every tiny shade difference can make the palette unnecessarily complicated.
Start with a manageable set of brand, neutral, and status colors. Add new variables only when they serve a clear purpose.
2. Choosing Unclear Variable Names
A variable named --blue-1 might not communicate whether it is intended for links, headings, or backgrounds.
Use semantic names when defining the roles of colors in your interface.
3. Forgetting Theme-Specific Colors
A color that works well against a white background may not work against a dark background.
Test text, links, buttons, borders, and focus indicators in every supported theme.
4. Assuming CSS Variables Automatically Create a Design System
Variables provide reusable values, but they do not enforce consistent design decisions on their own.
A well-organized system also requires clear naming conventions, sensible component styles, documentation where appropriate, and regular testing.
5. Ignoring Browser Support Requirements
CSS custom properties are supported by modern browsers, but older browser environments may require alternative styling approaches.
If your project must support legacy browsers, review your compatibility requirements before relying on custom properties throughout the stylesheet.
6. Forgetting Variable Scope
Custom properties follow the CSS cascade and inheritance rules.
For example:
.card {
--color-primary: #7c3aed;
}
This variable is available to the card and its descendants, but it does not automatically become a global variable for unrelated elements.
Use :root for site-wide tokens and narrower selectors when you intentionally want local overrides.
Frequently Asked Questions
1. How Do I Create CSS Variables for a Website Color Palette?
Define your colors as custom properties inside the :root selector, then reference them with var().
:root {
--color-primary: #2563eb;
--color-background: #ffffff;
--color-text: #0f172a;
}
body {
background-color: var(--color-background);
color: var(--color-text);
}
button {
background-color: var(--color-primary);
}
This allows you to reuse colors throughout your website and update them centrally.
2. What Is the Best Way to Name CSS Color Variables?
Use descriptive, consistent names that explain the purpose of each color. Names such as --color-primary, --color-text, --color-background, and --color-border are easy to understand.
For larger projects, combine semantic variables with raw palette tokens such as --blue-600 or --slate-900.
3. Can CSS Variables Be Used for Dark Mode?
Yes. Define your default color variables in :root, then override them inside a selector such as [data-theme="dark"].
Because your components continue using the same semantic variables, their colors change automatically when the active theme changes.
4. What Is the Difference Between CSS Variables and Sass Variables?
CSS custom properties are available in the browser at runtime and participate in the CSS cascade and inheritance system. They can be changed through different selectors, media queries, and JavaScript.
Sass variables are processed by the Sass compiler and generally replaced with their values in the generated CSS. They are useful for build-time calculations and stylesheet generation, while CSS custom properties are particularly useful for runtime theming.
5. Can CSS Variables Store Hex Color Codes?
Yes. CSS custom properties can store hex color values, such as #2563eb, as well as other valid CSS color representations, including rgb(), hsl(), and modern color functions.
For example:
:root {
--color-primary: #2563eb;
--color-secondary: rgb(124 58 237);
--color-accent: hsl(38 92% 50%);
}
Choose a format that suits your workflow and use it consistently where practical.
6. Can I Change CSS Variables with JavaScript?
Yes. JavaScript can update a custom property dynamically.
document.documentElement.style.setProperty(
"--color-primary",
"#7c3aed"
);
This changes the primary color variable on the root HTML element. Any applicable styles that reference the variable will use the updated value.
This technique is useful for theme selectors, interactive color tools, and user-customizable interfaces.
7. How Many CSS Color Variables Should a Website Have?
There is no fixed number. A simple website might need only a handful of variables, while a large application could require dozens of design tokens.
Start with the colors your design actually uses, including brand colors, text, backgrounds, borders, and essential interface states. Add more variables when they improve clarity or consistency.
8. Do CSS Variables Improve Website Performance?
CSS variables primarily improve maintainability and flexibility rather than guaranteeing faster page loads.
They help reduce duplicated color definitions and make theme changes easier. Actual performance depends on the overall stylesheet, DOM structure, rendering work, and other implementation details.
9. Can CSS Variables Be Used in Media Queries?
Yes. You can override custom properties inside media queries to change a website's colors or other design values under particular conditions.
For example:
:root {
--color-background: #ffffff;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: #0f172a;
}
}
The media query changes the variable value when the visitor's operating system prefers a dark color scheme.
10. Where Should I Define CSS Variables for a Website?
For a site-wide color palette, :root is usually the best starting point. It makes the variables available throughout the document.
Use component-level selectors when a variable should apply only to a particular component or section. For larger projects, consider keeping the core palette in a dedicated stylesheet or design-token file.
Conclusion
Learning how to create CSS variables for a website color palette is a practical way to build a more consistent and maintainable website. Instead of repeating hex codes throughout your stylesheets, you can define reusable color values and reference them wherever needed.
Start by choosing a small, purposeful palette. Define your global colors inside :root, use descriptive semantic names, and apply the variables to common elements such as buttons, links, backgrounds, text, and borders.
As your website grows, extend the system to include hover states, accessibility-focused colors, and light and dark themes. Test contrast ratios, keep your naming conventions consistent, and avoid introducing unnecessary color variations.
With a well-organized collection of CSS custom properties, updating your website's visual identity becomes much simpler. You can change a handful of values instead of rewriting individual component styles, making your design system easier to maintain as your project evolves.
If you are developing a new website or improving an existing one, start by creating your core color variables today. A little organization at the beginning can save considerable time as your website grows.