Dynamic Tints with CSS and Kotlin/JS
publicobject.com
Friday, January 30, 2026
I’ve been trying to build a remarkable UI for Rounds.app. One feature that turned out quite well is tinting the game name & menu bar icons when the winner changes.In this recording you can see colors change when I toggle the win condition:The title color changes when the winner changesI’ve go...
I’ve been trying to build a remarkable UI for Rounds.app. One feature that turned out quite well is tinting the game name & menu bar icons when the winner changes.
In this recording you can see colors change when I toggle the win condition:

I’ve got a two CSS classes, tinted and tintedDefault for the game name. I’m using a CSS transition to animate color changes:
.tinted {
transition: color 300ms linear;
}
.tintedDefault {
color: #ffffff;
}
By using a CSS class, any element that’s declared as tinted will automatically receive tints. For example, the title:
<div class="title tinted tintedDefault">Calico</div>Next I need to dynamically add a CSS rule. I’m using Kotlin/JS so it’s easy to hook up the adoptedStyleSheets API:
private var adoptedStyleSheet: CSSStyleSheet? = null
set(value) {
field = value
val array = js("[]")
if (value != null) {
array.push(value)
}
document.asDynamic().adoptedStyleSheets = array
}To call it, I build a stylesheet rule from a string:
val colorOrDefault = color ?: Colors.DefaultThemeColor
val cssStyleSheet: CSSStyleSheet = js("""new CSSStyleSheet()""")
cssStyleSheet.insertRule(
rule = """
.tinted {
color: ${colorOrDefault.css()} !important;
opacity: 1 !important;
}
""",
index = 0,
)
adoptedStyleSheet = cssStyleSheetUsing !important is important here; it ensures the dynamic tint takes precedent over the default one.
I remove the tint after a 1,500 ms delay:
resetJob = scope.launch {
delay(duration)
adoptedStyleSheet = null
}That’s enough to tint the text, but I need another trick to tint the SVG icons. The easiest way I found to recolor an SVG file was a CSS mask. Thankfully my icons are single-color.
<div
class="imageButton tintedBackground tintedBackgroundDefault"
style="mask: url('/assets/bottle40x64.svg'); width: 40px; height: 64px">
</div>Annoyingly, the dynamic color for masks is the background, so I need a second pair of CSS rules:
.tintedBackground {
transition: background-color 300ms linear;
}
.tintedBackgroundDefault {
background-color: #ffffff;
}
And a second dynamic CSS rule:
cssStyleSheet.insertRule(
rule = """
.tintedBackground {
background-color: ${colorOrDefault.css()} !important;
opacity: 1 !important;
}
""",
index = 1,
)The most difficult part of the whole exercise is using restraint. I’m inclined to color everything in bright colors all the time, but that yields a very ugly UI!
Rounds is my free web app for scoring in-person games. Try it out at rounds.app.
Read the full article
Continue reading on publicobject.com
More from publicobject.com

3 minutes ago
Disturbing photos in Epstein files appear to show Andrew on all fours over female sprawled on floor

4 minutes ago
Menschenrechte: Venezuela kündigt Amnestie für politische Häftlinge an
6 minutes ago
They Overpaid Thinking Their Dodge Hellcats Were Rare, The Judge Said That’s On You
7 minutes ago