Styling¶
Each presentation has its own CSS. You can attach styles either as a raw string or via the kotlinx.css DSL — and you can mix the two on the same presentation.
Raw CSS¶
fun stringCss() {
kslides {
presentation {
css +=
"""
h1 { color: gold; }
.slides { font-family: "Inter", sans-serif; }
"""
markdownSlide { content { "# Gold heading" } }
}
}
}
Anything that's valid CSS works. The string is appended to the presentation's stylesheet verbatim.
Whitespace matters
CSS in kslides content is space-sensitive. If you have a build step that auto-formats generated HTML, exclude the kslides output directory.
kotlinx.css DSL¶
fun dslCss() {
kslides {
presentation {
css {
rule("h1") {
color = Color.deepPink
fontWeight = FontWeight.bold
}
}
markdownSlide { content { "# Pink heading" } }
}
}
}
The DSL is type-safe and refactor-friendly — handy when sharing styles across presentations.
Targeting specific slides¶
Set an id on the slide and write a rule against it:
markdownSlide {
id = "title"
content { "# Hello" }
}
// then
css += """
#title h1 { font-size: 4em; }
"""
htmlSlide exposes classes for the same purpose — see HTML slides.
Font sizes¶
Slide and code font sizes are plain config values — no CSS required. All three cascade from kslides { } → presentation { } → slide, same as any other configuration property:
presentationConfig {
slideConfig {
codeFontSize = "0.60em" // default for all slides
codeWrap = true // wrap long code lines
}
}
markdownSlide {
slideConfig {
fontSize = "34px" // this slide only
codeFontSize = "0.40em"
}
}
fontSize— font size for all content on the slide (any CSS length). Themes size headings inem, so everything scales together.codeFontSize— font size for code blocks (reveal.js's default is0.55em).codeWrap— whentrue, long code lines wrap instead of overflowing horizontally. A slide can setfalseto override a presentation-widetrue.
The generated codeFontSize/codeWrap rules (fontSize renders as an inline style, not a head rule) are emitted into the document head after any presentation css additions, so on an equal-specificity tie the config-driven value wins over legacy hand-written rules.
Code font size¶
reveal.js renders code blocks — Markdown fences, code snippets, and htmlSlide <pre> blocks — at 0.55em relative to the slide. Because the slide canvas is a fixed size, long lines overflow with a scrollbar instead of shrinking to fit. For most cases, codeFontSize above is simpler; override .reveal pre directly when you need a selector the config API doesn't expose.
Every code block¶
Attach the rule to the kslides {} block (or a single presentation {}) so it applies everywhere:
fun globalCodeFont() {
kslides {
// Seeded into every presentation. reveal.js sizes code at 0.55em by default; lower
// ".reveal pre" so long lines fit the slide, or raise it to enlarge all code blocks.
css +=
"""
.reveal pre { font-size: 0.4em; }
"""
presentation {
markdownSlide {
content {
"""
```kotlin
val answer = 42
```
"""
}
}
}
}
}
Lower the value until the widest line fits; raise it to enlarge all code. To keep the rare over-long line inside the window instead of scrolling it, add .reveal pre code { white-space: pre-wrap; }.
One slide only¶
Give the slide an id and scope the rule to it. An id selector (#bigcode pre) outranks the global .reveal pre, so it wins with no !important and independent of order:
fun perSlideCodeFont() {
kslides {
presentation {
// "#bigcode pre" is an id selector, so it outranks the global ".reveal pre" rule and
// only this slide's code is enlarged. No !important needed.
css +=
"""
#bigcode pre { font-size: 0.7em; }
"""
markdownSlide {
id = "bigcode"
content {
"""
```kotlin
val answer = 42
```
"""
}
}
}
}
}
Several slides¶
An id must be unique per page — reveal.js uses it for deep links (#/bigcode) and the slide menu, so the same id can't be reused on two slides. Use a class instead; a class is made to be shared, so one rule styles every slide tagged with it:
fun sharedCodeFont() {
kslides {
// Shrink all code globally...
css +=
"""
.reveal pre { font-size: 0.4em; }
"""
presentation {
// ...then enlarge it on a subset of slides. An id must be unique, but a class can be reused.
// ".reveal .big pre" has two classes, so it outranks the global ".reveal pre" on specificity
// and wins no matter which rule is declared first.
css +=
"""
.reveal .big pre { font-size: 0.7em; }
"""
markdownSlide {
classes = "big"
content {
"""
```kotlin
val first = 1
```
"""
}
}
markdownSlide {
classes = "big"
content {
"""
```kotlin
val second = 2
```
"""
}
}
}
}
}
markdownSlide, htmlSlide, and dslSlide expose classes directly, and slideDefinition accepts a classes argument for the same purpose.
Qualify with .reveal to beat the global rule
A bare .big pre has the same specificity as the global .reveal pre, so the tie is broken by whichever is declared last — reorder the blocks and the override silently stops working. Writing .reveal .big pre (two classes) always outranks .reveal pre, so it wins regardless of order. A single-slide id selector (#bigcode pre) already outranks both and needs no qualifier.