super-jss
v1.0.0-beta.22
Published
Super JavaScript Stylesheets for Angular 20 — atomic CSS-in-JS using Signals with responsive breakpoints and theming.
Maintainers
Readme
Super JSS — Atomic CSS‑in‑JS for Angular 20
Ship less CSS. Style with Signals. Theme everything at runtime.
Super JavaScript Stylesheets (SJSS) is a tiny, runtime styling library for Angular 20. It generates atomic CSS as you use it, supports responsive breakpoints and theming, and gives you a minimal, ergonomic API.
- ⚡ Angular‑native: built on Signals
- 🎯 Atomic CSS generation: only what you use
- 📱 Responsive + theming:
xs…xxlbreakpoints and palette tokens - 🎨 Pseudo‑selectors:
&:hover,&:focus, etc. - 🧩 Ready‑made building blocks:
<sj-paper>,<sj-card>,<sj-button>
60‑second start
- Install
npm install super-jss- Use a standalone component (Angular 20)
import { Component } from '@angular/core';
import { SjDirective, SjButtonComponent, sj } from 'super-jss';
@Component({
selector: 'hello-sjss',
standalone: true,
imports: [SjDirective, SjButtonComponent],
template: `
<div [sj]="[ sj.display('flex'), sj.gap({ xs: 0.5, md: 1 }) ]">
Hello SJSS
</div>
<sj-button [usePaint]="'primary'">Action</sj-button>
`,
})
export class HelloSjssComponent {
// Expose the root API to the template
readonly sj = sj;
}Responsive sugars at a glance
usePadding,useGapare density‑driven responsive sugars sourced from your theme. Aliases map to density levels:compact→ 1,default→ 2,comfortable→ 3,spacious→ 4- Each density resolves to a responsive object you define in the theme, e.g.
components.surfaces.padding[1] = { xs: 0.5, md: 0.75, lg: 1 } - That means writing
usePadding="compact"expands to{ xs, md, lg }automatically at runtime.
usePaintis palette‑aware: it applies background/border/text using theme tokens and the component variant (filled,outlined,flat) with auto‑contrast defaults.
Example — a fully theme‑responsive surface in one line:
<sj-paper
variant="outlined"
usePadding="compact"
useRounded="default"
[usePaint]="'primary'"
>
Themed surface
</sj-paper>Try it live:
Quick links
- Docs
- Live Demo — theme editor in action
- Storybook — component reference
- StackBlitz · sjRootApi
- StackBlitz · Padding & Flex
- StackBlitz · Palette
- StackBlitz · Typography
- StackBlitz · Spacing
- StackBlitz · Padding System
- StackBlitz · Colors (theme.colors)
- GitHub
Why SJSS (in 30 seconds)
- Angular‑native, powered by Signals; no build‑time plugin required.
- Atomic CSS at runtime: ship only what you use.
- Token‑driven theming with responsive objects on every property.
- Tiny API: write plain CSS (or shorthands) as TypeScript objects.
Compare at a glance
| Library | Type | Theming/Tokens | Angular 20 | Notes | |-------------------|----------------------|------------------------|------------|------| | Tailwind CSS | Utility framework | Limited via config | Generic | Build‑time, globals | | Angular Material | Component library | Material tokens | Yes | Heavy components, prescriptive UI | | PrimeNG | Component library | Theme packs | Yes | Large bundle, theming via CSS vars | | MUI (React) | Component library | Rich theming (React) | No | React‑only | | SJSS | Styling library | Tokens + responsive API| Yes | Atomic CSS‑in‑JS, Signals‑native |
Install
npm install super-jssQuick start
A quick visual of SJSS authoring with strict typing and autocomplete:
Key ideas
- camelCase CSS properties:
backgroundColor,justifyContent,borderRadius - Responsive objects:
{ xs: 1, md: 2 } - Theme tokens:
sj.palette.primary.main,sj.palette.light.dark - Pseudo‑selectors:
sj.hover({ ... }),sj.focus({ ... })
Minimal API surface (v1)
The root API gives you two things:
- Any CSS property function
- A few curated shorthands with
.options
import { sj } from 'super-jss';
// CSS properties
sj.backgroundColor('primary.main');
sj.padding({ xs: 1, md: 2 });
sj.width(sj.width.options.fitContent);
sj.position(sj.position.options.absolute);
// Shorthands (popular)
sj.p(2); // padding
sj.m({ md: 1 }); // margin
sj.bg('primary.main');
sj.c('primary.contrast');
// Discoverable options for common props
sj.display.options; // { flex, grid, block, inline, inlineBlock, contents, none }
sj.flexDirection.options; // { row, rowReverse, column, columnReverse }
sj.justifyContent.options; // { flexStart, flexEnd, center, spaceBetween, spaceAround, spaceEvenly }
sj.alignItems.options; // { flexStart, flexEnd, center, stretch, baseline }
sj.width.options; // { auto, fitContent, maxContent, minContent }
sj.height.options; // { auto, fitContent, maxContent, minContent }
sj.position.options; // { static, relative, absolute, fixed, sticky }
// Tokens available at root
sj.palette.primary.main;
sj.breakpoints.md;Responsive examples
<div
[sj]="[
sj.display('flex'),
sj.flexDirection({ xs: 'column', md: 'row' }),
sj.gap({ xs: 0.5, md: 1 }),
]"
></div>Surfaces (density‑driven spacing)
Use <sj-paper> for neutral surfaces and enable consistent padding and rounding via density levels sourced from your theme.
Define densities in theme (TypeScript):
// Align surfaces globally via the active theme
theme.setTheme({
components: {
surfaces: {
padding: { 2: { xs: 0.5, md: 0.75, lg: 1 } },
gap: { 2: { xs: 0.5, md: 0.75, lg: 1 } },
radius: { 2: 0.5 }
}
}
});Use in templates (HTML):
<!-- Component form: padding+gap+rounded by density -->
<sj-paper variant="outlined" usePadding="default" useRounded="default">
Content
</sj-paper>
<!-- Individual toggles (still density‑driven) -->
<sj-paper variant="outlined" usePadding="default">…</sj-paper>
<sj-paper variant="outlined" useRounded="default">…</sj-paper>Host mode (apply surface to the parent element):
<div>
<sj-paper host usePadding="default" useRounded="default">
Content
</sj-paper>
</div>Notes
- Densities live under
theme.components.surfaces(padding, gap, radius) and use your theme.spacing units. [sj]merges last; explicit overrides always win.
FAQ
Q: Why this approach vs. utility frameworks or huge token bags?
A: SJSS generates only the atomic CSS you actually use, at runtime. No prebuilt megabundle. You write plain CSS properties, enhanced with .options for discoverability. Compared to utility-first CSS, you: (1) keep styling colocated with your component logic, (2) get type‑safe, theme‑aware values, and (3) ship less. Compared to heavy design-token bags, we keep only the essentials at root: sj.palette and sj.breakpoints.
Q: How do I maintain theming long-term?
A: Use semantic palette tokens everywhere ('primary.main', 'light.dark'). Centralize your theme in one place (theme service/config). Because styles reference semantic tokens, swapping a palette or adjusting contrast cascades automatically without touching components. Prefer semantic tokens over raw hex in app code.
Q: What’s the responsive story?
A: Every property supports responsive objects: { xs, sm, md, lg, xl, xxl }. This keeps responsive intent in one place per style. Example: sj.flexDirection({ xs: 'column', md: 'row' }) and sj.gap({ xs: 0.5, md: 1 }).
Q: Is it SSR‑friendly and fast? A: Yes. The library avoids direct DOM access during import and only generates minimal, deterministic atomic classes at runtime. Styles are memoized, deduped, and composed; pseudo‑selectors are compiled into atomic rules and reused. Result: tiny CSS, predictable ordering, and quick first paint.
Q: How do I discover valid values fast?
A: Use .options on common props: sj.display.options, sj.flexDirection.options, sj.justifyContent.options, sj.alignItems.options, sj.width.options, sj.height.options, sj.position.options. Your IDE will autocomplete ergonomic aliases like spaceBetween, flexStart, etc.
Q: Can I mix literal values with tokens?
A: Absolutely. Use literals where convenient ('fit-content', '1fr 2fr', 600) and tokens for theme consistency ('primary.main', 'neutral.contrast').
Q: How do I center with flex quickly?
A: sj.display(sj.display.options.flex), sj.justifyContent(sj.justifyContent.options.center), and sj.alignItems(sj.alignItems.options.center). That’s it.
💖 Support
If you find Super JSS useful, consider supporting its development:
- ☕ ☕ ☕ Buy me a coffee
📬 Contact
For inquiries, feedback, or issues, reach out at [email protected].
License
MIT © Ricardo Santoyo
