To solve this, our convivial_govcms_bootstrap theme adopts CSS Variables, which allow for:
- Real-time color updates without recompilation
- Better accessibility with automated contrast handling
- No-code customization for branding and color schemes
- Efficient theme management by avoiding unnecessary rework
In this blog post, we'll explore why this shift is important, how it enhances accessibility and branding, and finally, we'll break down the technical details that make it work so that you can implement it into your own theme.
You can see the colour picker in action below where the user is able to define the important base colours for a colour palette and then go on to further refine the colours. You may also notice the accessibility feedback provided to the user as they alter the colours.
The Need for a Dynamic Color Palette
Moving from SASS to CSS Variables
Previously, themes required recompiling SASS files to update colors, making it difficult for site builders to tweak palettes on the fly. CSS Variables solve this by:
- Allowing instant changes without needing recompilation
- Enabling user-defined settings in the Drupal UI
- Providing flexibility for real-time adjustments
Accessibility: The Pain of Managing Color Contrast
Color contrast is a crucial yet often neglected part of theme design. Many themes struggle with maintaining sufficient contrast between text and background, making content hard to read for users with visual impairments. Our color palette feature addresses this by:
- Dynamically adjusting contrast ratios based on WCAG standards,
- Providing a real-time contrast score in the UI,
- Allowing site builders to make accessibility-conscious design choices.
Empowering Site Builders with a No-Code Solution
Not every site builder is a developer. By using CSS Variables and a Drupal UI-based configuration, we eliminate the need to manually adjust theme files. With this system, users can:
- Set primary and secondary colors for their brand,
- Define variations for backgrounds, text, links, and buttons,
- Preview changes instantly without modifying theme code.
Prerequisites
Before diving into the integration, ensure you have the following:
- A Drupal 10 website,
- Administrator access for module and theme modifications,
- Familiarity with SCSS, PHP, and JavaScript.
Implementing the Color Palette System
Light and Dark Theme Variations
One of the most common use cases for a dynamic color system is supporting light and dark themes. By defining CSS variables for color values, site builders can seamlessly toggle between themes:
:root {
--background-light: #ffffff;
--background-dark: #222222;
--text-light: #000000;
--text-dark: #ffffff;
}
With this setup, different UI elements can automatically switch based on the selected mode, enhancing readability and aesthetics.
Branding and Color Palettes
A strong brand identity relies on a consistent color scheme. The color palette feature allows site builders to define primary and secondary brand colors, ensuring a unified look and feel across the website. These colors can be applied to:
- Headers and footers,
- Navigation elements,
- Backgrounds and overlays,
- Typography and icons.
Variations for UI Components
Beyond branding, colors play a key role in UI interaction. Site builders can define variations for different elements:
- Backgrounds: Light/dark backgrounds, overlays
- Text colors: Headings, paragraphs, links
- Buttons: Primary, secondary, hover states
- Borders and accents: Dividers, input fields, call-to-action highlights
:root {
--button-primary-bg: #007bff;
--button-primary-text: #ffffff;
--button-secondary-bg: #6c757d;
--button-secondary-text: #ffffff;
}
These settings ensure aesthetic consistency and improve usability across the theme.
Live Preview and Contrast Display
To enhance user experience, the system provides a demo area where site builders can preview changes in real-time. Additionally, it includes a color contrast checker, ensuring text meets WCAG accessibility standards.
Technical Implementation
1. Configuring Base Colors and Dependencies
To allow users to configure theme colors, we integrate the color palette settings into the theme configuration form using hook_form_system_theme_settings_alter(). This hook attaches the settings form, enabling users to select colors through the theme settings page.
/**
* Implements hook_form_system_theme_settings_alter().
*/
function mytheme_form_system_theme_settings_alter(&$form, &$form_state) {
require_once __DIR__ . '/includes/color_palette.inc';
_mytheme_color_palette_theme_settings($form, $form_state);
}
In this snippet, the _mytheme_color_palette_theme_settings function dynamically generates color configuration fields, enabling users to define base colors and their dependencies.
2. Attaching Colors to the Theme
To apply user-defined colors globally, modify the theme's attachments using hook_page_attachments_alter()
/**
* Implements hook_page_attachments_alter().
*/
function mytheme_page_attachments_alter(array &$attachments) {
// Attach Color Palettes feature if enabled.
if (theme_get_setting('colors.colors_enable')) {
require_once __DIR__ . '/includes/color_palette.inc';
_mytheme_color_palette($attachments);
}
}
This hook injects the necessary CSS variables into a new <style> element in the <html> element, ensuring the selected theme settings are applied dynamically.
3. JavaScript: Enhancing User Experience
The JavaScript file (color_palettes.js) dynamically updates colors in real-time, ensuring seamless transitions for dependent elements. It achieves this by:
- Processing color values dynamically (lightening/darkening as needed)
- Managing relationships between the base and derivative colors
- Handling contrast calculations for accessibility
Here’s an excerpt from the JavaScript logic:
// Function to process color based on the strategy
function processColor(color, processor) {
const parts = processor.split('-');
const strategy = parts[0];
const value = parseInt(parts[1], 10);
switch (strategy) {
case 'darken':
return pSBC(-value / 100, color);
case 'lighten':
return pSBC(value / 100, color);
default:
return color;
}
}
It allows derivative colors to adapt based on the user's selected base color dynamically.
4. Modify SCSS for Dynamic Color Application
Adjust the SCSS file (_color-palettes.scss) to read color values from CSS variables, allowing dynamic application based on user selections.
$focus-color: var(--standard-focus);
This approach ensures that colors are applied dynamically based on user selections.
5. Library Definition for Dependencies
Manage JavaScript and CSS assets by defining the color palette feature in mytheme.libraries.yml.
# Colour palettes
color_palettes:
version: 1.x
js:
js/color_palettes.js: { }
css:
theme:
css/color_palettes.css: { }
dependencies:
- core/jquery
- mytheme/leader_line_library
leader_line_library:
remote: https://github.com/anseki/leader-line
version: 1.0.7
license:
name: MIT
url: http://opensource.org/licenses/mit-license.php
gpl-compatible: true
js:
//cdn.jsdelivr.net/npm/leader-line@1.0.7/leader-line.min.js: { type: external, minified: true }
The Leader Line Library visually indicates color dependencies, enhancing user understanding of color relationships.
Conclusion
This approach to theme color management is not just limited to convivial_govcms_bootstrap—it can be applied to any Drupal theme that uses CSS Variables. By embracing a dynamic, accessible, and no-code color palette system, we:
- Reduce the complexity of color management,
- Improve accessibility with real-time contrast adjustments,
- Enable site builders to create visually cohesive designs effortlessly.
This feature is a game-changer for Drupal theming, allowing anyone—from developers to site builders—to customize their themes without touching code. If you’re building a theme, consider adopting this flexible, user-friendly, and powerful approach to color management.