Skip to content

Custom CSS

Quizzes ship with a small theme that follows your site colours out of the box. You can retune it with a handful of CSS custom properties, or target individual elements directly through stable class names.

All of the bundled CSS lives in a low-priority cascade layer:

@layer starlight-quiz {
/* every bundled rule */
}

Unlayered CSS always beats layered CSS, regardless of specificity. So any rule you write (which is unlayered unless you opt into a layer) wins over the bundled styles without needing !important, even a low-specificity selector like :root. This is what makes the variable overrides below work.

The theme is driven by these --slq-* custom properties. Each one falls back to the matching Starlight colour token, and then to a built-in default for plain Astro projects (with a dark-mode variant via prefers-color-scheme):

Variable Purpose Falls back to
--slq-accent Radio bullet, progress-bar fill, focus --sl-color-accent
--slq-text Body text --sl-color-text
--slq-muted Secondary / muted text --sl-color-gray-3
--slq-bg Quiz background --sl-color-bg
--slq-surface Panel surface (results, progress, intro) --sl-color-gray-6
--slq-border Borders --sl-color-gray-5
--slq-correct Correct-answer text / marker --sl-color-green
--slq-correct-bg Correct-answer background --sl-color-green-low
--slq-correct-high Correct-answer emphasis --sl-color-green-high
--slq-wrong Wrong-answer text / marker --sl-color-red
--slq-wrong-bg Wrong-answer background --sl-color-red-low
--slq-wrong-high Wrong-answer emphasis --sl-color-red-high
--slq-radius Corner radius 0.5rem

Because they resolve to Starlight’s own tokens, quizzes inherit your site theme (including dark mode) with no configuration. The variables are declared on the quiz, results, progress and intro roots, so they cascade to everything inside each component.

Set any of them in your own stylesheet. On :root they apply site-wide:

custom.css
:root {
--slq-accent: #490086;
--slq-radius: 0.25rem;
}

In a Starlight project, add the file to customCss in astro.config.mjs; in plain Astro, import it wherever you import starlight-quiz/styles.

To restyle only some quizzes, scope the override to a wrapper or to the quiz root:

custom.css
/* Only quizzes inside an element with this class */
.exam .sl-quiz {
--slq-accent: #b91c1c;
--slq-radius: 0;
}

For anything the variables don’t cover, target the elements directly. Every part of a quiz carries a stable sl-quiz-* class, and stateful parts gain a --correct / --wrong modifier after submitting. The most useful hooks:

Class Element
.sl-quiz The quiz container (the bordered card)
.sl-quiz-number The auto-numbered “Question N” label
.sl-quiz-title The quiz title heading
.sl-quiz-question The question text
.sl-quiz-fieldset The group wrapping the answers
.sl-quiz-answer A single answer (gains --correct / --wrong)
.sl-quiz-answer-feedback Per-answer feedback text
.sl-quiz-blank A fill-in-the-blank input (gains --correct / --wrong)
.sl-quiz-feedback The overall result message (gains --correct / --wrong)
.sl-quiz-corrections The correct answers shown after a wrong submission
.sl-quiz-content The explanation section revealed after submitting
.sl-quiz-actions · .sl-quiz-reset The button row · the reset button
.sl-quiz-results The results panel (tier modifier --excellent--fail)
.sl-quiz-progress The progress widget (--mobile in the mobile ToC bar)
.sl-quiz-intro The intro panel

For example, to square off answer rows and thicken the correct-answer border:

custom.css
.sl-quiz-answer {
border-radius: 0;
}
.sl-quiz-answer--correct {
border-inline-start: 3px solid var(--slq-correct);
}