DEV Community

Eyruz Badalzada
Eyruz Badalzada

Posted on

The Gap Tailwind Never Closed — and Why I Built FrontAlign to Fill It

Every large frontend codebase eventually hits the same wall.

You start with a utility CSS framework because it's fast. Then you need interactive components, so you pull in a headless behavior library. Then you need lifecycle management for dynamically rendered content, so you wire up your own MutationObserver and IntersectionObserver logic. Then you need the same design system to work across a Next.js marketing site, a Vue dashboard, and a legacy admin panel — and suddenly "just add Tailwind" has turned into three dependency trees, three mental models, and a slow leak of event listeners nobody remembers attaching.

That gap — between styling tools and an actual UI engine — is what I built FrontAlign to close.

It's not "another CSS framework"

FrontAlign bills itself as a UI engine, and the distinction is deliberate. It combines four things that are normally separate packages into one coherent system:

  • a design-token-driven CSS foundation
  • a utility-first layout layer
  • theme-aware styling (dark mode included)
  • an intelligent JavaScript runtime with lifecycle management

The guiding principle is simple: static interfaces should stay CSS-first, interactive interfaces should initialize intelligently, and dynamic interfaces should stay predictable without hand-rolled observer code.

Where the architecture actually earns its keep

FrontAlign splits cleanly into three layers — a CSS foundation, a JavaScript runtime, and a Compiler/JIT engine — each with one job. That separation is what lets it scale in ways a pure utility library can't.

1. Zero-dependency by design

The CSS layer and the runtime are bound together natively, with no external packages sitting underneath. In a large codebase, that matters more than it sounds — every extra dependency in a UI layer is another version to pin, another breaking change to absorb, another thing that can conflict with your bundler.

2. One token system, not one-off overrides

Colors, spacing, radius, shadows, and component states are all driven by semantic CSS custom properties defined at the root:

:root {
  --primary: var(--blue-600);
  --danger: var(--red-500);
  --success: var(--green-500);
  --space-md: 1rem;
  --radius-2: 0.5rem;
}
Enter fullscreen mode Exit fullscreen mode

Dark mode isn't a second stylesheet — it's the same tokens redefined under a [fa-theme="dark"] attribute. Every button, form, modal, and navbar picks up the change automatically, because they were never hardcoded to a color in the first place.

3. Components that don't leak

This is the part most utility-CSS setups quietly get wrong. FrontAlign's runtime splits components into two categories:

  • Delegated components (navbar, dropdown, accordion, collapse, alert, drawer, form) register a handful of listeners once, at the document level, using event delegation — so elements added later just work without extra wiring.
  • Auto-loaded components (swiper, tabview, toast, popover, lazy images) are watched with IntersectionObserver and initialize only when they actually enter the viewport.

On top of that, a MutationObserver watches for nodes inserted after page load — CMS content, client-rendered sections, tab panels that mount late — and automatically brings new fa-component elements into the same lifecycle. When you're done with an instance, fa.dispose() tears down every observer, listener, and delegated module it registered. No manual cleanup, no leaked handlers.

const fa = new FrontAlign();

// later, e.g. on route change in an SPA
fa.dispose();
Enter fullscreen mode Exit fullscreen mode

4. One contract, every stack

The same class names, fa-component attributes, and runtime model work identically whether you're dropping FrontAlign in via CDN on a static page or importing it into React, Next.js, Vue, or Astro:

import { useNavbar, useModal } from "frontalign/react";

export default function App() {
  useNavbar();
  useModal();
  return <div>...</div>;
}
Enter fullscreen mode Exit fullscreen mode

For teams maintaining UI across multiple stacks — which is most teams past a certain size — that consistency is the actual unlock. You're not maintaining three different mental models of what a "modal" is.

Where this fits next to Tailwind

Tailwind solved utility-first styling extremely well, and FrontAlign isn't trying to out-utility it. The gap is everything around the CSS: component behavior, DOM lifecycle, and cleanup. Reaching for Tailwind usually means also reaching for a separate headless behavior library and writing your own observer/cleanup code for anything dynamic. FrontAlign folds those into the same package, under the same token system, so you're maintaining one contract instead of stitching three together.

Try it

npm install frontalign
Enter fullscreen mode Exit fullscreen mode
import "frontalign/css";
import { FrontAlign } from "frontalign";

const fa = new FrontAlign();
Enter fullscreen mode Exit fullscreen mode

It's MIT-licensed and actively maintained. If you're maintaining a UI layer that's outgrown "just utility classes," I'd genuinely like your feedback — issues and stars on GitHub help more than anything else at this stage.

Top comments (0)