coss.com Svelte

Styling

Configure COSS color, radius, typography, and overlay tokens with Tailwind CSS v4.

Overview

This library is optimized for specific semantic color tokens that provide crisp, contrasted borders and visual depth. The styling system builds on shadcn-svelte’s CSS-variable approach for consistency and maintainability.

Components use translucent borders instead of solid colors. Those borders mix with small bottom shadows to stay crisp even when the background lacks contrast.

The color system is optional, but it provides the intended visual result. Conventional tokens may produce borders and shadows with different contrast.

The Svelte orange #ff3e00 belongs to this documentation site’s navigation and links. It is not a component token. Installed components keep the neutral COSS theme shown below.

Installation

See Get Started for installation with the shadcn-svelte CLI. To add the theme manually, paste these tokens into the Tailwind stylesheet imported by your root layout.

@custom-variant dark (&:is(.dark *));

@theme inline {
  --font-sans: var(--font-sans);
  --font-heading: var(--font-sans);
  --font-mono: var(--font-mono);
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-info: var(--info);
  --color-info-foreground: var(--info-foreground);
  --color-success: var(--success);
  --color-success-foreground: var(--success-foreground);
  --color-warning: var(--warning);
  --color-warning-foreground: var(--warning-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --color-sidebar: var(--sidebar);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-ring: var(--sidebar-ring);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --animate-skeleton: skeleton 2s -1s infinite linear;

  @keyframes skeleton {
    to {
      background-position: -200% 0;
    }
  }
}

:root {
  --radius: 0.625rem;
  --background: var(--color-white);
  --foreground: var(--color-neutral-800);
  --card: var(--color-white);
  --card-foreground: var(--color-neutral-800);
  --popover: var(--color-white);
  --popover-foreground: var(--color-neutral-800);
  --primary: var(--color-neutral-800);
  --primary-foreground: var(--color-neutral-50);
  --secondary: --alpha(var(--color-black) / 4%);
  --secondary-foreground: var(--color-neutral-800);
  --muted: --alpha(var(--color-black) / 4%);
  --muted-foreground: color-mix(in srgb, var(--color-neutral-500) 90%, var(--color-black));
  --accent: --alpha(var(--color-black) / 4%);
  --accent-foreground: var(--color-neutral-800);
  --destructive: var(--color-red-500);
  --destructive-foreground: var(--color-red-700);
  --info: var(--color-blue-500);
  --info-foreground: var(--color-blue-700);
  --success: var(--color-emerald-500);
  --success-foreground: var(--color-emerald-700);
  --warning: var(--color-amber-500);
  --warning-foreground: var(--color-amber-700);
  --border: --alpha(var(--color-black) / 8%);
  --input: --alpha(var(--color-black) / 10%);
  --ring: var(--color-neutral-400);
  --sidebar: var(--color-neutral-50);
  --sidebar-foreground: color-mix(in srgb, var(--color-neutral-800) 64%, var(--sidebar));
  --sidebar-primary: var(--color-neutral-800);
  --sidebar-primary-foreground: var(--color-neutral-50);
  --sidebar-accent: --alpha(var(--color-black) / 4%);
  --sidebar-accent-foreground: var(--color-neutral-800);
  --sidebar-border: --alpha(var(--color-black) / 6%);
  --sidebar-ring: var(--color-neutral-400);
}

.dark {
  --background: color-mix(in srgb, var(--color-neutral-950) 96%, var(--color-white));
  --foreground: var(--color-neutral-100);
  --card: color-mix(in srgb, var(--background) 98%, var(--color-white));
  --card-foreground: var(--color-neutral-100);
  --popover: color-mix(in srgb, var(--background) 96%, var(--color-white));
  --popover-foreground: var(--color-neutral-100);
  --primary: var(--color-neutral-100);
  --primary-foreground: var(--color-neutral-800);
  --secondary: --alpha(var(--color-white) / 4%);
  --secondary-foreground: var(--color-neutral-100);
  --muted: --alpha(var(--color-white) / 4%);
  --muted-foreground: color-mix(in srgb, var(--color-neutral-500) 90%, var(--color-white));
  --accent: --alpha(var(--color-white) / 4%);
  --accent-foreground: var(--color-neutral-100);
  --destructive: color-mix(in srgb, var(--color-red-500) 90%, var(--color-white));
  --destructive-foreground: var(--color-red-400);
  --info: var(--color-blue-500);
  --info-foreground: var(--color-blue-400);
  --success: var(--color-emerald-500);
  --success-foreground: var(--color-emerald-400);
  --warning: var(--color-amber-500);
  --warning-foreground: var(--color-amber-400);
  --border: --alpha(var(--color-white) / 6%);
  --input: --alpha(var(--color-white) / 8%);
  --ring: var(--color-neutral-500);
  --sidebar: color-mix(in srgb, var(--color-neutral-950) 97%, var(--color-white));
  --sidebar-foreground: color-mix(in srgb, var(--color-neutral-100) 64%, var(--sidebar));
  --sidebar-primary: var(--color-neutral-100);
  --sidebar-primary-foreground: var(--color-neutral-800);
  --sidebar-accent: --alpha(var(--color-white) / 4%);
  --sidebar-accent-foreground: var(--color-neutral-100);
  --sidebar-border: --alpha(var(--color-white) / 5%);
  --sidebar-ring: var(--color-neutral-400);
}

Font Variables

Components use three font variables.

  • --font-sans controls body text, controls, and labels.
  • --font-mono controls code and keyboard shortcuts.
  • --font-heading controls dialog, alert dialog, sheet, and empty-state titles.

Set the variables on html or body so they cascade into portals. By default, the theme maps --font-heading to --font-sans.

:root {
  --font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, monospace;
}

Custom fonts

Set the three properties to any loaded fonts. When sans and heading share one family, only --font-sans needs a distinct value because the theme aliases --font-heading to it.

For a separate heading family, point the theme token at that variable:

:root {
  --font-sans: "Inter Variable", sans-serif;
  --font-heading: "Cal Sans", sans-serif;
  --font-mono: "Geist Mono Variable", monospace;
}

@theme inline {
  --font-heading: var(--font-heading);
}

Apply the variables to html or body so they cascade through the application and its portals.

Shards UI Setup

Shards UI renders overlays through portals. Give the application root its own stacking context and make body the containing block for full-viewport backdrops.

Application Root Isolation

<script lang="ts">
  import "../app.css";
  import type { Snippet } from "svelte";

  let { children }: { children: Snippet } = $props();
</script>

<div class="relative isolate flex min-h-svh flex-col">
  {@render children()}
</div>

This creates a local stacking context so portalled components stay above page content without component-specific z-index overrides.

iOS Safari Compatibility

body {
  position: relative;
}

This keeps portalled dialogs, sheets, popovers, selects, and menus above application content. It also prevents backdrop gaps after scrolling in current iOS Safari.