Skip to content

Commit

Permalink
fix(compiler): make sure selectors inside container queries are corre…
Browse files Browse the repository at this point in the history
…ctly 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
  • Loading branch information
dario-piotrowicz authored and AndrewKushnir committed Dec 6, 2022
1 parent 1e58a8c commit 9a5d842
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/compiler/src/shadow_css.ts
Expand Up @@ -571,7 +571,8 @@ export class ShadowCss {
this._scopeSelector(rule.selector, scopeSelector, hostSelector, this.strictStyling);
} else if (
rule.selector.startsWith('@media') || rule.selector.startsWith('@supports') ||
rule.selector.startsWith('@document') || rule.selector.startsWith('@layer')) {
rule.selector.startsWith('@document') || rule.selector.startsWith('@layer') ||
rule.selector.startsWith('@container')) {
content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
} else if (rule.selector.startsWith('@font-face') || rule.selector.startsWith('@page')) {
content = this._stripScopingSelectors(rule.content);
Expand Down
55 changes: 55 additions & 0 deletions packages/compiler/test/shadow_css/container_queries_spec.ts
@@ -0,0 +1,55 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {ShadowCss} from '@angular/compiler/src/shadow_css';

describe('ShadowCss, container queries', () => {
function s(css: string, contentAttr: string, hostAttr: string = '') {
const shadowCss = new ShadowCss();
return shadowCss.shimCssText(css, contentAttr, hostAttr);
}

it('should scope normal selectors inside an unnamed container rules', () => {
const css = `@container max(max-width: 500px) {
.item {
color: red;
}
}`;
const result = s(css, 'host-a');
expect(noIndentation(result)).toEqual(noIndentation(`@container max(max-width: 500px) {
.item[host-a] {
color: red;
}
}`));
});

it('should scope normal selectors inside a named container rules', () => {
const css = `@container container max(max-width: 500px) {
.item {
color: red;
}
}`;
const result = s(css, 'host-a');
// Note that for the time being we are not scoping the container name itself,
// this is something that may or may not be done in the future depending
// on how the css specs evolve. Currently as of Chrome 107 it looks like shadowDom
// boundaries don't effect container queries (thus the scoping wouldn't be needed)
// and this aspect of container queries seems to be still under active discussion:
// https://github.com/w3c/csswg-drafts/issues/5984
expect(noIndentation(result))
.toEqual(noIndentation(`@container container max(max-width: 500px) {
.item[host-a] {
color: red;
}
}`));
});
});

function noIndentation(str: string): string {
return str.replace(/\n\s+/g, '\n');
}

0 comments on commit 9a5d842

Please sign in to comment.