Skip to main content

Ralsina.Me — Roberto Alsina's website

Color Coordination Using Base16

The Problem

A few days ago I wrote about how I moved from a al­l-in­clu­sive en­vi­ron­ment (KDE Plas­ma) to Qtile, a tiling win­dow man­ager, and all the things I did to have the ameni­ties I missed from Plas­ma.

One thing there that may need fur­ther ex­pla­na­tion is the sec­tion about col­or schemes be­cause the con­cepts them­selves are fair­ly un­usu­al.

So, let's dig in­to it a bit more.

This is how a few apps look by de­fault if you don't con­fig­ure things:

unconfigured apps

One is a Qt ap­p, and the oth­er is a GTK app and they look ... bad?

I mean, I don't re­al­ly care all that much, but not on­ly are the wid­get styles to­tal­ly dif­fer­en­t, but the col­ors are all over the place.

And the same hap­pens to Qtile's bar, and my ter­mi­nal (alacrit­ty) and my tmux­er (zel­li­j) and my web brows­er and so on.

Ev­ery­thing is a dif­fer­ent col­or.

In Plas­ma, a comon col­or scheme is en­forced on most apps (not in chrome, though) and it makes things much nicer.

So, what's the equiv­a­lent in the Win­dow Man­ag­er world? There is­n't one, re­al­ly, but there are bits and pieces you can make in­to ... 80% of it.

Here's what I did.

My Solution

First, you need a source of con­sis­tent col­or schemes. If you just re­al­ly, re­al­ly, re­al­ly like a sin­gle one, then they may have a site full of con­fig­u­ra­tions for dif­fer­ent apps to force them to fol­low it.

For ex­am­ple: Drac­u­la or Nord

But I want­ed to be able to try a bunch and see which one I liked.

For this, there is noth­ing like base16

Base16 de­fines a stan­dard. You will have 16 col­ors. Those col­ors mean things.

  • Col­or 0 is the back­ground.
  • Col­or 1 is the fore­ground.

And so on.

Then it de­fines some oth­er things, like "If you are do­ing a 'dark' scheme, col­ors go from dark­er to lighter" and so on.

Then they pro­vide a col­lec­tion of themes, which are each 16 col­ors fol­low­ing those rules.

For ex­am­ple, this is the Bro­gram­mer Theme:

scheme: "Brogrammer"
author: "Vik Ramanujam (http://github.com/piggyslasher)"
base00: "1f1f1f"
base01: "f81118"
base02: "2dc55e"
base03: "ecba0f"
base04: "2a84d2"
base05: "4e5ab7"
base06: "1081d6"
base07: "d6dbe5"
base08: "d6dbe5"
base09: "de352e"
base0A: "1dd361"
base0B: "f3bd09"
base0C: "1081d6"
base0D: "5350b9"
base0E: "0f7ddb"
base0F: "ffffff"

Now, sup­pose you want an app to fol­low the "base 16 stan­dard" to see how it looks in Bro­gram­mer style.

All you need to do is take that ap­p's con­fig file and put the right col­or where it needs it.

So, for ex­am­ple, for the Alacrit­ty ter­mi­nal:

colors:
  # Default colors
  primary:
    background: '0x1b1918'
    foreground: '0xa8a19f'

  # Colors the cursor will use if `custom_cursor_colors` is true
  cursor:
    text: '0x1b1918'
    cursor: '0xa8a19f'

  # Normal colors
  normal:
    black:   '0x1b1918'
    red:     '0xf22c40'
    green:   '0x7b9726'
    yellow:  '0xc38418'
    blue:    '0x407ee7'
    magenta: '0x6666ea'
    cyan:    '0x3d97b8'
    white:   '0xa8a19f'

Of course edit­ing all the con­fig files ev­ery time you want to change your col­or scheme is a pain.

So the base16 project al­so col­lects tem­plates. Those are files that when com­bined with a theme gen­er­ate the con­fig­u­ra­tion file for an ap­pli­ca­tion.

This is the Alacrit­ty tem­plate:

# Base16 {{scheme-name}} - alacritty color config
# {{scheme-author}}
colors:
  # Default colors
  primary:
    background: '0x{{base00-hex}}'
    foreground: '0x{{base05-hex}}'

  # Colors the cursor will use if `custom_cursor_colors` is true
  cursor:
    text: '0x{{base00-hex}}'
    cursor: '0x{{base05-hex}}'

  # Normal colors
  normal:
    black:   '0x{{base00-hex}}'
    red:     '0x{{base08-hex}}'
    green:   '0x{{base0B-hex}}'
    yellow:  '0x{{base0A-hex}}'
    blue:    '0x{{base0D-hex}}'
    magenta: '0x{{base0E-hex}}'
    cyan:    '0x{{base0C-hex}}'
    white:   '0x{{base05-hex}}'

See those bits like {{base05-hex}}? That one gets replaced with your theme's color 5.

But again, us­ing the tem­plate for each app you want to theme is bor­ing.

So you need a tool to do that. The one I use is called flavours

What flavours does is:

  • Get all the base16 col­or themes
  • Get all the base16 app con­fig tem­plates
  • Fol­low­ing a con­fig­u­ra­tion file, gen­er­ate all the con­fig files you need.
  • Op­tion­al­ly: run com­mands so the apps no­tice their con­figs have changed.

For ex­am­ple, this is my con­fig­u­ra­tion for Alacrit­ty:

[[items]]
file = "~/.config/alacritty/alacritty.yml"
template = "alacritty"
subtemplate = "default-256"
rewrite = false

It says:

  • Generate ~/.config/alacritty/alacritty.yml
  • Use the alacritty template
  • From that template use the version called default-256 (don't worry)
  • DO NOT RECRE­ATE THE WHOLE FILE

That last bit is im­por­tan­t. That file does­n't just have the the­me, it has a lot of oth­er im­por­tant stuff, so I don't want it to just have the theme in it.

So, I had to ed­it it once and put these lines be­fore and af­ter where the theme goes:

# Start flavours
... theme goes here
# End flavours

So when I use flavours to apply a theme it will only replace that bit and leave the rest.

Since alacritty notices when the config has changed, I don't need a hook entry. In other cases you can use it. Here's mine for qtile, to let it know it should reread its config:

hook = "killall -USR1 qtile"

So, I configured this for a bunch of things, and at this point, I can just run something like flavours apply atelier-forest and ...

color coordinated apps

Yeah, they are not per­fec­t. I still need to tweak some stuff, but it's get­ting there.

Cur­rent­ly my flavours con­fig­u­ra­tion co­or­di­nates the­se:

  • Alacrit­ty
  • Qtile
  • Zel­lij
  • Rofi
  • Qt
  • Gtk (us­ing Flat­col­or)
  • VS Code
  • Qute­Brows­er

That's rough­ly ev­ery app I use (yes, I am mi­grat­ing from Chrome to Qute­Brows­er for no good rea­son)

And be­cause I am not ok, I wrote a cou­ple of tiny things to make things eas­i­er for me.

A rofi-based theme pick­er called rofi-base16:

rofi-base16 in action

And a base 16 tem­plate for Zel­li­j.

I al­so wrote an ug­ly script to set VS Code's theme but it's shame­ful, so will not be shown here.

Hope­ful­ly this ex­plains some­thing to some­one. If it does­n't, well, it will help me when I in­evitably for­get how this works :-)


Contents © 2000-2024 Roberto Alsina