Get started

DTCG border tokens: author, transform, and verify composite borders

A DTCG border composite treats color, width, and style as one design decision. The source object is only the starting point. It doesn't prove that references resolve, a translation tool emits the intended CSS, or a component renders the right border. This guide separates those claims and provides a copyable fixture and acceptance record for tracing one border from source to screen.

Updated September 19, 2026

Pin the contract before authoring the border

First, name the report target that the fixture is meant to follow. The examples below target the published DTCG 2025.10 format indicated by the captured DTCG glossary. The glossary deliberately provides high-level terminology instead of the complete technical contract, so a production workflow should retain the exact report or schema URI with the source file and recheck it when the report changes.

The version pin matters because a familiar-looking JSON object may be accepted for several different reasons. It might conform to a published format, match a tool's import convention, or simply parse as JSON. Those claims aren't equivalent. A successful design-tool preview has the same limit: it demonstrates behavior in that tool under the tested conditions, not portable support everywhere else.

LayerOwnsUseful evidenceDoes not prove
DTCG report targetDTCG report targetPortable token structure and value typesPinned report or schema identityA translation tool supports every feature
Authoring toolAuthoring toolEditing, references, and tool-specific application behaviorSaved source plus tool and versionAnother tool resolves it identically
Translation toolTranslation toolResolution, naming, transforms, and serializationPinned version, configuration, log, and generated fileA component loads or uses that artifact
Project policyProject policyToken boundaries, naming, ownership, modes, and exceptionsApproved decision recordThe implementation matches the decision
ConsumerConsumerSelectors, cascade, component states, and rendered behaviorComputed values in a named build and fixtureEvery consumer and mode is correct
The border contract is split across layers. Record each layer instead of letting one successful preview stand in for the whole chain.

Do not universalize a tool convention

Tokens Studio documents a detailed border workflow and Figma behavior. Terrazzo and legacy Cobalt document their own supported token and translation behavior. Those pages apply to their named products. Don't turn an import option, extension, generated name, or Figma application rule into a universal DTCG requirement.

Define what belongs inside the border

The portable border concept coordinates three named values: color, width, and style. Border radius is a separate decision. It changes geometry rather than the stroke itself, and the Tokens Studio documentation also treats it separately. Don't add side selection, detailed dash patterns, CSS logical properties, or browser-specific serialization to the composite unless the pinned contract and chosen tool explicitly support them.

That boundary keeps a DTCG border from becoming a bag for every CSS property containing the word border. The source records a design decision. A later mapping decides whether it becomes three CSS longhands, a shorthand, native-platform fields, or another target representation.

Author a minimal DTCG border fixture

The fixture below defines typed primitive inputs and one semantic composite. Its color, width, and stroke style remain reusable, while the semantic token states that they form the standard boundary treatment. Descriptions capture intent. They help reviewers tell an intentional contract from a convenient grouping.

{
  "$schema": "https://www.designtokens.org/schemas/2025.10/format.json",
  "color": {
    "border": {
      "neutral": {
        "$type": "color",
        "$description": "Neutral boundary color for standard controls and panels.",
        "$value": {
          "colorSpace": "srgb",
          "components": [0.45, 0.47, 0.50],
          "alpha": 1,
          "hex": "#737880"
        }
      }
    }
  },
  "dimension": {
    "border": {
      "thin": {
        "$type": "dimension",
        "$description": "Standard single-pixel border at the target CSS scale.",
        "$value": { "value": 1, "unit": "px" }
      }
    }
  },
  "stroke": {
    "solid": {
      "$type": "strokeStyle",
      "$description": "Continuous stroke for standard interface boundaries.",
      "$value": "solid"
    }
  },
  "border": {
    "control": {
      "default": {
        "$type": "border",
        "$description": "Default boundary shared by standard interactive controls.",
        "$value": {
          "color": "{color.border.neutral}",
          "width": "{dimension.border.thin}",
          "style": "{stroke.solid}"
        }
      }
    }
  }
}
Authored source fixture targeting the DTCG 2025.10 format. It is an example for this guide, not an Identity Forge export or an executed interoperability result.

The references are part of the authored source too. Their presence doesn't prove that a resolver found compatible targets. Keep the authored object separate from the resolved expectation so a missing target, cycle, or incompatible type can't disappear inside generated output.

{
  "tokenPath": "border.control.default",
  "resolvedExpectation": {
    "color": {
      "colorSpace": "srgb",
      "components": [0.45, 0.47, 0.50],
      "alpha": 1,
      "hex": "#737880"
    },
    "width": { "value": 1, "unit": "px" },
    "style": "solid"
  },
  "resolutionStatus": "unobserved"
}
Expected resolution, kept outside the authored fixture. Change resolutionStatus only after the named resolver and version have been run.

Property references are not the whole alias topic

This border uses references because its properties have reusable identities. For missing targets, chained references, circularity, compatibility, and whole-token aliases, use the dedicated DTCG alias guide instead of expanding the border contract.

Choose the representation by change behavior

A composite fits when the three properties form one stable decision. It isn't automatically the best representation for every border. Ask what should happen when one property changes, who owns that change, and which consumers it may reach.

RepresentationUse it whenMain advantageWarning sign
One border compositeOne border compositeColor, width, and style are normally applied and changed togetherConsumers receive one coordinated decisionTeams repeatedly unpack it to vary one property
Separate reusable tokensSeparate reusable tokensProperties have independent consumers or lifecyclesWidth, color, or style can be reused without copying valuesConsumers must reconstruct the same border everywhere
Semantic border tokenSemantic border tokenSeveral consumers share the same intent and should move togetherThe stable name survives primitive value changesThe name describes appearance instead of purpose
Component-owned exceptionComponent-owned exceptionOne named component has a justified independent requirementThe exception has explicit scope and ownershipA local override spreads to unrelated components
Choose the narrowest representation that matches the decision's real change scope.

These choices can work together. The example uses separate primitive properties inside a semantic composite. A component can consume that shared composite until evidence shows that it needs independent change authority. If only a data table divider must become thinner while inputs, cards, and menus stay unchanged, that supports a table-owned decision or documented exception. It isn't a reason to weaken every shared border.

Modes and states also shape the boundary. Light and dark modes may resolve the same semantic border name to different colors while preserving its width and style. A focus or error state may need a separate semantic border because its meaning differs, even when the current values match. Name the intent first. Don't infer shared ownership from identical values.

Inspect a real token artifact before choosing a boundary

Identity Forge kits include implementation artifacts such as DTCG token exports. Use a published kit as upstream material to inspect, then record what your own transformer and application do with it. The current evidence does not establish that a kit exports the border composite shown in this article.

Specify the transformation without inventing a result

A transformation contract records what you intend a named tool to do. Include the tool and exact version, configuration identity, source identity or hash, target platform, naming rule, output path, and expected properties. Until the command has run and you've captured the artifact, the result remains an expectation.

{
  "translationContract": {
    "tool": "UNRESOLVED",
    "version": "UNRESOLVED",
    "configuration": "UNRESOLVED",
    "inputFile": "tokens/border.tokens.json",
    "inputHash": "UNRESOLVED",
    "target": "css-custom-properties",
    "expectedSymbols": [
      "--border-control-default-color",
      "--border-control-default-width",
      "--border-control-default-style"
    ],
    "outputFile": "UNRESOLVED"
  },
  "artifactObservation": "UNRESOLVED"
}
Translation contract template. Replace unresolved fields with captured facts from the actual build.

For a CSS target, a project might choose to emit longhands. They make each resolved property inspectable and avoid depending on a tool's shorthand ordering. That's a project choice, not a DTCG requirement.

:root {
  --border-control-default-color: #737880;
  --border-control-default-width: 1px;
  --border-control-default-style: solid;
}

.control {
  border-color: var(--border-control-default-color);
  border-width: var(--border-control-default-width);
  border-style: var(--border-control-default-style);
}
Illustrative expected CSS, not generated output. Confirm symbol names, serialization, and selector mapping against the chosen transformer and project configuration.

Expected CSS is still useful

An explicit expectation gives reviewers a falsifiable target. If the transformer emits a shorthand, changes the symbol names, converts the color, or drops a property, the difference is visible. The mistake is calling the expectation generated or tested before anyone has observed it.

Verify one named consumer

Pick a consumer that matters, such as the default text input in the account form. Don't verify an anonymous swatch or isolated rectangle and assume the application is covered. A named consumer exposes selector scope, cascade, state handling, and local overrides.

  1. 1

    Capture the emitted artifact

    Record the generated file identity, build or package version, and exact declarations for the border token. Compare them with the expected symbols and values.

  2. 2

    Confirm the consumer mapping

    Identify the selector, utility, component prop, or platform mapping that connects the emitted artifact to the named component. A correct artifact can still remain unused.

  3. 3

    Inspect computed values

    Record the target element's computed border color, width, and style. Check whether shorthands, higher-specificity selectors, inline styles, or component variants replace them.

  4. 4

    Exercise required modes and states

    Repeat the observation in every in-scope mode and state, including default, hover, focus, disabled, and error where supported. Mark unsupported or out-of-scope cases explicitly.

  5. 5

    Check protected surfaces

    Change the source border in a controlled branch or fixture. Confirm that intended consumers change while named protected surfaces remain stable.

  6. 6

    Record exceptions and disposition

    Attach every accepted local override to a scope, reason, owner, and review condition. Choose accept, revise, or block from the recorded evidence.

An intentionally obvious controlled change works well, such as changing the test width from 1px to 3px in a non-release fixture. If the input changes but an unrelated card doesn't, the mapping may have the intended reach. Restore the approved value after the trace. The goal is to expose the dependency path, not approve the temporary design.

Copy the border acceptance record

Keep this record with the test evidence or release decision. Unresolved fields stay visible because an honest blank is more useful than a plausible claim nobody checked.

{
  "source": {
    "file": "tokens/border.tokens.json",
    "hash": "UNRESOLVED",
    "contractTarget": "DTCG 2025.10",
    "tokenPath": "border.control.default",
    "references": {
      "color": "color.border.neutral",
      "width": "dimension.border.thin",
      "style": "stroke.solid"
    },
    "resolvedExpectation": {
      "colorHex": "#737880",
      "width": "1px",
      "style": "solid"
    }
  },
  "translation": {
    "tool": "UNRESOLVED",
    "version": "UNRESOLVED",
    "configuration": "UNRESOLVED",
    "target": "css-custom-properties",
    "artifactPath": "UNRESOLVED",
    "artifactHash": "UNRESOLVED",
    "observedSymbols": "UNRESOLVED",
    "observedValues": "UNRESOLVED"
  },
  "consumer": {
    "name": "Account form text input",
    "buildIdentity": "UNRESOLVED",
    "selectorOrMapping": "UNRESOLVED",
    "modes": ["light", "dark"],
    "states": ["default", "hover", "focus", "disabled", "error"],
    "expectedComputedValues": {
      "borderColor": "#737880",
      "borderWidth": "1px",
      "borderStyle": "solid"
    },
    "observedComputedValues": "UNRESOLVED"
  },
  "protectedSurfaces": [
    "Data table row dividers",
    "Decorative separators"
  ],
  "exceptions": [],
  "correctionOwner": "UNRESOLVED",
  "disposition": "block",
  "reason": "Artifact and runtime observations have not been captured."
}
Copyable border acceptance record. The initial block disposition is appropriate while required artifact and consumer evidence remains unresolved.

Choose accept only when the in-scope source, resolution, artifact, mapping, and consumer observations agree and any exceptions are approved. Choose revise when the intended decision is sound but a correctable mapping, configuration, or local override is wrong. Choose block when required evidence is absent, references don't resolve, the wrong consumers change, or a protected surface is affected.

Route failures to the layer that owns them

FailureLikely owning layerCheck firstTypical correction
Invalid border shapeInvalid border shapeSource authoring or contract selectionPinned report and token value structureCorrect the source or target the intended contract
Missing or incompatible referenceMissing or incompatible referenceResolver input or token architectureReferenced path, type, and resolution logRepair the path or choose a compatible token
Border type unsupportedBorder type unsupportedTranslation tool or configurationSupported types, plugins, and pinned versionAdd an approved transform or choose a supported output route
Generated name collisionGenerated name collisionNaming transformFull emitted symbol tableChange the naming rule and rebuild
Correct build, stale application valueCorrect build, stale application valueDistribution or application buildArtifact hashes and loaded package or filePublish or load the reviewed artifact
Correct variable, wrong computed borderCorrect variable, wrong computed borderConsumer mapping or cascadeSelector scope, specificity, shorthand, and inline stylesCorrect the mapping or remove the unintended override
One state or mode is wrongOne state or mode is wrongState or mode contract and implementationMode activation and variant selectorsAdd or correct the missing mapping
One justified component differsOne justified component differsComponent-owned exceptionRecorded scope, reason, owner, and protected surfacesApprove and document the exception or remove it
Diagnose from source toward the consumer. Fixing a downstream symptom can hide the layer that actually broke.

The order matters. If the computed border is wrong, first confirm that the application loaded the reviewed artifact. If it did, inspect the selector and cascade. Don't edit the primitive source before locating the break: that can change every correct consumer while leaving the faulty override untouched.

Where Identity Forge stops

Identity Forge supplies implementation-ready design kits and DTCG token exports. The frozen product evidence doesn't establish that a current Identity Forge kit exports a DTCG border composite, so the fixture in this guide is illustrative and must not be attributed to the product.

Even when an Identity Forge export is the upstream source, the consuming project still owns translation configuration, naming, application mapping, rendered verification, exceptions, and release approval. A source artifact can make the decision portable. It can't observe your build, cascade, component variants, or production surface for you.

One useful next action

Choose one shared border used by a real component. Record its exact source token and references, pin one transformer and configuration, capture the emitted declarations, and inspect the component's computed border. Leave every field you didn't observe marked unresolved.

DTCG border token questions

What is a DTCG border token?

It is a composite design token whose value coordinates color, width, and style. The DTCG glossary describes composites as closely related values that are normally applied together.

Should border radius be part of the border composite?

No. Keep radius separate. It controls geometry rather than the border stroke, and the captured Tokens Studio documentation treats border radius as a separate token concern.

Should every border use a composite token?

No. Use a composite when its properties form one coordinated decision. Keep properties separate when they have independent consumers or change lifecycles. Add a semantic name when several consumers share an intent, and use a component exception only with explicit scope and ownership.

Does valid DTCG JSON prove the border will work in CSS?

No. Source validity doesn't prove reference resolution, transformer support, generated CSS, application loading, selector mapping, or computed runtime values. Test those layers separately.

Is the CSS in this guide generated by a specific tool?

No. It is illustrative expected output for a project that chooses CSS longhands. Record the actual tool, version, configuration, output file, and observed declarations before calling any artifact generated or verified.

Does Identity Forge currently export DTCG border composites?

The frozen product evidence confirms DTCG token exports but doesn't establish a current border-composite export. Inspect the selected export and record what is actually present.

Sources

  • DTCG Glossary: Defines aliases, composite design tokens, design tools, and translation tools at a high level, and identifies a border composite as color, width, and style.
  • Border - Composite - Tokens Studio for Figma: Documents Tokens Studio border authoring and Figma application behavior, including border properties supplied directly or through references and border radius as a separate concern.
  • DTCG Tokens - Terrazzo: Shows DTCG tokens as nested JSON data and places code generation within a translation tool's implementation context.
  • tokens.json Manifest - Cobalt: Documents an implementation-specific DTCG-compatible manifest, supported token types, and tool extensions, illustrating why tool support must be recorded separately from the portable contract.
  • Design tokens with confidence: Describes the core border composite value as color, width, and style in a DTCG-oriented overview.
  • The developer's guide to design tokens and CSS variables: Distinguishes platform-neutral design-token data from CSS custom properties used as a browser implementation layer.
  • Component tokens vs semantic tokens: when to add a component layer: Provides an existing decision framework based on change scope, named consumers, modes, states, protected surfaces, and ownership.
  • Identity Forge: Documents Identity Forge design kits and their implementation artifacts, including token exports, while not establishing that a current kit exports a border composite.