Devs have been trying to avoid CSS for years with inline styles, CSS-in-JS, Tailwind. But they're not enough, these half-measures. Someone had to take it to the next level.
Introducing I Can't Believe It's Not CSS
Styling for developers in denial.
Write your styles as SQL migrations. Apply them, and your styles appear in the browser. Need to undo a design decision? Just roll back with a down migration.
Quick Example
Check out the GitHub repository or install it with npm:
npm install -D i-cant-believe-its-not-css
npx icbincss init
Here's how you style a button:
-- migrations/up/001_init.sql
CREATE TOKEN 'brand/500' VALUE #2266ee;
CREATE SELECTOR btn AS AND(E('button'), C('primary'));
CREATE STYLE SELECTOR btn (
background = token('brand/500'),
color = #fff,
padding = 12px 24px
);
Apply the migration:
npx icbincss migrate up
npx icbincss build
And you get this CSS:
:root {
--brand-500: #2266ee;
}
button.primary {
background: var(--brand-500);
color: #fff;
padding: 12px 24px;
}
What You Can Do
Database Migrations for Styles
Version your styles with up/down migrations. Roll back that questionable design decision from last Tuesday.
npx icbincss migrate create --name=add_buttons
npx icbincss migrate up
npx icbincss migrate down
Query Your CSS with SQL
Because why wouldn't you SELECT your styles?
SELECT * FROM styles WHERE resp_kind = 'media';
SELECT * FROM styles WHERE selector = 'btn';
Use Real Databases
Store your styles in Postgres or SQLite. Open them in your favorite database GUI. Run JOIN queries on your button colors.
npx icbincss db init-postgres --database=my_styles
npx icbincss db sync-sqlite --file=styles.db
Catch Conflicts Before They Ship
Detect specificity issues and shorthand/longhand conflicts:
npx icbincss doctor
# Cross-context overrides for .card (spec 0,1,0) → padding:
# - (global)
# - @media (min-width: 768px)
#
# Shorthand/longhand conflict for .box:
# - border (shorthand) and border-left (longhand) both defined
Framework Integrations
Vite
// vite.config.ts
import { defineConfig } from "vite";
import { icbincssVitePlugin } from "i-cant-believe-its-not-css";
export default defineConfig({
plugins: [icbincssVitePlugin()],
});
// src/main.ts
import "virtual:icbincss.css";
Edits to migrations trigger HMR updates, because you deserve hot-reloading for your SQL.
Next.js
// next.config.mjs
import { withICBINCSS } from "i-cant-believe-its-not-css";
export default withICBINCSS(
{ reactStrictMode: true },
{ outFile: "public/icbincss.css" }
);
Advanced Features
Responsive Design
Media queries, container queries, and feature queries:
ALTER STYLE SELECTOR card
WHERE width >= 768px
SET padding = 24px;
ALTER STYLE SELECTOR sidebar
WHERE container main > 600px
SET display = grid;
ALTER STYLE SELECTOR grid
WHERE supports(display: grid)
SET display = grid;
Cascade Layers
CREATE LAYERS (reset, base, components, utilities);
SET LAYER = components;
CREATE STYLE SELECTOR card (
padding = 16px
);
Keyframe Animations
CREATE KEYFRAMES fade_in (
'0%' ( opacity = 0 ),
'100%' ( opacity = 1 )
);
Font Faces
CREATE FONT_FACE family 'Inter' (
src = url('/fonts/Inter.woff2') format('woff2'),
font_weight = 400
);
Try It Yourself
It compiles to plain CSS with zero runtime overhead. It works with React, Vue, Angular, vanilla HTML. It supports both CommonJS and ESM.
Check out the GitHub repository or read the full documentation.
npm install -D i-cant-believe-its-not-css
Watch the full product release video to see it in action.
Top comments (0)