"Whitespace next to a Razor tag or expression boundary collapses to nothing"
Spaces between Razor expressions or between inline elements and text disappear at render time. For example, chunks <span class="cval">@x</span> more text renders as chunks123more with no spacing. A plain multi-expression line like @_worldSize × @_worldSize also loses its spacing, rendering as 256×256 instead of 256 × 256. Using (U+00A0) doesn't help — it vanishes too.
The engine's Razor rendering pipeline collapses whitespace that is immediately adjacent to a tag or expression boundary. A literal space right before <span> and right after </span> both vanish, while a space in the middle of one uninterrupted text run (no tag or expression boundary crossed) survives. The workaround fails because U+00A0 still satisfies char.IsWhiteSpace in .NET, so the collapse logic treats it identically to a regular space.
Two approaches, in order of preference:
-
Collapse into a single interpolated string — when no per-fragment styling is needed, merge multiple
@expr/literal fragments into one C# expression:@($"{worldSize} × {worldSize}"). This produces a single text node with no tag/expression boundary for the collapse logic to act on. -
Use CSS margin on inner elements — when a styled inner
<span>genuinely needs breathing room from its neighbours, apply margin on the span's class (e.g..cval { margin: 0 3px; }) instead of relying on a text-node space. Box-model spacing doesn't go through the whitespace-collapse pass at all and is the only reliable fix once has already failed.
HTML entities that aren't whitespace (·, ×, etc.) decode and render correctly — entities themselves aren't the problem. Only whitespace-class characters are collapsed.
The whitespace collapse targets characters that pass .NET's char.IsWhiteSpace check when they sit at a tag/expression boundary. Approach 1 eliminates those boundaries entirely (one text node, nothing to collapse). Approach 2 moves the spacing into the CSS box model, which is resolved after text-node processing, so the whitespace pass never sees it. The key insight: whitespace in the middle of a continuous text run is safe — the collapse only fires at structural boundaries.