diff --git a/experimental/css-has-pseudo/CHANGELOG.md b/experimental/css-has-pseudo/CHANGELOG.md index 9f66bdc38..0bd743f2e 100644 --- a/experimental/css-has-pseudo/CHANGELOG.md +++ b/experimental/css-has-pseudo/CHANGELOG.md @@ -1,5 +1,16 @@ # Changes to CSS Has Pseudo +### Unreleased (minor) + +- Rules within `@supports` selector check for `:has` won't be transformed. This respects stylesheet author of making the selector conditional: + +```pcss +@supports selector(:has(:focus)) { + /* Won't be transformed */ + :has(:focus) {} +} +``` + ### 0.4.0 (April 5, 2022) - Update `querySelector(:has())` polyfill, disallowing nested `:has` (`:has(.foo, :has(.bar))`) diff --git a/experimental/css-has-pseudo/src/index.ts b/experimental/css-has-pseudo/src/index.ts index b137136b5..74c2d3c80 100644 --- a/experimental/css-has-pseudo/src/index.ts +++ b/experimental/css-has-pseudo/src/index.ts @@ -16,7 +16,7 @@ const creator: PluginCreator<{ preserve?: boolean, specificityMatchingName?: str return { postcssPlugin: 'css-has-pseudo-experimental', RuleExit: (rule, { result }) => { - if (!rule.selector.includes(':has(')) { + if (!rule.selector.includes(':has(') || isWithinSupportCheck(rule)) { return; } @@ -102,6 +102,22 @@ creator.postcss = true; export default creator; +function isWithinSupportCheck(rule) { + let isSupportCheck = false; + let ruleParent = rule.parent; + + while (!isSupportCheck && ruleParent) { + if (ruleParent.type === 'atrule') { + + isSupportCheck = ruleParent.params.includes(':has(') && ruleParent.params.startsWith('selector('); + } + + ruleParent = ruleParent.parent; + } + + return isSupportCheck; +} + function selectorSpecificity(node) { let a = 0; let b = 0; diff --git a/experimental/css-has-pseudo/test/basic.css b/experimental/css-has-pseudo/test/basic.css index 1606462ef..e37868806 100644 --- a/experimental/css-has-pseudo/test/basic.css +++ b/experimental/css-has-pseudo/test/basic.css @@ -130,3 +130,15 @@ body:not(:has(:focus)) { .x:has(> :any-link) { order: 31; } + +@supports selector(:has(:focus)) { + :has(:focus) { + order: 32; + } +} + +@supports (display: grid) { + :has(:focus) { + order: 33; + } +} diff --git a/experimental/css-has-pseudo/test/basic.expect.css b/experimental/css-has-pseudo/test/basic.expect.css index a92a3338a..052c39c82 100644 --- a/experimental/css-has-pseudo/test/basic.expect.css +++ b/experimental/css-has-pseudo/test/basic.expect.css @@ -258,3 +258,18 @@ body:not(:has(:focus)) { .x:has(> :any-link) { order: 31; } + +@supports selector(:has(:focus)) { + :has(:focus) { + order: 32; + } +} + +@supports (display: grid) { + [csstools-has-1m-2w-2p-37-14-1m-2u-33-2r-39-37-15] { + order: 33; + } + :has(:focus) { + order: 33; + } +} diff --git a/experimental/css-has-pseudo/test/basic.preserve.expect.css b/experimental/css-has-pseudo/test/basic.preserve.expect.css index 9fe0845a3..053bc256d 100644 --- a/experimental/css-has-pseudo/test/basic.preserve.expect.css +++ b/experimental/css-has-pseudo/test/basic.preserve.expect.css @@ -130,3 +130,15 @@ [csstools-has-1a-3c-1m-2w-2p-37-14-1q-w-1m-30-2x-32-2z-15]:not(.does-not-exist) { order: 31; } + +@supports selector(:has(:focus)) { + :has(:focus) { + order: 32; + } +} + +@supports (display: grid) { + [csstools-has-1m-2w-2p-37-14-1m-2u-33-2r-39-37-15] { + order: 33; + } +} diff --git a/experimental/css-has-pseudo/test/basic.specificity-matching-name.expect.css b/experimental/css-has-pseudo/test/basic.specificity-matching-name.expect.css index 6f76bbda4..cbc4287ec 100644 --- a/experimental/css-has-pseudo/test/basic.specificity-matching-name.expect.css +++ b/experimental/css-has-pseudo/test/basic.specificity-matching-name.expect.css @@ -258,3 +258,18 @@ body:not(:has(:focus)) { .x:has(> :any-link) { order: 31; } + +@supports selector(:has(:focus)) { + :has(:focus) { + order: 32; + } +} + +@supports (display: grid) { + [csstools-has-1m-2w-2p-37-14-1m-2u-33-2r-39-37-15] { + order: 33; + } + :has(:focus) { + order: 33; + } +}