Zuri.SASS

Zuri SASS Documentation

A minimal Sass component library inspired by Material Design 3. This is the complete reference — installation, customization, every component and utility.

Introduction

Zuri SASS is a zero-runtime CSS library authored in Sass. It ships a drop-in compiled stylesheet (dist/style.css) plus the Sass source (zuri/) so you can override variables and inherit the mixin toolkit.

The design language follows Material Design 3: token-driven color (light + dark maps), six elevation levels, a seven-step shape scale, and spec-compliant state layers.

  • No JavaScript — pure CSS, works with any framework.
  • Small — ~24 KB minified.
  • Customizable — every color, radius and font is a Sass variable.
  • MIT licensed.

Install

Via npm

npm install zurisass
<link rel="stylesheet" href="node_modules/zurisass/dist/style.css" />

Via Sass source

Use this path if you want to override variables before compile time.

// your-styles.scss
$primary-color: #0a7;
$base-border-radius: 8px;

@import "zurisass/zuri/index";

From the repository

git clone https://github.com/Njoxpy/ZuriSASS
cd ZuriSASS
npm install
npm run build:css    # → dist/style.css + dist/style.min.css
npm run watch        # rebuild on every save

Quick start

Drop class names on your elements.

<!doctype html>
<html>
  <head><link rel="stylesheet" href="dist/style.css" /></head>
  <body>
    <button class="btn">Primary action</button>

    <div class="text-field text-field--outlined">
      <label class="text-field__label" for="email">Email</label>
      <input class="text-field__input" id="email" type="email" />
    </div>

    <div class="elevation-2 shape-md p-4">Raised surface</div>
  </body>
</html>

Project structure

zuri/
├── index.scss             // entrypoint — imports everything below
├── variables/             // $primary-color, spacing, fonts, etc.
├── base/                  // reset + safe-margin
├── theme/                 // color maps, typography, elevation, shape, state-layer
├── components/            // btn, card, header, forms, text-field, tables
├── utilities/             // spacing, flex, display, text alignment
└── responsive/            // breakpoints + respond-to mixin

Theming — overview

Zuri exposes three layers of customization, from coarsest to finest:

  1. Variables — override common tokens like $primary-color, $base-border-radius, $font-stack before importing.
  2. Color maps — override $light-themes and $dark-themes for full M3 palette control.
  3. Theme class — put .light-theme or .dark-theme on a container to switch palettes at runtime.

Variables

Defined in zuri/variables/_variables.scss.

VariableDefaultPurpose
$primary-color#6200eaBrand color for .btn, .fab, focus rings.
$secondary-color#2ecc71Accent color.
$error-color#b00020Error states.
$disabled-color#BDBDBDDisabled text & borders.
$base-border-radius4pxDefault corner radius.
$base-padding0.75remComponent padding unit.
$btn-padding10px 20pxButton padding.
$font-stacksans-serifDefault font family for typography classes.

Override any of these before @import "zurisass/zuri/index";.

Color maps

Two Sass maps drive the whole palette: $light-themes and $dark-themes. Each contains the Material 3 color tokens.

$light-themes: (
  primary: #6200ea,
  on-primary: #ffffff,
  primary-container: #bb86fc,
  on-primary-container: #3700b3,

  secondary: #03dac6,
  on-secondary: #000000,
  ...
  surface: #ffffff,
  on-surface: #000000,
  error: #b00020,
  ...
);

For each key X, Zuri auto-generates:

  • .text-X — sets color.
  • .bg-X — sets background-color.
  • .btn-X — a button variant using X as the background.

So adding a new color token in the map automatically produces all three classes.

Dark mode

Put .dark-theme (or .light-theme) on any container — typically <body> — and the .bg-* / .text-* utilities automatically resolve against the matching color map.

<body class="dark-theme">
  <section class="bg-primary text-on-primary">Hero</section>
</body>

<script>
  // Toggle via JS if you need a user preference
  document.body.classList.toggle("dark-theme");
</script>

Buttons

The default .btn uses $primary-color. Themed variants (.btn-primary, .btn-secondary, .btn-error, …) are generated from the color map.

<button class="btn">Default</button>
<button class="btn-primary text-on-primary">Primary</button>
<button class="btn-secondary text-on-secondary">Secondary</button>
<button class="btn" disabled>Disabled</button>

<!-- Floating action button (fixed bottom-right) -->
<button class="fab">+</button>
ClassUse
.btnDefault filled button.
.btn-<color>One generated per entry in the color map.
.fabCircular floating action button, fixed bottom-right.

Text fields

BEM structure: .text-field with nested __label, __input, __helper, plus modifier classes.

<div class="text-field text-field--outlined">
  <label class="text-field__label" for="email">Email</label>
  <input class="text-field__input" id="email" type="email" />
  <span class="text-field__helper">We never share your email.</span>
</div>
ModifierEffect
.text-field--outlinedOutlined variant (otherwise filled).
.text-field--errorError state — red label, border, helper.
[disabled] on inputDisabled state.

Forms

The base <form> element has theme-aware padding and label styling. Combine with .text-field components for full forms.

<form>
  <label>Name</label>
  <input type="text" />
  <button class="btn">Submit</button>
</form>

Cards

<div class="card">
  <div class="card-image"><img src="product.jpg" alt="" /></div>
  <div class="card-content">
    <div class="card-price"><h2>$50</h2><p>4.9</p></div>
    <p>Product description…</p>
    <div class="card-cta">
      <button>Add to cart</button>
    </div>
  </div>
</div>

Tables

Add .table-content to any <table> for striped rows, header styling, and consistent spacing.

<table class="table-content">
  <thead><tr><td>Name</td><td>Role</td></tr></thead>
  <tbody>
    <tr><td>Jane</td><td>Designer</td></tr>
  </tbody>
</table>

Typography

Material 3 type scale as classes. Apply to any element.

ClassSizeWeight
.headline-196pxlight
.headline-260pxlighter
.headline-348pxnormal
.headline-434pxnormal
.headline-524pxnormal
.headline-620pxmedium
.subtitle-1 / .subtitle-216 / 14pxnormal
.body-1 / .body-216 / 14pxnormal
.caption18pxnormal
.overline10pxnormal

Elevation

Six Material 3 shadow levels. Use the class, or the mixin inside your own components.

<div class="elevation-3">Raised surface</div>
.my-card {
  @include elevation(2);
}

Available levels: elevation-0 (none) through elevation-5 (highest).

Shape

Seven-step corner radius scale.

ClassRadius
.shape-none0
.shape-xs4px
.shape-sm8px
.shape-md12px
.shape-lg16px
.shape-xl28px
.shape-full9999px (pill)
.chip { @include shape(full); }

State layers

Material 3 applies translucent overlays at the spec opacities for hover, focus-visible and pressed states. Use the state-layer mixin on any interactive surface.

.my-button {
  background: $primary-color;
  color: white;
  @include state-layer(#fff);   // overlay color
}

Opacities: hover 8%, focus 12%, pressed 12%.

Spacing utilities

Spacing scale: 0, 1, 2, 3, 4, 5, 6, 8, 10 (where n = n × 0.25rem up to 4, then jumps).

PrefixProperty
p-*padding (all sides)
pt-* / pr-* / pb-* / pl-*padding one side
px-* / py-*padding horizontal / vertical
m-*, mt-* …margin (same pattern)
.mx-autohorizontal centering
gap-*flex/grid gap

Layout utilities

ClassEffect
.d-flex / .d-grid / .d-block / .d-none / .d-inline-flexdisplay values
.flex-row / .flex-colflex-direction
.flex-wrap / .flex-nowrapflex-wrap
.flex-1 / .flex-autoflex shorthand
.justify-start / -center / -between / -around / -endjustify-content
.items-start / -center / -stretch / -endalign-items
.text-left / -center / -righttext-align
.w-full / .w-auto / .h-fullwidth / height
.visible / .invisiblevisibility

Color utilities

Generated from the theme color maps. For every key X:

  • .text-X — e.g. .text-primary, .text-on-surface.
  • .bg-X — e.g. .bg-secondary, .bg-error-container.

Breakpoints

NameMin width
mobile480px
tablet768px
desktop1200px
wide1440px

Also available: .container class with responsive max-width.

Responsive mixins

.hero {
  font-size: 1.5rem;
  @include respond-to(tablet)  { font-size: 2rem; }
  @include respond-to(desktop) { font-size: 3rem; }
}

.mobile-menu {
  @include respond-below(tablet) { display: block; }
}
  • respond-to($name) — min-width query.
  • respond-below($name) — max-width query (exclusive).

Contributing

  1. Fork the repo.
  2. Create a branch: git checkout -b feature/my-component.
  3. Make changes in zuri/. Run npm run watch to rebuild on save.
  4. Add a demo to preview/components.html.
  5. Open a pull request.
Style guide: use BEM for new components (.block__element--modifier). Drive variant classes from the theme color map via @each, not hardcoded colors.

Roadmap

  • Migrate @import → @use / @forward (Sass 2.0 compatibility).
  • Components: checkbox, radio, switch, chip, dialog, snackbar, dropdown, progress, slider.
  • Twelve-column grid system.
  • Icon-button variant.
  • CSS custom-properties build for zero-recompile theming.

Troubleshooting

"gulp: command not found"

Run npm install first. Use npm run build:css instead of calling gulp directly.

Sass deprecation warnings about @import

Expected — migration to @use/@forward is on the roadmap. The @import syntax still works in Sass 1.x.

Custom variables not applying

They must be declared before the library import:

// ✅ correct
$primary-color: #0a7;
@import "zurisass/zuri/index";

// ❌ wrong — library values are already locked in
@import "zurisass/zuri/index";
$primary-color: #0a7;

Changelog

v1.0.0

  • Initial public release.
  • Components: button, FAB, card, header, fixed-header, form, text-field (filled + outlined + error), table.
  • Material 3 systems: elevation, shape, state layers.
  • Utilities: spacing, flex, display, text alignment.
  • Responsive: respond-to / respond-below mixins.
  • Light + dark theme maps with auto-generated color utilities.
  • npm-publishable package — dist/style.css, dist/style.min.css, full Sass source.