Typography

A text role is defined once with its size and line height per breakpoint; a component names the role.
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' } };

Theme uxdsl.theme.json, merged over the base theme

{
  "typography_details": {
    "h2": {
      "fontSize": "xs(space(6)) md(space(7)) xl(space(9))",
      "lineHeight": "xs(1.25) md(1.3)"
    }
  }
}

UXDSL you write example.uxdsl

.section-title { @ds-typo(h2); }

CSS you get compiled by uxdsl; :root shows only these tokens

:root {
  --uxdsl__typography__h2-font-size: var(--uxdsl__space__6);
  --uxdsl__typography__h2-line-height: 1.25;
}
@media (min-width: 768px) {
  :root {
    --uxdsl__typography__h2-font-size: var(--uxdsl__space__7);
    --uxdsl__typography__h2-line-height: 1.3;
  }
}
@media (min-width: 1280px) { :root { --uxdsl__typography__h2-font-size: var(--uxdsl__space__9); } }
.section-title {
  font-family: var(--uxdsl__typography__h2-font-family);
  font-size: var(--uxdsl__typography__h2-font-size);
  line-height: var(--uxdsl__typography__h2-line-height);
  font-weight: var(--uxdsl__typography__h2-font-weight);
  letter-spacing: var(--uxdsl__typography__h2-letter-spacing);
  margin-block-start: var(--uxdsl__typography__h2-margin-block-start);
  margin-block-end: var(--uxdsl__typography__h2-margin-block-end);
}

Rules

  • A role is a set of fields in typography_details: fontFamily, fontSize, lineHeight, fontWeight, letterSpacing, textTransform, textDecoration, fontStyle, marginBlockStart, marginBlockEnd. Each is a CSS value or a responsive expression; anything else is UXD_TYPO_FIELD.
  • default fills the fields a role omits; a role’s own field replaces the default’s whole value, breakpoints included.
  • @ds-typo(role) emits one declaration per field the theme defines for the role, and nothing else — no reset of text-transform or font-style. An unknown role is UXD_TYPO_REFERENCE; it never falls back to default.
  • The directive emits where it is written: a declaration after it wins (.eyebrow { @ds-typo(caption); margin: 0; } keeps margin: 0).
  • Sizes step at breakpoints; they are not fluid. A role is visual: keep heading levels right for the document, whichever role styles them.
  • A muted text is a palette color on the component, not an opacity field.
.eyebrow { @ds-typo(caption); margin: 0; }
.title { @ds-typo(hero); }  /* UXD_TYPO_REFERENCE: the theme defines no hero role */

The guide for coding agents is on For AI agents.