Skip to content

Commit e112e32

Browse files
crisbetoalxhub
authored andcommitted
fix(compiler): handle case-sensitive CSS custom properties (#41380)
Currently we normalize all CSS property names in the `StylingBuilder` which breaks custom properties, because they're case-sensitive. These changes add a check so that custom properties aren't normalized. Fixes #41364. PR Close #41380
1 parent c4628f2 commit e112e32

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

packages/compiler/src/render3/view/styling_builder.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,11 @@ export class StylingBuilder {
219219
if (isEmptyExpression(value)) {
220220
return null;
221221
}
222-
name = normalizePropName(name);
222+
// CSS custom properties are case-sensitive so we shouldn't normalize them.
223+
// See: https://www.w3.org/TR/css-variables-1/#defining-variables
224+
if (!isCssCustomProperty(name)) {
225+
name = hyphenate(name);
226+
}
223227
const {property, hasOverrideFlag, suffix: bindingSuffix} = parseProperty(name);
224228
suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix;
225229
const entry:
@@ -607,6 +611,10 @@ function getStylePropInterpolationExpression(interpolation: Interpolation) {
607611
}
608612
}
609613

610-
function normalizePropName(prop: string): string {
611-
return hyphenate(prop);
614+
/**
615+
* Checks whether property name is a custom CSS property.
616+
* See: https://www.w3.org/TR/css-variables-1
617+
*/
618+
function isCssCustomProperty(name: string): boolean {
619+
return name.startsWith('--');
612620
}

packages/core/test/acceptance/styling_spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,29 @@ describe('styling', () => {
294294
const header = fixture.nativeElement.querySelector('h1') as HTMLElement;
295295
expect(getComputedStyle(header).getPropertyValue('width')).toEqual('100px');
296296
});
297+
298+
it('should support case-sensitive css variables', () => {
299+
// This test only works in browsers which support CSS variables.
300+
if (!supportsCssVariables) {
301+
return;
302+
}
303+
304+
@Component({
305+
template: `
306+
<div [style.--MyVar]="'100px'">
307+
<span style="width: var(--MyVar)">CONTENT</span>
308+
</div>
309+
`
310+
})
311+
class Cmp {
312+
}
313+
TestBed.configureTestingModule({declarations: [Cmp]});
314+
const fixture = TestBed.createComponent(Cmp);
315+
fixture.detectChanges();
316+
317+
const span = fixture.nativeElement.querySelector('span') as HTMLElement;
318+
expect(getComputedStyle(span).getPropertyValue('width')).toEqual('100px');
319+
});
297320
});
298321

299322
modifiedInIvy('shadow bindings include static portion')

0 commit comments

Comments
 (0)