Skip to main content

Command Palette

Search for a command to run...

SnapCSS — A Runtime CSS Engine

Updated
•6 min read•View as Markdown

SnapCSS — A Runtime CSS Engine

A utility-first CSS engine that works entirely at runtime.
No build step. No compilation. No tooling required.


Why I Built SnapCSS

Modern frontend styling systems are powerful, but they often depend on an entire build pipeline before you can write a single class.

For quick prototypes, experiments, browser-based projects, or lightweight applications, that setup can feel unnecessarily heavy.

I wanted something simpler:

  • Write utility classes directly in HTML

  • Load one script

  • Start styling instantly

  • No compilation step required

That idea became SnapCSS.

What Is SnapCSS?

SnapCSS is a runtime CSS engine.

Instead of generating stylesheets ahead of time, SnapCSS scans your DOM at runtime, resolves utility class names into style objects, and applies those styles directly in the browser.

Depending on the feature, styles are applied using:

  • Inline styles

  • Dynamically injected CSS rules

The result is a lightweight utility-first styling system that works entirely in the browser.

Usage

CDN — Zero Tooling

<script src="https://unpkg.com/@visshnnu-tejaa/snapcss/dist/snapcss.min.js"></script>

<div class="p-8 bg-cyan-500 text-white rounded-xl shadow-lg hover:bg-violet-500">
  Works instantly. No build step.
</div>

npm — Framework Support

npm install @visshnnu-tejaa/snapcss
import { init, setDarkMode } from '@visshnnu-tejaa/snapcss';

init();

Feature Walkthrough

1. Utility Classes

SnapCSS supports a wide range of utility classes including:

  • Spacing

  • Layout

  • Typography

  • Colors

  • Flexbox

  • Grid

  • Borders

  • Shadows

  • Opacity

  • Overflow

  • Transforms

  • Transitions

  • Positioning

  • Z-index

<div class="flex items-center gap-4 p-6 bg-white rounded-2xl shadow-md">
  <span class="text-lg font-bold text-gray-800">
    SnapCSS
  </span>
</div>

2. Responsive Breakpoints

SnapCSS uses a ResizeObserver to monitor viewport changes in real time.

When a breakpoint threshold is crossed, matching responsive utilities are automatically applied or removed.

Supported Breakpoints

Prefix Width
sm: 640px
md: 768px
lg: 1024px
xl: 1280px
2xl: 1536px
<div class="p-4 sm:p-6 md:p-8 lg:p-12 bg-white md:bg-blue-500 lg:bg-green-500">
  Responsive padding and color
</div>

3. Dark Mode

SnapCSS injects CSS rules for every unique dark: utility into a shared <style> tag.

Dark mode can then be toggled globally using:

import { setDarkMode } from '@visshnnu-tejaa/snapcss';

setDarkMode(true);   // Enable dark mode
setDarkMode(false);  // Disable dark mode
setDarkMode(null);   // Follow OS preference
<div class="bg-white dark:bg-gray-900 text-black dark:text-white p-6">
  Adapts to dark mode
</div>

4. State Variants

Interactive state modifiers are powered using native DOM event listeners.

Supported variants include:

  • hover:

  • focus:

  • focus-visible:

  • active:

SnapCSS dynamically applies and removes styles based on user interaction.

<button class="bg-blue-500 hover:bg-blue-700 active:scale-95 text-white px-4 py-2 rounded-lg">
  Click me
</button>

5. Group Hover

SnapCSS supports parent-triggered child styling using:

  • group

  • group-hover:

<div class="group p-4 bg-gray-100 rounded-xl">
  <p class="text-gray-500 group-hover:text-violet-600 transition-colors">
    I change when the parent is hovered
  </p>
</div>

6. Structural Modifiers

Style elements based on DOM position using:

  • first:

  • last:

  • odd:

  • even:

<ul>
  <li class="p-2 first:font-bold last:text-gray-400 odd:bg-gray-50">
    Item
  </li>

  <li class="p-2 first:font-bold last:text-gray-400 odd:bg-gray-50">
    Item
  </li>

  <li class="p-2 first:font-bold last:text-gray-400 odd:bg-gray-50">
    Item
  </li>
</ul>

7. Space Utilities

Utilities like space-x-* and space-y-* automatically apply spacing between sibling elements.

<div class="flex space-x-4">
  <div class="w-10 h-10 bg-red-400 rounded"></div>
  <div class="w-10 h-10 bg-green-400 rounded"></div>
  <div class="w-10 h-10 bg-blue-400 rounded"></div>
</div>

8. Dynamic DOM Support

SnapCSS automatically watches for new DOM nodes using a MutationObserver.

This allows dynamically rendered UI components to work immediately without rescanning or re-initialization.

function Card({ title }) {
  return (
    <div class="p-6 bg-white rounded-xl shadow-md hover:shadow-lg transition-shadow">
      {title}
    </div>
  );
}

9. Custom Themes

SnapCSS supports theme extension during initialization.

import { init } from '@visshnnu-tejaa/snapcss';

init({
  theme: {
    colors: {
      brand: {
        500: '#7C6CF2',
        600: '#6B5CE7',
      },
    },
  },
});

You can then use custom utilities anywhere:

<div class="bg-brand-500 text-white">
  Custom themed color
</div>

How SnapCSS Works Internally

The engine is divided into focused modules:

Module Responsibility
parser Parses utility class names
resolver Resolves utilities into style objects
applier Applies styles to DOM elements
scanner Performs the initial DOM scan
observer Watches for dynamically added elements
darkmode Handles dark mode rule injection
responsive Handles responsive breakpoints
states Manages interaction states
group Implements group-hover behavior
structural Handles first/last/odd/even logic
cache Memoizes resolved utilities

The Parsing System

One of the most interesting parts of SnapCSS is the parser.

A class like:

sm:hover:bg-violet-500

is tokenized left-to-right.

The engine extracts modifier chains:

  • sm → responsive modifier

  • hover → interaction modifier

The remaining tokens:

bg violet 500

are resolved into a final style object:

{
  backgroundColor: '#8b5cf6'
}

Architecture Decisions

Why Inline Styles?

Inline styles apply immediately and avoid stylesheet generation overhead.

They also simplify runtime style application because styles can be written directly to the target element.

Why Inject CSS for Dark Mode?

Dark mode requires global toggling behavior.

Injecting CSS rules once and toggling a single html.dark class is significantly more efficient than recalculating every dark-mode element individually.

Why Use ResizeObserver?

Responsive utilities in SnapCSS are controlled through JavaScript.

A ResizeObserver provides real-time viewport updates that the runtime engine can react to instantly.

Why Use MutationObserver?

Modern applications frequently create and destroy DOM nodes dynamically.

The observer ensures new elements are styled automatically without requiring manual rescans.

Try SnapCSS

Install via npm

npm install @visshnnu-tejaa/snapcss

CDN

<script src="https://unpkg.com/@visshnnu-tejaa/snapcss/dist/snapcss.min.js"></script>

Final Notes

SnapCSS is actively maintained and continuously evolving.

Built with:

  • TypeScript

  • tsup

Published on:

  • npm

Licensed under MIT.