When I first started writing the code for this website, I had cobbled together styles from Cayman, Rouge and a good amount of Coolors to iterate on the color schemes. But as my site grew, I wanted to refactor the code into a reusable Jekyll theme: Jekyll Theme Manpage, a cuter version of the classic Linux Manpage.
One of the challenges I faced was updating the theme to work with Sass 1.80.0, which shows this warning:
Warning: @import is deprecated and will be removed in Sass 2.0.0. Use @use instead.
The Challenge
I wanted to create multiple color schemes (skins) that users could:
- Apply without modifying the core theme files
- Support both light and dark mode variants
- Work with modern Sass practices (
@use
instead of@import
)
The File Structure
Here’s how the files work together:
your-jekyll-site/
├── _sass/
│ ├── skins/
│ │ ├── _purple.scss # Default skin
│ │ └── _nord.scss # Another skin
│ ├── _variables.scss # Shared variables
│ └── jekyll-theme-manpage.scss # Main theme styles
├── assets/
│ └── css/
│ └── style.scss # Entry point
└── _config.yml # Theme configuration
1. The Entry Point (style.scss
)
This is where Jekyll starts processing your styles:
---
---
@forward "skins/{{ site.skin | default: 'purple'}}";
@use "variables";
@use "normalize";
@use "jekyll-theme-manpage";
Each line has a purpose:
- Empty front matter tells Jekyll to process this file
@forward
loads skin variables after Liquid processessite.skin
@use
loads and scopes each module’s styles and variables
2. Skin Files (_sass/skins/_*.scss
)
// Base colors
$theme-color: #663399;
$bg-color: #ffffff;
// ... other base variables
// Light mode
:root {
--theme-color: #{$theme-color};
--bg-color: #{$bg-color};
// ... other variables
}
// Dark mode
[data-theme="dark"] {
--theme-color: #{$dark-theme-color};
--bg-color: #{$dark-bg-color};
// ... dark mode overrides
}
Each skin defines CSS custom properties that can be used throughout the theme. The :root
selector sets default (light mode) values, while [data-theme="dark"]
provides overrides for dark mode. We use Sass interpolation (#{$variable}
) to convert Sass variables into CSS custom property values.
3. Variables (_sass/_variables.scss
)
// Breakpoints
$large-breakpoint: 64em !default;
$medium-breakpoint: 42em !default;
// Theme colors (from skin)
$theme-color: var(--theme-color) !default;
$bg-color: var(--bg-color) !default;
// ... other variables
This file creates Sass variables that reference our CSS custom properties. The !default
flag allows these values to be overridden if they’re defined elsewhere, making the theme more customizable. These variables are then used throughout other Sass files.
4. Main Theme (_sass/jekyll-theme-manpage.scss
)
@use "variables" as v;
body {
background-color: v.$bg-color;
color: v.$text-color;
}
// For semi-transparent colors, use modern CSS color syntax
.highlight {
background: rgb(from var(--theme-color) r g b / 0.15);
}
The main theme file contains all core styles and uses the variables defined earlier. We use modern CSS color syntax (rgb(from var())
) because Sass color functions can’t directly manipulate CSS custom properties. The @use
rule namespaces our variables to avoid conflicts.
5. Configuration (_config.yml
)
Users can select their theme:
title: My Jekyll Site
skin: purple # Available: purple, github, nord
Jekyll’s configuration file determines which skin to load through Liquid templating. This value is processed before Sass compilation, allowing users to switch themes by changing a single configuration value without modifying any CSS files.
Optional: Theme Switching
While themes work without JavaScript (based on system preferences), you can add dynamic switching:
// Apply theme to document
const setTheme = (theme) => {
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.style.colorScheme = theme;
};
// Check system preference
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
setTheme('dark');
}
Include it in your layout:
<script src="{{ '/assets/js/theme-switcher.js' | relative_url }}"></script>
Creating New Themes
To create a new theme:
To create a new theme, add a skin file that follows the same structure as the existing ones:
// Define base colors
$theme-color: #your-color;
$bg-color: #ffffff;
:root {
--theme-color: #{$theme-color};
--bg-color: #{$bg-color};
}
[data-theme="dark"] {
--theme-color: #{$dark-theme-color};
--bg-color: #{$dark-bg-color};
}
The :root
and the [data-theme="dark"]
should be copy-paste from the existing theme files so all you need to do is define your colors.
- Update
_config.yml
:skin: mytheme
Summary
- Jekyll processes Liquid templating first (
purple
), selecting the right skin file @forward
makes the skin’s variables available to other files- CSS custom properties allow runtime theme switching
- Modern CSS color syntax enables working with CSS variables in color functions
This approach gives us the best of both worlds: compile-time theme selection through Jekyll’s configuration while maintaining modern Sass practices with @use
.
References: