CoherynUI CSS — Cascade & Specificity Specification v1.0
Status: Approved Specification
Reference ADR: ADR-004: Cascade Layers and Precedence
1. Scope & Layer Architecture
CoherynUI CSS relies natively on standard CSS Cascade Layers (@layer) to guarantee predictable rule resolution. This removes the need for artificial specificity inflation (such as chained classes or !important proliferation).
Canonical Layer Hierarchy
All emitted stylesheets must declare the canonical layer order at the very top:
@layer cyn.reset,
cyn.tokens,
cyn.base,
cyn.recipes,
cyn.utilities;
From lowest priority to highest priority (for normal declarations):
cyn.reset: Modern box-sizing, margin resets, default border colors, and media defaults.cyn.tokens: CSS custom properties definitions (:rootand[data-theme="..."]).cyn.base: Element-level typography, baseline heading scales, and accessibility resets.cyn.recipes: Multi-declaration compound patterns (e.g.ui-card,ui-button,.glass).cyn.utilities: Atomic utility classes (e.g..p-6,.flex,.radius-xl).
2. Precedence Rules & Specificity
2.1 Normal Declarations
Within standard CSS:
- A utility class in
cyn.utilitiesalways beats a declaration incyn.recipes, which beatscyn.base. - Example: An element with class
ui-card p-4will render withpadding: 1rem(fromp-4incyn.utilities), even ifui-cardspecifiespadding: 1.5remincyn.recipes.
2.2 Important Declarations (!important)
Per the CSS Cascading and Inheritance Level 5 specification:
Critical Invariant: An
!importantdeclaration in an earlier layer overrides an!importantdeclaration in a later layer. Specifically:!importantlayer precedence is the exact reverse of normal layer precedence.
- Normal layer priority:
utilities > recipes > base > reset - Important layer priority:
reset (!important) > base (!important) > recipes (!important) > utilities (!important)
Therefore, CoherynUI compiler diagnostics (CY2005) will actively flag when !important is used across recipes or reset styles that could invert utility expectations.
2.3 Unlayered Author Styles
Styles defined outside of @layer by the author always take precedence over layered declarations (unless the layered declaration is !important). This allows developers to write custom CSS overrides without struggling against utility specificity:
/* Author unlayered CSS */
.my-custom-override {
padding: 3rem; /* Wins over .p-4 in cyn.utilities */
}
3. Variant Precedence & Grouping
Within the cyn.utilities layer, rules are deterministically ordered to ensure variants override base utilities:
1. Base utilities (e.g. .p-4)
2. State variants (e.g. .hover\:p-6:hover, .focus\:p-6:focus)
3. Responsive viewport queries (sm: -> md: -> lg: -> xl: -> 2xl:)
4. Responsive state variants (sm:hover:)
5. Container queries (cq: -> cq@sidebar:)
This deterministic sorting ensures that regardless of the order classes appear in an HTML class attribute (e.g. class="sm:p-6 p-4" vs class="p-4 sm:p-6"), the larger breakpoint or state variant always wins.
4. Prefix Customization (coherynui.config.toml)
By default, CoherynUI uses cyn as the canonical prefix for cascade layers (@layer cyn.*) and design token CSS custom properties (--cyn-*). All prefixes are fully customizable in coherynui.config.toml:
[compiler]
# Customize cascade layer namespace:
# e.g. "acme" -> @layer acme.reset, acme.tokens, acme.recipes, acme.utilities;
layer_prefix = "cyn"
# Customize CSS custom properties prefix:
# e.g. "acme" -> --acme-color-surface, --acme-space-4
variable_prefix = "cyn"
# Optional utility class prefix (empty by default):
# e.g. "ui-" -> .ui-flex, .ui-p-4
class_prefix = ""