Skip to content

Commit 7622a38

Browse files
authored
fix: use :root font-size as compile-time rem base (#315)
When no explicit inlineRem option is passed, the compiler now scans CSS for :root { font-size: Npx } and uses that value as the rem multiplier instead of hardcoding 14. This makes the documented v5 approach for overriding rem actually work. Closes nativewind/nativewind#1650
1 parent ba01ca5 commit 7622a38

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/__tests__/native/units.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,28 @@ test("rem - inline override", () => {
126126
});
127127
});
128128

129+
test("rem - css root font-size override", () => {
130+
registerCSS(`
131+
:root { font-size: 16px; }
132+
.my-class { font-size: 10rem; }
133+
`);
134+
135+
const { result } = renderHook(() => {
136+
return useNativeCss(View, { className: "my-class" });
137+
});
138+
139+
expect(result.current.type).toBe(VariableContext.Provider);
140+
expect(result.current.props.value).toStrictEqual({
141+
[VAR_SYMBOL]: true,
142+
[emVariableName]: 160,
143+
});
144+
145+
expect(result.current.props.children.type).toBe(View);
146+
expect(result.current.props.children.props).toStrictEqual({
147+
style: { fontSize: 160 },
148+
});
149+
});
150+
129151
test("rem - css override", () => {
130152
registerCSS(
131153
`

src/compiler/compiler.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,28 @@ export function compile(code: Buffer | string, options: CompilerOptions = {}) {
8484

8585
const vars = new Map<string, UniqueVarInfo>();
8686

87+
// Determine the effective rem multiplier for compile-time inlining.
88+
// If inlineRem is explicitly set, use that. Otherwise, scan for
89+
// :root { font-size: Npx } in the CSS to allow CSS-based configuration.
90+
let effectiveRem: number | false = options.inlineRem ?? undefined!;
91+
if (effectiveRem === undefined) {
92+
const css = typeof code === "string" ? code : code.toString();
93+
const match = css.match(/:root\s*\{[^}]*font-size:\s*([\d.]+)px/);
94+
effectiveRem = match?.[1] ? parseFloat(match[1]) : 14;
95+
}
96+
8797
const firstPassVisitor: Visitor<CustomAtRules> = {};
8898

89-
if (options.inlineRem !== false) {
99+
if (effectiveRem !== false) {
100+
const remMultiplier = effectiveRem;
90101
firstPassVisitor.Length = (length) => {
91-
if (length.unit !== "rem" || options.inlineRem === false) {
102+
if (length.unit !== "rem") {
92103
return length;
93104
}
94105

95106
return {
96107
unit: "px",
97-
value: round(length.value * (options.inlineRem ?? 14)),
108+
value: round(length.value * remMultiplier),
98109
};
99110
};
100111
}

0 commit comments

Comments
 (0)