DEV Community

Seif Ahmed
Seif Ahmed

Posted on

Refactoring Vlox's Theme Engine 🎨

The Architecture:

Most standard theme systems swap a single global class on the <body> element. My engine acts like a blender. It lets themes inherit specific traits from one another. You can inject classes from Theme B, blend them with Theme A, and remove unwanted classes from Theme C by mapping targets.


The Update:

In the past, themes were tracked by index, but reordering the array broke saved themes for existing users.

To fix this, I used unique keys for themes instead of indexes.


The Configuration:

Each unique theme contains an array of configuration objects. Every configuration object contains four keys:

  • class: (Required): The target CSS class name.
  • elements: (Required): Elements targeted immediately on page load.
  • postsComponentElements: (Optional): Elements targeted ONLY after dynamic posts finish loading.
  • action: (Optional): Specifies whether to add or remove the class. Defaults to add.

The Code:

function runThemeEngine(theme, category) {
    if (!Array.isArray(theme)) return;

    for (let rule of theme) {
        if (!Array.isArray(rule[category]) || !rule.class) continue;
        rule[category].forEach(element => {
            if (rule.action === "remove") NS(element).removeClass(rule.class);
            else NS(element).addClass(rule.class);
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

The Execution Logic:

1. Core UI:

This process fires during initial page load. It updates permanent structural layouts.

2. Post Components:

This engine runs at the end of renderPosts() functions. It filters configuration arrays to style elements only after they exist safely.


If you liked Vlox, please consider giving it a 🌟 on GitHub at https://github.com/Hfs2024/Vlox. It means the 🌎 to me!

Top comments (2)

Collapse
 
alexandersstudi profile image
Alexander

Moving to unique keys instead of array indexes is definitely the right call for persisting user preferences without breaking state. The "blender" concept is interesting, though relying on JS to imperatively query and inject classes across the DOM can introduce layout thrashing or flashes of unstyled content as the app scales. Have you considered shifting the blending logic to CSS custom properties scoped to data attributes? Letting the browser natively handle the cascade usually drops the JS overhead to near zero.

Collapse
 
codemaster_121482 profile image
Seif Ahmed • Edited

Hey Alexander!

Thanks for your suggestion, but I avoided this method because it requires you to add inline attributes to every single element you want to style which can become hard to maintain as Vlox scales. Also, there is no flashes or layout trashing as the theme engine executes immediately after the initial page load.