UX-DSL
XS0px

Typography

Responsive text styles, defined in your theme.
Choose a text style in the component. Let the system control how it adapts across screens.
Interactive Demo: Typography

Current viewport: 0px. The theme defines which text properties change at this width.

Theme Config (Live Typography)
h1: {
"fontSize": "xs(space(7)) md(space(8)) lg(space(9)) xl(space(10))",
"fontFamily": "var(--uxdsl__font__ui)"// inherited
"fontWeight": "700"
"lineHeight": "xs(1.2) md(1.3)"
"letterSpacing": "-0.02em"
"textTransform": "none"// inherited
"textDecoration": "none"// inherited
"fontStyle": "normal"// inherited
"marginBlockStart": "0"// inherited
"marginBlockEnd": "0.2em"
}
CSS Usage
.any-class{@ds-typo(h1);}

Theme Configuration: The settings below define your JSON theme. Once configured in uxdsl.theme.json, the mixin above applies these responsive rules automatically.

Typography Showcase
h1

UXDSL: The Design System Language

h2

The Evolution of Styling

h3

Atomic vs Semantic

h4

The rise of design tokens

h5
Runtime adaptability
h6
Future of CSS generation
p

UXDSL bridges the gap between design tokens and CSS generation, allowing for a truly semantic and adaptable design system that scales with your application.

body

UXDSL provides a type-safe, token-aware styling experience that integrates seamlessly with modern frameworks.

spanInline token usage
caption

Figure 1: Token dependency graph

smallv1.0.0-beta
codeconst answer = 42;
pre
const theme = { colors: { primary: 'blue' } };

Define the text style once. Let the system adapt it.

Typography is a configured text style with responsive behavior. A component chooses a style such as h1; the theme defines its size, weight, line height and other properties across breakpoints. Like Density, it keeps shared responsive decisions in the system.

Spacing defines values. Density defines responsive spacing. Typography defines responsive text styles. Typography can use Spacing tokens without forcing the same progression as Density. Native CSS remains available for intentional exceptions.

The source is the theme JSON

This illustrative theme defines the complete progression. Omitted built-in breakpoint names retain the library defaults; custom names can also be configured.

{
  "breakpoints": { "xs": 0, "md": 768, "xl": 1280 },
  "spacing": { "7": "1.75rem", "8": "2rem", "10": "2.5rem" },
  "fonts": { "families": { "ui": "Inter, sans-serif" } },
  "typography_details": {
    "default": {
      "fontFamily": "var(--uxdsl__font__ui)",
      "fontWeight": "400",
      "lineHeight": "1.5"
    },
    "h1": {
      "fontSize": "xs(space(7)) md(space(8)) xl(space(10))",
      "fontWeight": "700",
      "lineHeight": "xs(1.2) md(1.3)"
    }
  }
}

typography_details.default supplies missing fields to each configured style. A style’s own field replaces that default field as a whole; it does not merge individual breakpoint expressions. A responsive field needs a base value. The most recent applicable rule remains active until another breakpoint overrides it.

How this h1 behaves
ViewportFont sizeLine height
Below 768pxspace(7) → 1.75rem1.2
768px to below 1280pxspace(8) → 2rem1.3
1280px and abovespace(10) → 2.5rem1.3, inherited from md

Choose a style in the component

UXDSL

.page-title {
  @ds-typo(h1);
}

Pure CSS: the size progression

/* Equivalent size behavior, shown in isolation */
.page-title { font-size: 1.75rem; }
@media (min-width: 768px) {
  .page-title { font-size: 2rem; }
}
@media (min-width: 1280px) {
  .page-title { font-size: 2.5rem; }
}

The mixin consumes CSS variables such as --uxdsl__typography__h1-size and --uxdsl__typography__h1-line. The compiler generates their responsive definitions from the JSON. Pure CSS can centralize the same behavior with variables and media queries; UXDSL provides the reusable configuration and compilation layer.

Keep HTML semantics independent of visual styling: use the appropriate heading level for the document, even when its visual style comes from another Typography role. Custom configured names, such as label, can also be consumed with @ds-typo(label).

Change the system, update its consumers

  • Change a Typography progression to update every component consuming that style.
  • Change a Spacing token to update its direct consumers and the Typography or Density definitions referencing it.
  • Change a breakpoint threshold to move transitions using that name.
  • Choose another configured style or use a deliberate local CSS override when only one component should change.

One generator for build time and runtime

PostCSS accepts the JSON as its theme option. SSR and browser applications use generateThemeCss(theme) from postcss-uxdsl/ds-runtime. Both call the same Typography generator. For live changes, regenerate and replace the managed theme stylesheet rather than appending overrides:

import { generateThemeCss } from 'postcss-uxdsl/ds-runtime'

// themeStyle is the application's existing managed <style> element.
// Generate first so an invalid update cannot clear the active stylesheet.
const css = generateThemeCss(nextTheme)
themeStyle.textContent = css

The playground edits the JSON and applies this same generator. Its breakpoint buttons inspect a simulated viewport width using the shared resolver; they do not resize the browser. Default mode follows the actual viewport.

Supported fields and validation

Configured fields are fontFamily, fontSize, lineHeight, fontWeight, letterSpacing, textTransform, textDecoration, fontStyle, marginBlockStart and marginBlockEnd. Each accepts a nonempty string containing a CSS value or a configured responsive progression.

The shared compiler checks role names, fields, base values and breakpoint widths. It preserves nested CSS expressions and Spacing references. It does not yet validate every CSS value, token dependency or accessibility requirement. Legacy flat typography variables remain supported; use typography_details for structured responsive styles.

AI implementation guide

How an AI agent should use Typography

Responsibility: maintain shared text roles and their responsive behavior. Typography defines reusable visual text styles; components select the appropriate role without hardcoding the resolved values. HTML preserves document semantics.

Typography is the preferred shared abstraction for text styling. Preserve intent, not just the current computed value. Keep the configured role and its responsive behavior intact, just as you would preserve a Density token or a semantic Palette reference.

  • Inspect typography_details, its default fields, referenced fonts, spacing, and breakpoints before choosing or modifying a style. Treat these references as dependencies; inspect them without assuming they need to change.
  • Reuse an appropriate configured style with @ds-typo(role). Do not invent undefined roles or tokens.
  • Do not replace a Typography reference with a fixed font size merely because both look identical at the current breakpoint.
  • Keep semantic HTML appropriate to the document hierarchy; visual size does not determine the heading level.
  • Modify a shared style only when all its consumers should receive the change. Use a deliberate local rule for an isolated exception.
  • Preserve native CSS, units and token references when editing JSON. Do not convert unitless line height to pixels.
  • Use the shared generator and resolver. Do not recreate breakpoint parsing or write generated CSS as the source of truth.
  • Check just below, at and just above each configured breakpoint. Verify wrapping, zoom, font loading and other consumers of changed styles.

Decision rule: Choose the configured Typography role in the component. Define and evolve its visual and responsive behavior in the theme. Use local CSS only for intentional exceptions.

Example: preserve the shared role

.page-title {
  @ds-typo(h1);
}

The component selects the h1 typography role. The theme controls its font family, weight, line height, spacing references and responsive size progression.

Avoid copying the currently resolved values when the component is intended to remain connected to the shared Typography role:

.page-title {
  font-size: 2rem;
  line-height: 1.2;
}

These local values no longer follow changes to the shared role. They are appropriate only when that independence is an intentional exception.

Agent reasoning example

Make page titles follow the application’s responsive typography.
  1. Inspect the existing title styles and their responsive mappings.
  2. Choose the appropriate configured style, such as h1.
  3. Apply @ds-typo(h1) to the title selector while preserving appropriate HTML semantics.
  4. Verify the full progression instead of copying the font size visible on one screen.