cursery.nixDocs

Styling

Apps style elements with scoped classes from <web/style>, and the page with global styles.

Scoped styles#

css turns CSS into a class. Attach it with class:

src/app/default.nix
let
  inherit (import <web/dom>) html;
  inherit (import <web/style>) css;

  # The body of the class's rule, with native CSS nesting.
  card = css ''
    padding: 1rem;
    border-radius: 0.5rem;

    &:hover {
      background: var(--surface-hover);
    }

    @media (width < 40rem) {
      padding: 0.5rem;
    }
  '';
in
{
  render = _: html.div { class = card; } "Hello";
}

Styles can also select each other, and image makes CSS images from SVG. See <web/style>.

Combine classes#

class takes a list of styles and strings. null adds nothing, for conditional classes:

Classes
html.div { class = [ card "shadow-md" (if active then selected else null) ]; } "Hello"

Global styles#

An app's styles is CSS for the whole page:

src/app/default.nix
{
  styles = ''
    :root {
      --surface-hover: #f4f4f5;
    }

    body {
      margin: 0;
      font-family: system-ui, sans-serif;
    }
  '';
}

Other styling tools#

Optionally, other tools can style the page too, through stylesheets the server entry links. For example, install Tailwind with its Vite plugin:

$ pnpm add -D tailwindcss @tailwindcss/vite
vite.config.js
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [cursery({ /* ... */ }), tailwindcss()],
});

Point it at the app's Nix files:

src/app.css
@import "tailwindcss";
@source "./app";

Link the stylesheet from the server entry:

src/page.nix
(html.head [
  (html.link { rel = "stylesheet"; href = "/src/app.css"; })
  assets
])

Utility classes go in class as strings. Scoped styles are in @layer components and global styles in @layer base, so utilities override both.