Skip to content

Commit 9e62bf2

Browse files
committed
Split :has rules when using experimental.optimizeUniversalDefaults (#12736)
* Split `:has` rules when using optimizeUniversalDefaults * Update changelog
1 parent 50fa6dd commit 9e62bf2

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111

1212
- Ensure max specificity of `0,0,1` for button and input Preflight rules ([#12735](https://github.com/tailwindlabs/tailwindcss/pull/12735))
13+
- Split `:has` rules when using `experimental.optimizeUniversalDefaults` ([#12736](https://github.com/tailwindlabs/tailwindcss/pull/12736))
1314

1415
## [3.4.1] - 2014-01-05
1516

src/lib/resolveDefaultsAtRules.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,12 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) {
104104
// we consider them separately because merging the declarations into
105105
// a single rule will cause browsers that do not understand the
106106
// vendor prefix to throw out the whole rule
107+
// Additionally if a selector contains `:has` we also consider
108+
// it separately because FF only recently gained support for it
107109
let selectorGroupName =
108-
selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'
110+
selector.includes(':-') || selector.includes('::-') || selector.includes(':has')
111+
? selector
112+
: '__DEFAULT__'
109113

110114
let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
111115
selectorGroups.set(selectorGroupName, selectors)

tests/resolve-defaults-at-rules.test.js

+55
Original file line numberDiff line numberDiff line change
@@ -772,3 +772,58 @@ crosscheck(() => {
772772
})
773773
})
774774
})
775+
776+
test('optimize universal defaults groups :has separately', () => {
777+
let config = {
778+
experimental: { optimizeUniversalDefaults: true },
779+
content: [
780+
{ raw: html`<div class="ring-1"></div>` },
781+
{ raw: html`<div class="has-[:checked]:ring-1"></div>` },
782+
],
783+
corePlugins: { preflight: false },
784+
}
785+
786+
let input = css`
787+
@tailwind base;
788+
@tailwind utilities;
789+
`
790+
791+
return run(input, config).then((result) => {
792+
return expect(result.css).toMatchFormattedCss(css`
793+
.ring-1 {
794+
--tw-ring-inset: ;
795+
--tw-ring-offset-width: 0px;
796+
--tw-ring-offset-color: #fff;
797+
--tw-ring-color: #3b82f680;
798+
--tw-ring-offset-shadow: 0 0 #0000;
799+
--tw-ring-shadow: 0 0 #0000;
800+
--tw-shadow: 0 0 #0000;
801+
--tw-shadow-colored: 0 0 #0000;
802+
}
803+
.has-\[\:checked\]\:ring-1:has(:checked) {
804+
--tw-ring-inset: ;
805+
--tw-ring-offset-width: 0px;
806+
--tw-ring-offset-color: #fff;
807+
--tw-ring-color: #3b82f680;
808+
--tw-ring-offset-shadow: 0 0 #0000;
809+
--tw-ring-shadow: 0 0 #0000;
810+
--tw-shadow: 0 0 #0000;
811+
--tw-shadow-colored: 0 0 #0000;
812+
}
813+
.ring-1 {
814+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
815+
var(--tw-ring-offset-color);
816+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width))
817+
var(--tw-ring-color);
818+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
819+
}
820+
.has-\[\:checked\]\:ring-1:has(:checked) {
821+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
822+
var(--tw-ring-offset-color);
823+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width))
824+
var(--tw-ring-color);
825+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
826+
}
827+
`)
828+
})
829+
})

0 commit comments

Comments
 (0)