Conditionally loading CSS stylesheets in Hugo and loading CSS files as partials is possible.
tl;dr
<style>
tag in your template file, and load Hugo partials inside a media query (or load stylesheet based on a data attribute value)Hugo uses Chroma by default. You can use Prism instead if you want.
Chroma renders the highlighted syntax at build time
PrismJS gives you a lot of flexibility in terms of plugins, themes and portability.
PrismJS renders client side whereas Chroma probably renders at build time. Chroma is probably really good for site performance.
My considerations for using one or the other:
PrismJS has a few neat plugins like treeview
I have been using PrismJS for my sites so far. It’s flexible and extendible.
Chroma renders the highlighted syntax at build time, so i decided to switch
1[markup]
2 [markup.highlight]
3 noclasses = false
1hugo gen chromastyles --style=emacs > layouts/partials/css/syntax-light.css
2hugo gen chromastyles --style=monokai > layouts/partials/css/syntax-dark.css
You can see code samples using different themes here
light = xcode, manni, emacs dark = fruity, dracula, native, rrt, vim
comments should be italic and muted color. it should be different from the color of strings and should not be used for anything else all strings should be a different color
1<style type="text/css" media="screen">
2@media (prefers-color-scheme: dark) {
3 {{ partial "css/syntax-dark.css" . | safeCSS }}
4}
5@media (prefers-color-scheme: light) {
6 {{ partial "css/syntax-light.css" . | safeCSS }}
7}
8</style>
Yes, you can load CSS files as partials. They just need to be in the layout/partials
folder. Using a partial means that the code is included as inline code inside the HTML.
Alternatively, you can set the media
attribute directly on <link>
as well:
1<link
2 rel="stylesheet"
3 href="/css/syntax-light.css"
4 media="screen and (prefers-color-scheme: light)"
5/>
6<link
7 rel="stylesheet"
8 href="/css/syntax-dark.css"
9 media="screen and (prefers-color-scheme: dark)"
10/>
If your theme changes based on a data
attribute, like data-theme="dark"
and not based on the prefers-color-scheme
media query like @media (prefers-color-scheme: dark) {}
, then your code to load the relevant CSS file based on current theme will not work. The issue here is that you need to load both styles from both stylesheets, not one, because the theme can change dynamically any time.
My solution in a scenario like this is to merge your stylesheet into one and use an attribute selector to change my CSS custom properties. See the code below for an example:
1html[data-theme="dark"] {
2 --color-syntax-bg: hsl(231.4, 14.9%, 15%);
3}
4
5html[data-theme="default"],
6html[data-theme="light"] {
7 --color-syntax-bg: hsl(180deg 11% 95%);
8}
9
10/* Background */ .bg { background-color: var(--color-syntax-bg); }
11/* PreWrapper */ .chroma { background-color: var(--color-syntax-bg); }
and then load just a single stylesheet, no conditional loading needed in HTML or JS
1<link rel="stylesheet" href="/css/syntax.css" />