Repository navigation
A custom property stores 5px, 5ms and 5 all as 5, so transition-duration: var(--v) over --v: 5px applies 5ms #551
Description
Before submitting a new issue
- I tested using the latest version of the library, as the bug might be already fixed.
- I tested using a supported version of react native.
- I checked for possible duplicate issues, with possible answers.
Bug summary
A custom property's value loses its unit when the sheet compiles: --v: 5ms, --v: 5px and --v: 5 all store 5, and --v: 5s stores 5000. So a property that reads the variable can't tell a length from a time or a number: with variables kept (inlineVariables: false), transition-duration: var(--v) over --v: 5px applies transitionDuration: 5, the same as over 5ms, and animation-iteration-count: var(--v) over --v: 2px applies animationIterationCount: 2.
In CSS a var() whose value doesn't fit the property's grammar makes the declaration invalid at computed-value time (css-variables-1 §3), so the property takes its initial value: Chromium 156, Firefox 157 and WebKit 27.2 compute transition-duration: 0s and animation-iteration-count: 1 for these. 5em and 5deg keep their unit ([{}, "em", 5, 1] and "5deg"), so only px lengths and times lose it.
--v: 5ms -> [["v",5]]
--v: 5 -> [["v",5]]
--v: 5px -> [["v",5]]
--v: 5s -> [["v",5000]]
--v: 5em -> [["v",[{},"em",5,1]]]
--v: 5deg -> [["v","5deg"]]
.a { --v: 5px; transition-duration: var(--v); } -> {"transitionDuration":5}
.a { --v: 5ms; transition-duration: var(--v); } -> {"transitionDuration":5}
.a { --v: 2px; animation-iteration-count: var(--v); } -> {"animationIterationCount":2}
.a { --v: 2; animation-iteration-count: var(--v); } -> {"animationIterationCount":2}
parseUnparsed (src/compiler/declarations.ts) turns a px length token and a time token into a bare number (through parseLength and parseTime), as a declaration's own parser does once it knows its property. A custom property's value has no property yet, so its kind is gone before any reader sees it.
Library version
main at a37903f (0.0.0-nightly.a37903f)
Environment info
Windows 11 10.0.26300, Node 26.12.1, Yarn 4.9.2, react-native 0.86.3 (the repository's dev dependency).
No app or native build is involved: the output comes from the repository's jest setup.Steps to reproduce
- Clone the reproducer branch, which is
mainat a37903f with one file added,src/__tests__/native/custom-property-unit.test.tsx, and install:git clone --branch repro/551-custom-property-keeps-no-unit https://github.com/YevheniiKotyrlo/react-native-css cd react-native-css yarn install - Run
yarn jest src/__tests__/native/custom-property-unit.test.tsxand read the logged lines.
src/__tests__/native/custom-property-unit.test.tsx:
import { StyleSheet } from "react-native";
import { render, screen } from "@testing-library/react-native";
import { compile } from "react-native-css/compiler";
import { View } from "react-native-css/components/View";
import { registerCSS, testID } from "react-native-css/jest";
jest.mock("../../native/reanimated", () => ({
animatedComponentFamily: (component: unknown) => component,
}));
test.each(["5ms", "5", "5px", "5s", "5em", "5deg"])(
"the stored value of --v: %s",
(value) => {
const sheet = compile(`.a { --v: ${value}; }`, {
inlineVariables: false,
}).stylesheet();
console.log(`--v: ${value} -> ${JSON.stringify(sheet.s?.[0]?.[1][0]?.v)}`);
},
);
test.each([
["5px", "transition-duration"],
["5ms", "transition-duration"],
["2px", "animation-iteration-count"],
["2", "animation-iteration-count"],
])("--v: %s read by %s: var(--v)", (value, property) => {
registerCSS(`.a { --v: ${value}; ${property}: var(--v); }`, {
inlineVariables: false,
});
render(<View testID={testID} className="a" />);
console.log(
`.a { --v: ${value}; ${property}: var(--v); } -> ${JSON.stringify(StyleSheet.flatten(screen.getByTestId(testID).props.style))}`,
);
screen.unmount();
});Expected: the stored value keeps its kind, so transition-duration: var(--v) over --v: 5px and animation-iteration-count: var(--v) over --v: 2px are refused and the properties take their initial values, 0s and 1, as in the browsers.
Actual: 5px and 5ms both store 5, and both apply transitionDuration: 5; 2px applies animationIterationCount: 2.
The run's output on main at a37903f, Windows 11, Node 26.12.1
console.log
--v: 5ms -> [["v",5]]
at log (src/__tests__/native/custom-property-unit.test.tsx:18:13)
console.log
--v: 5 -> [["v",5]]
at log (src/__tests__/native/custom-property-unit.test.tsx:18:13)
console.log
--v: 5px -> [["v",5]]
at log (src/__tests__/native/custom-property-unit.test.tsx:18:13)
console.log
--v: 5s -> [["v",5000]]
at log (src/__tests__/native/custom-property-unit.test.tsx:18:13)
console.log
--v: 5em -> [["v",[{},"em",5,1]]]
at log (src/__tests__/native/custom-property-unit.test.tsx:18:13)
console.log
--v: 5deg -> [["v","5deg"]]
at log (src/__tests__/native/custom-property-unit.test.tsx:18:13)
console.log
.a { --v: 5px; transition-duration: var(--v); } -> {"transitionDuration":5}
at log (src/__tests__/native/custom-property-unit.test.tsx:32:11)
console.log
.a { --v: 5ms; transition-duration: var(--v); } -> {"transitionDuration":5}
at log (src/__tests__/native/custom-property-unit.test.tsx:32:11)
console.log
.a { --v: 2px; animation-iteration-count: var(--v); } -> {"animationIterationCount":2}
at log (src/__tests__/native/custom-property-unit.test.tsx:32:11)
console.log
.a { --v: 2; animation-iteration-count: var(--v); } -> {"animationIterationCount":2}
at log (src/__tests__/native/custom-property-unit.test.tsx:32:11)
PASS src/__tests__/native/custom-property-unit.test.tsx
√ the stored value of --v: 5ms (15 ms)
√ the stored value of --v: 5 (1 ms)
√ the stored value of --v: 5px (1 ms)
√ the stored value of --v: 5s (1 ms)
√ the stored value of --v: 5em (1 ms)
√ the stored value of --v: 5deg (1 ms)
√ --v: 5px read by transition-duration: var(--v) (8 ms)
√ --v: 5ms read by transition-duration: var(--v) (2 ms)
√ --v: 2px read by animation-iteration-count: var(--v) (1 ms)
√ --v: 2 read by animation-iteration-count: var(--v) (2 ms)
Test Suites: 1 passed, 1 total
Tests: 10 passed, 10 total
Snapshots: 0 total
Time: 1.126 s, estimated 10 s
Ran all test suites matching /src\\__tests__\\native\\custom-property-unit.test.tsx/i.
Reproducible example repository
https://github.com/YevheniiKotyrlo/react-native-css/tree/repro/551-custom-property-keeps-no-unit
Activity