Skip to content

Commit 4c02395

Browse files
dario-piotrowiczAndrewKushnir
authored andcommitted
fix(compiler): make sure selectors inside container queries are correctly scoped (#48353)
improve the emulated shadowDom implementation so that it can correctly scope selectors present inside the @container at-rule (recently added to the css specs) resolves #48264 PR Close #48353
1 parent f443ee6 commit 4c02395

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

packages/compiler/src/shadow_css.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,8 @@ export class ShadowCss {
571571
this._scopeSelector(rule.selector, scopeSelector, hostSelector, this.strictStyling);
572572
} else if (
573573
rule.selector.startsWith('@media') || rule.selector.startsWith('@supports') ||
574-
rule.selector.startsWith('@document') || rule.selector.startsWith('@layer')) {
574+
rule.selector.startsWith('@document') || rule.selector.startsWith('@layer') ||
575+
rule.selector.startsWith('@container')) {
575576
content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
576577
} else if (rule.selector.startsWith('@font-face') || rule.selector.startsWith('@page')) {
577578
content = this._stripScopingSelectors(rule.content);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {ShadowCss} from '@angular/compiler/src/shadow_css';
10+
11+
describe('ShadowCss, container queries', () => {
12+
function s(css: string, contentAttr: string, hostAttr: string = '') {
13+
const shadowCss = new ShadowCss();
14+
return shadowCss.shimCssText(css, contentAttr, hostAttr);
15+
}
16+
17+
it('should scope normal selectors inside an unnamed container rules', () => {
18+
const css = `@container max(max-width: 500px) {
19+
.item {
20+
color: red;
21+
}
22+
}`;
23+
const result = s(css, 'host-a');
24+
expect(noIndentation(result)).toEqual(noIndentation(`@container max(max-width: 500px) {
25+
.item[host-a] {
26+
color: red;
27+
}
28+
}`));
29+
});
30+
31+
it('should scope normal selectors inside a named container rules', () => {
32+
const css = `@container container max(max-width: 500px) {
33+
.item {
34+
color: red;
35+
}
36+
}`;
37+
const result = s(css, 'host-a');
38+
// Note that for the time being we are not scoping the container name itself,
39+
// this is something that may or may not be done in the future depending
40+
// on how the css specs evolve. Currently as of Chrome 107 it looks like shadowDom
41+
// boundaries don't effect container queries (thus the scoping wouldn't be needed)
42+
// and this aspect of container queries seems to be still under active discussion:
43+
// https://github.com/w3c/csswg-drafts/issues/5984
44+
expect(noIndentation(result))
45+
.toEqual(noIndentation(`@container container max(max-width: 500px) {
46+
.item[host-a] {
47+
color: red;
48+
}
49+
}`));
50+
});
51+
});
52+
53+
function noIndentation(str: string): string {
54+
return str.replace(/\n\s+/g, '\n');
55+
}

0 commit comments

Comments
 (0)