Introducing Themescura

Towards better tools for user-facing customizations

A few icons of themescura colored in various colors with a overlay of a diagram.

A few icons of themescura colored in various colors with a overlay of a diagram.

What it is

You can also open themescura from the popup at the bottom right corner.

Before reading the post, try to customize the look so that it matches your taste. Remember, this post is only as beautiful as you can make it, which also applies to the entire site.

Fear not, you can visit the customize page for a Guide on what the controls represent.

Also, you can test out themes from the Showcase:

Mellowed

Glitch Pop

Gitpup

PrePub

Solarized

Clayprint

Crayons on Walls

Stein

Delta Synchronotron

Motivation

I have always loved customization. I was introduced to its true form with Linux.

On linux, instead of a default interface, there are several “flavors” of desktop enviornments, different takes on how apps are launched, files are navigated, app windows handled, etc. 1

A linux user got choice. They could choose which interface or system worked the best for them, or mould those that came near. And if none did, they had the freedom to create one. No interface was considered “better” just because it was the default one. Which meant that people could explore alternatives. The customizations were usually dependent on the GUI frameworks. And it came at the cost of time and effort.

Here on the web, a lot can be styled and in a lot of ways. Sadly, things are usually styled once. Basic dark mode is offered by those who can add one, otherwise the style of a webpage is rather static. Evolving only with time.

There are sites that offer themes to customize the appearance, including some that allow changing the main color. Some web apps like slack allow changing a bunch of colors, but the core interface still retains the static styles. There are extensions that apply custom CSS styles to websites, and they are cumbersome to use and require expertise in CSS. There are browsers, four extensions wearing a chromium trenchcoat, that offer “prepackaged” styles via “boosts” 2. Most options for customization on web are offered as a playful tool for the “super-users”.

Furthermore, customization is hard. What looks like a few colors are dozens upon dozens of shades and tints for every border, background, and text, for every active hovered and disabled states 3. There are too many tokens.

When someone begins the path of customization, a lack of understanding of how colors interact makes it hard for them to decide which is the right color. The problem is further exacerbated by the lack of the mapping from a palette to the generated theme’s final variables. If someone wants to change a color they have to change it in all the “tokens”. And with such a large amount of tokens, adding customization becomes insurmountable.

Designers often test out different themes for their designs. Usually their software has features to support themes. However, the complexity of the large amount of colors still persists. There is no way of generating colors dependent on other pre-selected colors. Each shade of each color has to be manually adjusted. Or a plugin has to be used to do this generation for you. Regardless, the theme has a fixed structure, making iterations a hassle.

I found no promising tools, neither in frontend nor in design that would help me define the themes myself in a logical way and didn’t hamper the developer experience. Just even for experimentation no tools existed that were fast and flexible enough. No figma didn’t work either.

The need also arose from the curiosity of how a webpage would look with different colors and fonts. My previous method was to open the developer console and, lo and behold, stare at the same demon of too many tokens XD.

I have bolted together a few chunks of code and a sprinkled a bit of magic to make this first iteration of themescura.

It isn’t the first implementation of the idea, as it was experimented with in different amounts throughout the work I did in the past few years. But it is the first comprehensive implementation.

I also made it so that I could talk about the idea of generative themes while pointing at something that actually works.

Some more “becauses”, in no particular order:

And finally,
Why? Why not?

What it does

Themescura generates variables from a palette. These variables are used to style the interface. It also types the themes of the generated variables, which can be used in the frontend.

The palette is used to generate theme variables.

You, the user, can edit the themes in real time on every page. The palettes and generated css variables are stored locally on the browser so that theme is retained across pages and is applied without loading the editor.

It can be used to:

  1. Explore Style Space
    Test out fonts and color combinations quickly.
  2. Develop Design System
    Once a theme has been selected, a design system can be developed using the generated variables.
  3. Refine Theme
    The theme and the design system are iterated using the same tools. The relationship between the palette and the generated variables can also evolve with time.
  4. Offer User-facing Customizations
    Can be limited to preset themes or allow extended customizations.

How it works

The palette is used to generate theme variables, which are then used to generate css variables and a generated theme object.

Source code: src/components/themeManager & src/theme.ts
Parts of code are linked in relevant places for context.

Everything starts with the palette. The palette consists of base tokens associated with layout and vars specific to dark and light mode.

The palette is used to generate the theme variables. For example, the text color of a button with primary color as background, --primary-contrast, is selected by comparing primary color’s brightness.

The structure of the generated theme can be whatever we want. The generated theme object consists of the set of css variables and their values in the nested object.

We could use this theme object directly to theme our css if we were using css-in-js, however, every time we change this object, the styles have to be regenerated. A better way is to use a generated theme object that instead of values, has just “pointers” to the changing variables. (which are CSS Variables)

The generated css variables are inserted in a single style tag and are later updated via the manager.

Nested themes, themes inside themes, can also be built by setting the variables on the parent that will nest the themed elements. See the demo blocks in Dark Modes post for an example.

As themescura doesn’t depend on any framework to implement the styles in the frontend, it can be used with any website.

It should be obvious that we should not load the theme editor every single time for every single page. We separate the code that is needed for applying the theme css variables and for editing/generating the theme. A small script is used to apply the theme on page load. The editor is loaded lazily when the user opens the popup. The editor is written with SolidJS to piggyback on the reactive state for handling themes.

Where AI
Unfortunately, to the disappointment of several, there is no AI underneath.

What can be improved

A lot honestly.

First there are the bugs. The slight glitch when loading the font. The broken themes of the previously navigated pages revealed on back/forward navigation. The layout shift from different font sizes due to varying base size of font families. The very limited and fixed card types. The lack of contrast between border and surface for nested surfaces.

And then so much could be added.

There could be separate font families for different portions of the website, for example, a heading font and a post content font family.

There could be checks to ensure accessible contrast ratios for the text and background and surface colors.

There could be more intuitive controls for how the colors relate to each other in the form of contrast, saturation and tint etc instead of the five colors.

There could be component specific styles defined in the generated theme similar to card type.

The icons could be thematic. They are fixed for now as it is hard to have a 1:1 icon pack replacements similar to what we have for fonts.

Although typescript helps a lot in css-in-js, using css variables directly results in hard to maintain code, which can be improved by improving the developer tooling for CSS.

Colors could be picked from images. And the image could be set as the page background.

The themes could be pooled in a shared registry, allowing people to share the themes with each other. (The current size of the palette is short enough to be shared just by copy pasting it’s JSON).

User defined preferences/palette could be shared across websites, so the user could theme multiple websites using their preferred palette of colors and fonts.

More importantly there could be an interface for the theme generation: How the Palette effects the generated variables. Preferably in the form of a node graph.

I have planned more features, but I need time to gather feedback and to discuss the idea with others.

So there it is.

Themescura.

What changes

The idea that a website’s theme is static.
The idea that user facing customization is hard.
The idea that to allow customization we need a server.

This is one step of many towards interfaces that make interfaces.


Footnotes

  1. There are themes for linux as well but different “flavors” are themed a little differently.

  2. Although I admit the arc boosts are more thematic and also change the layout in interesting ways (usually hiding the bloated cruft), but they will break with the next version of the website, and it will need the developer of the theme to fix it.

    Also, they are there for only the most popular websites of the internet.
    There is also a nice feature that allows styling the website based on a foreground and the background text.

  3. Variables inserted in the root in dark theme for:
    Github YouTube and Reddit.

    Note the relatively large size of these files

Sooner or later, everything ends.

Comments