Skip to content

fix: read px as CSS pixels on foreign children - #171

Merged
triniwiz merged 2 commits into
mainfrom
fix/foreign-px-css-pixels
Nov 8, 2026
Merged

triniwiz merged 2 commits into
mainfrom
fix/foreign-px-css-pixels

Conversation

@triniwiz

@triniwiz triniwiz commented Nov 6, 2026

Copy link
Copy Markdown
Owner

Problem

Inside a Mason container, px meant two different things. Mason's own views read it as CSS pixels. Plain NativeScript children (Svg, Canvas, any other foreign view) kept core's meaning, which is device pixels. So class="size-[22px]" on an <Svg> was about 7 dip on a 3x screen, a third of the same class on a Mason view. This came up in nativescript-hallow26.

Fix

foreign-layout.ts: the foreign Style setters now turn px into a dip number before core stores it. Converting only the value written to the Mason leaf would not be enough, because core still uses its own copy:

  • iOS measures foreign views through View.measureChild, which uses effectiveWidth.
  • Android's measure function reads the child's LayoutParams, which core sets.
  • Windows panels copy Width/Height from the XAML element.

A px value set before adoption is rewritten through the channel it came from (CSS, local or keyframe), so precedence is unchanged. This needed sourceKey on a CssProperty and source on a CssAnimationProperty.

Windows now converts width, height, min/max sizes and margins as well, but it still leaves copying them to its panels.

Limits

  • Only the properties the bridge mirrors are converted. Padding and border width on a foreign view still treat px as device pixels.
  • If a CSS px value is shadowed by an inline value before adoption, only the inline value is converted. If the inline value is later unset, the CSS value comes back as device pixels.
  • A child moved out of a Mason container keeps its converted dip values.

Testing

  • npm test: 62 files, 1290 passed.
  • tsc --noEmit on masonkit: clean.
  • I rewrote the existing test that asserted the old conversion, and added coverage that a converted value keeps its source, plus a Windows case.
  • Not verified on a device.

A plain NativeScript child of a Mason container (Svg, Canvas, ...) kept
core's meaning of px, device pixels, while Mason's own views read px as
CSS pixels. `width: 22px` on an Svg was a third of the size on a 3x screen.

The foreign Style setters now turn px into a dip number before core stores
it, so core's measure (iOS measureChild), Android's LayoutParams and the
Windows XAML box agree with the Mason leaf. A px value set before adoption
is rewritten through its own value source, keeping CSS/local/keyframe
precedence. Windows converts width, height, min/max and margins too, but
still leaves copying them to its panels.
@triniwiz
triniwiz merged commit fccba2e into main Nov 8, 2026
1 of 4 checks passed
@triniwiz
triniwiz deleted the fix/foreign-px-css-pixels branch November 8, 2026 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant