CSS math functions
Overview
Section titled “Overview”Prysm supports CSS math functions: clamp(), round(), min(), and max(). These functions can be used anywhere CSS lengths, angles, time, percentages, or numbers are accepted, including inside calc() expressions and with CSS custom properties (var()) populated through Prysm Data-Binding.
All expressions are parsed and evaluated directly in Prysm‘s C++ style engine during layout passes.
Why CSS math functions matter for Game UI
Section titled “Why CSS math functions matter for Game UI”Game user interfaces have significantly different architectural requirements than traditional web pages:
- Zero JavaScript overhead and strict frame budgets: Game UIs typically target 60 or 120 FPS. Running JavaScript resize listeners,
ResizeObserverloops, or measuring element bounds (getBoundingClientRect) each frame consumes precious CPU time on the main UI thread. In Prysm, math functions evaluate natively in C++ during the layout pass without JavaScript execution, bridge marshaling, or garbage collection. - A single UI for diverse display setups: Games must scale seamlessly across dramatically different viewports—from compact 720p or 800p handhelds (such as the Steam Deck or Nintendo Switch) to 1080p, 1440p, 4K TVs, and 21:9 or 32:9 ultrawide desktop monitors. Instead of maintaining sprawling media queries or resolution-switch scripts, math functions enable fluid, self-bounding UI components.
- Separation of game logic and presentation: Rather than writing clamping, stepping, or aspect-ratio bounding code in C++ or C# gameplay systems before pushing data to the UI, gameplay code can expose raw numeric state (such as health points, ammo counts, recoil offsets, or compass headings). The stylesheets handle presentation boundaries, percentage clamping, and stepped animations directly.
Game UI use cases
Section titled “Game UI use cases”Responsive cross-platform scaling
Section titled “Responsive cross-platform scaling”Game HUDs must remain legible on small handheld screens without becoming excessively large or intrusive on 4K monitors:
.hud-action-bar { /* Scales fluidly with viewport width, bounded between 320px and 720px */ width: clamp(320px, 40vw, 720px); /* Ensures font size remains readable on handhelds without overpowering 4K displays */ font-size: clamp(14px, 1.8vw, 24px);}Screen-safe positioning and boundaries
Section titled “Screen-safe positioning and boundaries”Floating nameplates, radar indicators, and cursor tooltips can be constrained within the screen without measuring bounding boxes in JavaScript:
.floating-tooltip { position: absolute; /* Keep the 300px-wide tooltip at least 16px away from screen edges */ left: clamp(16px, var(--cursor-x), calc(100vw - 316px)); top: clamp(16px, var(--cursor-y), calc(100vh - 160px));}In-stylesheet game state clamping
Section titled “In-stylesheet game state clamping”Clamp dynamic game values directly in CSS even if gameplay values momentarily exceed nominal ranges:
.health-bar-fill { /* Clamps player HP between 0% and 100% directly in CSS */ width: clamp(0%, calc(var(--current-hp) / var(--max-hp) * 100%), 100%);}Console title-safe zones and overscan
Section titled “Console title-safe zones and overscan”Comply with console certification requirements by establishing guaranteed minimum safe-zone margins that expand proportionally on larger screens:
.hud-container { /* Guarantees at least 32px safe inset, expanding with large screen resolutions */ padding-top: max(32px, 4vh); padding-bottom: max(32px, 4vh); padding-left: max(48px, 5vw); padding-right: max(48px, 5vw);}Adaptive panels and combat logs
Section titled “Adaptive panels and combat logs”Ensure dynamic chat windows and inventory containers expand to fit content while maintaining a sensible maximum size relative to the viewport:
.combat-log-panel { width: min(520px, 90vw); max-height: min(360px, 45vh);}Segmented health, armor, and stamina bars
Section titled “Segmented health, armor, and stamina bars”Convert continuous health or armor percentages into discrete segmented visual blocks (such as 10% shield pips) purely through CSS:
.shield-bar-stepped { /* Snaps continuous shield percentage down to discrete 10% blocks */ width: round(down, var(--shield-pct), 10%);}Compass tapes and radial wheels
Section titled “Compass tapes and radial wheels”Snap floating navigation compasses, radial weapon wheels, or heading markers to fixed angular steps:
.hud-compass-tape { /* Snaps compass bearing to 15-degree visual increments */ transform: rotate(round(nearest, var(--heading-deg), 15deg));}Pixel-grid snapping for retro and 2D games
Section titled “Pixel-grid snapping for retro and 2D games”In pixel-art games or stylized retro UIs, sub-pixel floating-point offsets can cause sprite shimmering and blurred glyphs. Snapping dynamic coordinates to virtual pixel or texel grids prevents sub-pixel artifacts:
.pixel-cursor { /* Snaps element position to a 2px virtual grid to prevent sub-pixel blur */ transform: translate( round(nearest, var(--target-x), 2px), round(nearest, var(--target-y), 2px) );}Composable expressions with calc()
Section titled “Composable expressions with calc()”Math functions can be nested within one another or inside calc() to create sophisticated layout rules:
.damage-indicator { /* Scale and clamp a stepped recoil translation within safe bounds */ transform: translateY( clamp(-100px, round(nearest, calc(var(--recoil-offset) * -1.2), 4px), 0px) );}Differences from standard behavior and limitations
Section titled “Differences from standard behavior and limitations”While Prysm implements clamp(), round(), min(), and max() according to the CSS Values and Units Module specification, the following differences and limitations apply:
- No mixing of percentages and dimensional units in expressions: In alignment with Prysm‘s
calc()implementation, mixing percentages (%) with dimensional length units (such aspx,em, orvw) inside the same math function expression is not supported. This is because percentages depend on element layout box resolution. - No support in
@keyframes: Math functions are not supported within@keyframesrule definitions. - Argument category compatibility: All arguments within a single math function call must resolve to compatible type categories (for example, lengths with lengths, or angles with angles).
For standard syntax, argument ordering, and specification details, see the MDN references for CSS math functions, clamp(), round(), min(), and max().
© 2026 Coherent Labs. All rights reserved.