From 9a5db88e54e47ec1812200f544c3e8aa317a79d5 Mon Sep 17 00:00:00 2001
From: Robin Malfait <malfait.robin@gmail.com>
Date: Thu, 9 Jun 2022 18:22:20 +0200
Subject: [PATCH 01/11] Fix candidate extractor regression (#8558)

* fix regression

This is a regression where `%>utility<%` didn't properly abstract
`utility`

* update changelog
---
 CHANGELOG.md                    |  4 +++-
 src/lib/defaultExtractor.js     |  4 ++--
 tests/default-extractor.test.js | 11 +++++++++++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bbe8c35dbcae..521b39bba276 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
-- Nothing yet!
+### Fixed
+
+- Fix candidate extractor regression ([#8558](https://github.com/tailwindlabs/tailwindcss/pull/8558))
 
 ## [3.1.0] - 2022-06-08
 
diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js
index 973250ea4d5a..98bc7386baca 100644
--- a/src/lib/defaultExtractor.js
+++ b/src/lib/defaultExtractor.js
@@ -43,7 +43,7 @@ function* buildRegExps(context) {
             /(?![{([]])/,
 
             // optionally followed by an opacity modifier
-            /(?:\/[^\s'"\\$]*)?/,
+            /(?:\/[^\s'"\\><$]*)?/,
           ]),
 
           regex.pattern([
@@ -58,7 +58,7 @@ function* buildRegExps(context) {
           ]),
 
           // Normal values w/o quotes — may include an opacity modifier
-          /[-\/][^\s'"\\$={]*/,
+          /[-\/][^\s'"\\$={><]*/,
         ])
       ),
     ]),
diff --git a/tests/default-extractor.test.js b/tests/default-extractor.test.js
index 789f2eb5d685..4e1792e8e7b9 100644
--- a/tests/default-extractor.test.js
+++ b/tests/default-extractor.test.js
@@ -438,3 +438,14 @@ test('with double quotes array within function', async () => {
   expect(extractions).toContain('pl-1.5')
   expect(extractions).not.toContain('pl-1')
 })
+
+test('with angle brackets', async () => {
+  const extractions = defaultExtractor(
+    `<div class="bg-blue-200 <% if (useShadow) { %>shadow-xl<% } %>">test</div>`
+  )
+
+  expect(extractions).toContain('bg-blue-200')
+  expect(extractions).toContain('shadow-xl')
+  expect(extractions).not.toContain('>shadow-xl')
+  expect(extractions).not.toContain('shadow-xl<')
+})

From 7aa2d4ddf3e755a24123a6d3157a32b7bffea7d8 Mon Sep 17 00:00:00 2001
From: Jordan Pittman <jordan@cryptica.me>
Date: Thu, 9 Jun 2022 14:09:57 -0400
Subject: [PATCH 02/11] =?UTF-8?q?Don=E2=80=99t=20clip=20slashes=20inside?=
 =?UTF-8?q?=20brackets=20when=20using=20the=20theme=20function=20(#8563)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/lib/evaluateTailwindFunctions.js    |  2 +-
 tests/evaluateTailwindFunctions.test.js | 31 +++++++++++++++++++++++
 tests/opacity.test.js                   | 33 +++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/src/lib/evaluateTailwindFunctions.js b/src/lib/evaluateTailwindFunctions.js
index 2b755394cbd0..4239d411cb17 100644
--- a/src/lib/evaluateTailwindFunctions.js
+++ b/src/lib/evaluateTailwindFunctions.js
@@ -162,7 +162,7 @@ let nodeTypePropertyMap = {
 export default function ({ tailwindConfig: config }) {
   let functions = {
     theme: (node, path, ...defaultValue) => {
-      let matches = path.match(/^([^\/\s]+)(?:\s*\/\s*([^\/\s]+))$/)
+      let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/)
       let alpha = undefined
 
       if (matches) {
diff --git a/tests/evaluateTailwindFunctions.test.js b/tests/evaluateTailwindFunctions.test.js
index d14e95e85ce3..657cb35b5849 100644
--- a/tests/evaluateTailwindFunctions.test.js
+++ b/tests/evaluateTailwindFunctions.test.js
@@ -1024,3 +1024,34 @@ test('Theme function can extract alpha values for colors (8)', () => {
     expect(result.warnings().length).toBe(0)
   })
 })
+
+test('Theme functions can reference values with slashes in brackets', () => {
+  let input = css`
+    .foo1 {
+      color: theme(colors[a/b]);
+    }
+    .foo2 {
+      color: theme(colors[a/b]/50%);
+    }
+  `
+
+  let output = css`
+    .foo1 {
+      color: #000000;
+    }
+    .foo2 {
+      color: rgb(0 0 0 / 50%);
+    }
+  `
+
+  return runFull(input, {
+    theme: {
+      colors: {
+        'a/b': '#000000',
+      },
+    },
+  }).then((result) => {
+    expect(result.css).toMatchCss(output)
+    expect(result.warnings().length).toBe(0)
+  })
+})
diff --git a/tests/opacity.test.js b/tests/opacity.test.js
index 38ea4ab44142..7215d14db332 100644
--- a/tests/opacity.test.js
+++ b/tests/opacity.test.js
@@ -728,3 +728,36 @@ it('should be possible to use <alpha-value> inside arbitrary values', () => {
     `)
   })
 })
+
+it('Theme functions can reference values with slashes in brackets', () => {
+  let config = {
+    content: [
+      {
+        raw: html` <div class="bg-foo1 bg-foo2"></div> `,
+      },
+    ],
+    theme: {
+      colors: {
+        'a/b': '#000000',
+      },
+      extend: {
+        backgroundColor: ({ theme }) => ({
+          foo1: theme('colors[a/b]'),
+          foo2: theme('colors[a/b]/50%'),
+        }),
+      },
+    },
+  }
+
+  return run('@tailwind utilities', config).then((result) => {
+    expect(result.css).toMatchCss(css`
+      .bg-foo1 {
+        --tw-bg-opacity: 1;
+        background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+      }
+      .bg-foo2 {
+        background-color: rgb(0 0 0 / 50%);
+      }
+    `)
+  })
+})

From 6b1eb19079a150515fe743faa20e559c9348282f Mon Sep 17 00:00:00 2001
From: Jordan Pittman <jordan@cryptica.me>
Date: Thu, 9 Jun 2022 16:26:18 -0400
Subject: [PATCH 03/11] Split `::backdrop` into separate defaults group (#8567)

* Split `::backdrop` into separate defaults group

* Update tests

* Update changelog
---
 CHANGELOG.md                                 |   1 +
 src/lib/resolveDefaultsAtRules.js            |  89 ++++---
 tests/__snapshots__/source-maps.test.js.snap |  46 ++++
 tests/basic-usage.test.css                   |  47 +++-
 tests/basic-usage.test.js                    |  53 +---
 tests/collapse-adjacent-rules.test.css       |  47 +++-
 tests/import-syntax.test.css                 |  47 +++-
 tests/important-boolean.test.css             |  47 +++-
 tests/important-modifier-prefix.test.css     |  47 +++-
 tests/important-selector.test.css            |  47 +++-
 tests/kitchen-sink.test.css                  |  47 +++-
 tests/plugins/divide.test.js                 | 252 +------------------
 tests/prefix.test.css                        |  47 +++-
 tests/resolve-defaults-at-rules.test.js      |  91 ++++++-
 tests/util/defaults.js                       |  47 +++-
 tests/variants.test.css                      |  47 +++-
 16 files changed, 650 insertions(+), 352 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 521b39bba276..e47c13172cc7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Fixed
 
 - Fix candidate extractor regression ([#8558](https://github.com/tailwindlabs/tailwindcss/pull/8558))
+- Split `::backdrop`` into separate defaults group ([#8567](https://github.com/tailwindlabs/tailwindcss/pull/8567))
 
 ## [3.1.0] - 2022-06-08
 
diff --git a/src/lib/resolveDefaultsAtRules.js b/src/lib/resolveDefaultsAtRules.js
index 62cf03c54440..389ea4bacac7 100644
--- a/src/lib/resolveDefaultsAtRules.js
+++ b/src/lib/resolveDefaultsAtRules.js
@@ -91,56 +91,73 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) {
       rule.remove()
     })
 
-    for (let universal of universals) {
-      /** @type {Map<string, Set<string>>} */
-      let selectorGroups = new Map()
+    if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
+      for (let universal of universals) {
+        /** @type {Map<string, Set<string>>} */
+        let selectorGroups = new Map()
+
+        let rules = variableNodeMap.get(universal.params) ?? []
+
+        for (let rule of rules) {
+          for (let selector of extractElementSelector(rule.selector)) {
+            // If selector contains a vendor prefix after a pseudo element or class,
+            // we consider them separately because merging the declarations into
+            // a single rule will cause browsers that do not understand the
+            // vendor prefix to throw out the whole rule
+            let selectorGroupName =
+              selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'
+
+            let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
+            selectorGroups.set(selectorGroupName, selectors)
+
+            selectors.add(selector)
+          }
+        }
 
-      let rules = variableNodeMap.get(universal.params) ?? []
+        if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
+          if (selectorGroups.size === 0) {
+            universal.remove()
+            continue
+          }
 
-      for (let rule of rules) {
-        for (let selector of extractElementSelector(rule.selector)) {
-          // If selector contains a vendor prefix after a pseudo element or class,
-          // we consider them separately because merging the declarations into
-          // a single rule will cause browsers that do not understand the
-          // vendor prefix to throw out the whole rule
-          let selectorGroupName =
-            selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'
+          for (let [, selectors] of selectorGroups) {
+            let universalRule = postcss.rule({
+              source: universal.source,
+            })
 
-          let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
-          selectorGroups.set(selectorGroupName, selectors)
+            universalRule.selectors = [...selectors]
 
-          selectors.add(selector)
+            universalRule.append(universal.nodes.map((node) => node.clone()))
+            universal.before(universalRule)
+          }
         }
-      }
 
-      if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
-        if (selectorGroups.size === 0) {
-          universal.remove()
-          continue
-        }
-
-        for (let [, selectors] of selectorGroups) {
-          let universalRule = postcss.rule({
-            source: universal.source,
-          })
+        universal.remove()
+      }
+    } else if (universals.size) {
+      let universalRule = postcss.rule({
+        selectors: ['*', '::before', '::after'],
+      })
 
-          universalRule.selectors = [...selectors]
+      for (let universal of universals) {
+        universalRule.append(universal.nodes)
 
-          universalRule.append(universal.nodes.map((node) => node.clone()))
+        if (!universalRule.parent) {
           universal.before(universalRule)
         }
-      } else {
-        let universalRule = postcss.rule({
-          source: universal.source,
-        })
 
-        universalRule.selectors = ['*', '::before', '::after', '::backdrop']
+        if (!universalRule.source) {
+          universalRule.source = universal.source
+        }
 
-        universalRule.append(universal.nodes)
-        universal.before(universalRule)
+        universal.remove()
       }
 
-      universal.remove()
+      let backdropRule = universalRule.clone({
+        selectors: ['::backdrop'],
+      })
+
+      universalRule.after(backdropRule)
     }
   }
 }
diff --git a/tests/__snapshots__/source-maps.test.js.snap b/tests/__snapshots__/source-maps.test.js.snap
index 32fc16e22b6a..e7aca966cd7e 100644
--- a/tests/__snapshots__/source-maps.test.js.snap
+++ b/tests/__snapshots__/source-maps.test.js.snap
@@ -309,5 +309,51 @@ Array [
   "2:4-18 -> 407:2-27",
   "2:4 -> 408:2",
   "2:18 -> 409:0",
+  "2:4 -> 411:0",
+  "2:4-18 -> 412:2-26",
+  "2:4-18 -> 413:2-26",
+  "2:4-18 -> 414:2-21",
+  "2:4-18 -> 415:2-21",
+  "2:4-18 -> 416:2-16",
+  "2:4-18 -> 417:2-16",
+  "2:4-18 -> 418:2-16",
+  "2:4-18 -> 419:2-17",
+  "2:4-18 -> 420:2-17",
+  "2:4-18 -> 421:2-15",
+  "2:4-18 -> 422:2-15",
+  "2:4-18 -> 423:2-20",
+  "2:4-18 -> 424:2-40",
+  "2:4-18 -> 425:2-17",
+  "2:4-18 -> 426:2-22",
+  "2:4-18 -> 427:2-24",
+  "2:4-18 -> 428:2-25",
+  "2:4-18 -> 429:2-26",
+  "2:4-18 -> 430:2-20",
+  "2:4-18 -> 431:2-29",
+  "2:4-18 -> 432:2-30",
+  "2:4-18 -> 433:2-40",
+  "2:4-18 -> 434:2-36",
+  "2:4-18 -> 435:2-29",
+  "2:4-18 -> 436:2-24",
+  "2:4-18 -> 437:2-32",
+  "2:4-18 -> 438:2-14",
+  "2:4-18 -> 439:2-20",
+  "2:4-18 -> 440:2-18",
+  "2:4-18 -> 441:2-19",
+  "2:4-18 -> 442:2-20",
+  "2:4-18 -> 443:2-16",
+  "2:4-18 -> 444:2-18",
+  "2:4-18 -> 445:2-15",
+  "2:4-18 -> 446:2-21",
+  "2:4-18 -> 447:2-23",
+  "2:4-18 -> 448:2-29",
+  "2:4-18 -> 449:2-27",
+  "2:4-18 -> 450:2-28",
+  "2:4-18 -> 451:2-29",
+  "2:4-18 -> 452:2-25",
+  "2:4-18 -> 453:2-26",
+  "2:4-18 -> 454:2-27",
+  "2:4 -> 455:2",
+  "2:18 -> 456:0",
 ]
 `;
diff --git a/tests/basic-usage.test.css b/tests/basic-usage.test.css
index 187d31752e83..81781e635378 100644
--- a/tests/basic-usage.test.css
+++ b/tests/basic-usage.test.css
@@ -1,6 +1,51 @@
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/basic-usage.test.js b/tests/basic-usage.test.js
index 0abd091a7169..e72596615c84 100644
--- a/tests/basic-usage.test.js
+++ b/tests/basic-usage.test.js
@@ -149,56 +149,7 @@ test('default ring color can be a function', () => {
 
   return run(input, config).then((result) => {
     expect(result.css).toMatchFormattedCss(css`
-      *,
-      ::before,
-      ::after,
-      ::backdrop {
-        --tw-border-spacing-x: 0;
-        --tw-border-spacing-y: 0;
-        --tw-translate-x: 0;
-        --tw-translate-y: 0;
-        --tw-rotate: 0;
-        --tw-skew-x: 0;
-        --tw-skew-y: 0;
-        --tw-scale-x: 1;
-        --tw-scale-y: 1;
-        --tw-pan-x: ;
-        --tw-pan-y: ;
-        --tw-pinch-zoom: ;
-        --tw-scroll-snap-strictness: proximity;
-        --tw-ordinal: ;
-        --tw-slashed-zero: ;
-        --tw-numeric-figure: ;
-        --tw-numeric-spacing: ;
-        --tw-numeric-fraction: ;
-        --tw-ring-inset: ;
-        --tw-ring-offset-width: 0px;
-        --tw-ring-offset-color: #fff;
-        --tw-ring-color: rgba(var(--red), 0.5);
-        --tw-ring-offset-shadow: 0 0 #0000;
-        --tw-ring-shadow: 0 0 #0000;
-        --tw-shadow: 0 0 #0000;
-        --tw-shadow-colored: 0 0 #0000;
-        --tw-blur: ;
-        --tw-brightness: ;
-        --tw-contrast: ;
-        --tw-grayscale: ;
-        --tw-hue-rotate: ;
-        --tw-invert: ;
-        --tw-saturate: ;
-        --tw-sepia: ;
-        --tw-drop-shadow: ;
-        --tw-backdrop-blur: ;
-        --tw-backdrop-brightness: ;
-        --tw-backdrop-contrast: ;
-        --tw-backdrop-grayscale: ;
-        --tw-backdrop-hue-rotate: ;
-        --tw-backdrop-invert: ;
-        --tw-backdrop-opacity: ;
-        --tw-backdrop-saturate: ;
-        --tw-backdrop-sepia: ;
-      }
-
+      ${defaults({ defaultRingColor: 'rgba(var(--red), 0.5)' })}
       .ring {
         --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
           var(--tw-ring-offset-color);
@@ -210,7 +161,7 @@ test('default ring color can be a function', () => {
   })
 })
 
-it('fasly config values still work', () => {
+it('falsy config values still work', () => {
   let config = {
     content: [{ raw: html`<div class="inset-0"></div>` }],
     theme: {
diff --git a/tests/collapse-adjacent-rules.test.css b/tests/collapse-adjacent-rules.test.css
index e29c0d71a451..98f4625d74e5 100644
--- a/tests/collapse-adjacent-rules.test.css
+++ b/tests/collapse-adjacent-rules.test.css
@@ -9,7 +9,52 @@
 }
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/import-syntax.test.css b/tests/import-syntax.test.css
index d9de35ecca61..c01e767117d6 100644
--- a/tests/import-syntax.test.css
+++ b/tests/import-syntax.test.css
@@ -3,7 +3,52 @@ h1 {
 }
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/important-boolean.test.css b/tests/important-boolean.test.css
index 7ffaacb2264a..8e2a865f39ee 100644
--- a/tests/important-boolean.test.css
+++ b/tests/important-boolean.test.css
@@ -1,6 +1,51 @@
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/important-modifier-prefix.test.css b/tests/important-modifier-prefix.test.css
index babc9354eed7..615d537b865f 100644
--- a/tests/important-modifier-prefix.test.css
+++ b/tests/important-modifier-prefix.test.css
@@ -1,6 +1,51 @@
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/important-selector.test.css b/tests/important-selector.test.css
index 32fd60e18507..7f15a668eeed 100644
--- a/tests/important-selector.test.css
+++ b/tests/important-selector.test.css
@@ -1,6 +1,51 @@
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/kitchen-sink.test.css b/tests/kitchen-sink.test.css
index 9883eb1c536c..2785325a8891 100644
--- a/tests/kitchen-sink.test.css
+++ b/tests/kitchen-sink.test.css
@@ -138,7 +138,52 @@ div {
 }
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/plugins/divide.test.js b/tests/plugins/divide.test.js
index d56dbfa16fcc..e50ea4e4fc33 100644
--- a/tests/plugins/divide.test.js
+++ b/tests/plugins/divide.test.js
@@ -1,4 +1,4 @@
-import { run, html, css } from '../util/run'
+import { run, html, css, defaults } from '../util/run'
 
 it('should add the divide styles for divide-y and a default border color', () => {
   let config = {
@@ -8,55 +8,7 @@ it('should add the divide styles for divide-y and a default border color', () =>
 
   return run('@tailwind base; @tailwind utilities;', config).then((result) => {
     expect(result.css).toMatchCss(css`
-      *,
-      ::before,
-      ::after,
-      ::backdrop {
-        --tw-border-spacing-x: 0;
-        --tw-border-spacing-y: 0;
-        --tw-translate-x: 0;
-        --tw-translate-y: 0;
-        --tw-rotate: 0;
-        --tw-skew-x: 0;
-        --tw-skew-y: 0;
-        --tw-scale-x: 1;
-        --tw-scale-y: 1;
-        --tw-pan-x: ;
-        --tw-pan-y: ;
-        --tw-pinch-zoom: ;
-        --tw-scroll-snap-strictness: proximity;
-        --tw-ordinal: ;
-        --tw-slashed-zero: ;
-        --tw-numeric-figure: ;
-        --tw-numeric-spacing: ;
-        --tw-numeric-fraction: ;
-        --tw-ring-inset: ;
-        --tw-ring-offset-width: 0px;
-        --tw-ring-offset-color: #fff;
-        --tw-ring-color: rgb(59 130 246 / 0.5);
-        --tw-ring-offset-shadow: 0 0 #0000;
-        --tw-ring-shadow: 0 0 #0000;
-        --tw-shadow: 0 0 #0000;
-        --tw-shadow-colored: 0 0 #0000;
-        --tw-blur: ;
-        --tw-brightness: ;
-        --tw-contrast: ;
-        --tw-grayscale: ;
-        --tw-hue-rotate: ;
-        --tw-invert: ;
-        --tw-saturate: ;
-        --tw-sepia: ;
-        --tw-drop-shadow: ;
-        --tw-backdrop-blur: ;
-        --tw-backdrop-brightness: ;
-        --tw-backdrop-contrast: ;
-        --tw-backdrop-grayscale: ;
-        --tw-backdrop-hue-rotate: ;
-        --tw-backdrop-invert: ;
-        --tw-backdrop-opacity: ;
-        --tw-backdrop-saturate: ;
-        --tw-backdrop-sepia: ;
-      }
+      ${defaults}
 
       .divide-y > :not([hidden]) ~ :not([hidden]) {
         --tw-divide-y-reverse: 0;
@@ -75,55 +27,7 @@ it('should add the divide styles for divide-x and a default border color', () =>
 
   return run('@tailwind base; @tailwind utilities;', config).then((result) => {
     expect(result.css).toMatchCss(css`
-      *,
-      ::before,
-      ::after,
-      ::backdrop {
-        --tw-border-spacing-x: 0;
-        --tw-border-spacing-y: 0;
-        --tw-translate-x: 0;
-        --tw-translate-y: 0;
-        --tw-rotate: 0;
-        --tw-skew-x: 0;
-        --tw-skew-y: 0;
-        --tw-scale-x: 1;
-        --tw-scale-y: 1;
-        --tw-pan-x: ;
-        --tw-pan-y: ;
-        --tw-pinch-zoom: ;
-        --tw-scroll-snap-strictness: proximity;
-        --tw-ordinal: ;
-        --tw-slashed-zero: ;
-        --tw-numeric-figure: ;
-        --tw-numeric-spacing: ;
-        --tw-numeric-fraction: ;
-        --tw-ring-inset: ;
-        --tw-ring-offset-width: 0px;
-        --tw-ring-offset-color: #fff;
-        --tw-ring-color: rgb(59 130 246 / 0.5);
-        --tw-ring-offset-shadow: 0 0 #0000;
-        --tw-ring-shadow: 0 0 #0000;
-        --tw-shadow: 0 0 #0000;
-        --tw-shadow-colored: 0 0 #0000;
-        --tw-blur: ;
-        --tw-brightness: ;
-        --tw-contrast: ;
-        --tw-grayscale: ;
-        --tw-hue-rotate: ;
-        --tw-invert: ;
-        --tw-saturate: ;
-        --tw-sepia: ;
-        --tw-drop-shadow: ;
-        --tw-backdrop-blur: ;
-        --tw-backdrop-brightness: ;
-        --tw-backdrop-contrast: ;
-        --tw-backdrop-grayscale: ;
-        --tw-backdrop-hue-rotate: ;
-        --tw-backdrop-invert: ;
-        --tw-backdrop-opacity: ;
-        --tw-backdrop-saturate: ;
-        --tw-backdrop-sepia: ;
-      }
+      ${defaults}
 
       .divide-x > :not([hidden]) ~ :not([hidden]) {
         --tw-divide-x-reverse: 0;
@@ -142,55 +46,7 @@ it('should add the divide styles for divide-y-reverse and a default border color
 
   return run('@tailwind base; @tailwind utilities;', config).then((result) => {
     expect(result.css).toMatchCss(css`
-      *,
-      ::before,
-      ::after,
-      ::backdrop {
-        --tw-border-spacing-x: 0;
-        --tw-border-spacing-y: 0;
-        --tw-translate-x: 0;
-        --tw-translate-y: 0;
-        --tw-rotate: 0;
-        --tw-skew-x: 0;
-        --tw-skew-y: 0;
-        --tw-scale-x: 1;
-        --tw-scale-y: 1;
-        --tw-pan-x: ;
-        --tw-pan-y: ;
-        --tw-pinch-zoom: ;
-        --tw-scroll-snap-strictness: proximity;
-        --tw-ordinal: ;
-        --tw-slashed-zero: ;
-        --tw-numeric-figure: ;
-        --tw-numeric-spacing: ;
-        --tw-numeric-fraction: ;
-        --tw-ring-inset: ;
-        --tw-ring-offset-width: 0px;
-        --tw-ring-offset-color: #fff;
-        --tw-ring-color: rgb(59 130 246 / 0.5);
-        --tw-ring-offset-shadow: 0 0 #0000;
-        --tw-ring-shadow: 0 0 #0000;
-        --tw-shadow: 0 0 #0000;
-        --tw-shadow-colored: 0 0 #0000;
-        --tw-blur: ;
-        --tw-brightness: ;
-        --tw-contrast: ;
-        --tw-grayscale: ;
-        --tw-hue-rotate: ;
-        --tw-invert: ;
-        --tw-saturate: ;
-        --tw-sepia: ;
-        --tw-drop-shadow: ;
-        --tw-backdrop-blur: ;
-        --tw-backdrop-brightness: ;
-        --tw-backdrop-contrast: ;
-        --tw-backdrop-grayscale: ;
-        --tw-backdrop-hue-rotate: ;
-        --tw-backdrop-invert: ;
-        --tw-backdrop-opacity: ;
-        --tw-backdrop-saturate: ;
-        --tw-backdrop-sepia: ;
-      }
+      ${defaults}
 
       .divide-y-reverse > :not([hidden]) ~ :not([hidden]) {
         --tw-divide-y-reverse: 1;
@@ -207,55 +63,7 @@ it('should add the divide styles for divide-x-reverse and a default border color
 
   return run('@tailwind base; @tailwind utilities;', config).then((result) => {
     expect(result.css).toMatchCss(css`
-      *,
-      ::before,
-      ::after,
-      ::backdrop {
-        --tw-border-spacing-x: 0;
-        --tw-border-spacing-y: 0;
-        --tw-translate-x: 0;
-        --tw-translate-y: 0;
-        --tw-rotate: 0;
-        --tw-skew-x: 0;
-        --tw-skew-y: 0;
-        --tw-scale-x: 1;
-        --tw-scale-y: 1;
-        --tw-pan-x: ;
-        --tw-pan-y: ;
-        --tw-pinch-zoom: ;
-        --tw-scroll-snap-strictness: proximity;
-        --tw-ordinal: ;
-        --tw-slashed-zero: ;
-        --tw-numeric-figure: ;
-        --tw-numeric-spacing: ;
-        --tw-numeric-fraction: ;
-        --tw-ring-inset: ;
-        --tw-ring-offset-width: 0px;
-        --tw-ring-offset-color: #fff;
-        --tw-ring-color: rgb(59 130 246 / 0.5);
-        --tw-ring-offset-shadow: 0 0 #0000;
-        --tw-ring-shadow: 0 0 #0000;
-        --tw-shadow: 0 0 #0000;
-        --tw-shadow-colored: 0 0 #0000;
-        --tw-blur: ;
-        --tw-brightness: ;
-        --tw-contrast: ;
-        --tw-grayscale: ;
-        --tw-hue-rotate: ;
-        --tw-invert: ;
-        --tw-saturate: ;
-        --tw-sepia: ;
-        --tw-drop-shadow: ;
-        --tw-backdrop-blur: ;
-        --tw-backdrop-brightness: ;
-        --tw-backdrop-contrast: ;
-        --tw-backdrop-grayscale: ;
-        --tw-backdrop-hue-rotate: ;
-        --tw-backdrop-invert: ;
-        --tw-backdrop-opacity: ;
-        --tw-backdrop-saturate: ;
-        --tw-backdrop-sepia: ;
-      }
+      ${defaults}
 
       .divide-x-reverse > :not([hidden]) ~ :not([hidden]) {
         --tw-divide-x-reverse: 1;
@@ -272,55 +80,7 @@ it('should only inject the base styles once if we use divide and border at the s
 
   return run('@tailwind base; @tailwind utilities;', config).then((result) => {
     expect(result.css).toMatchCss(css`
-      *,
-      ::before,
-      ::after,
-      ::backdrop {
-        --tw-border-spacing-x: 0;
-        --tw-border-spacing-y: 0;
-        --tw-translate-x: 0;
-        --tw-translate-y: 0;
-        --tw-rotate: 0;
-        --tw-skew-x: 0;
-        --tw-skew-y: 0;
-        --tw-scale-x: 1;
-        --tw-scale-y: 1;
-        --tw-pan-x: ;
-        --tw-pan-y: ;
-        --tw-pinch-zoom: ;
-        --tw-scroll-snap-strictness: proximity;
-        --tw-ordinal: ;
-        --tw-slashed-zero: ;
-        --tw-numeric-figure: ;
-        --tw-numeric-spacing: ;
-        --tw-numeric-fraction: ;
-        --tw-ring-inset: ;
-        --tw-ring-offset-width: 0px;
-        --tw-ring-offset-color: #fff;
-        --tw-ring-color: rgb(59 130 246 / 0.5);
-        --tw-ring-offset-shadow: 0 0 #0000;
-        --tw-ring-shadow: 0 0 #0000;
-        --tw-shadow: 0 0 #0000;
-        --tw-shadow-colored: 0 0 #0000;
-        --tw-blur: ;
-        --tw-brightness: ;
-        --tw-contrast: ;
-        --tw-grayscale: ;
-        --tw-hue-rotate: ;
-        --tw-invert: ;
-        --tw-saturate: ;
-        --tw-sepia: ;
-        --tw-drop-shadow: ;
-        --tw-backdrop-blur: ;
-        --tw-backdrop-brightness: ;
-        --tw-backdrop-contrast: ;
-        --tw-backdrop-grayscale: ;
-        --tw-backdrop-hue-rotate: ;
-        --tw-backdrop-invert: ;
-        --tw-backdrop-opacity: ;
-        --tw-backdrop-saturate: ;
-        --tw-backdrop-sepia: ;
-      }
+      ${defaults}
 
       .divide-y > :not([hidden]) ~ :not([hidden]) {
         --tw-divide-y-reverse: 0;
diff --git a/tests/prefix.test.css b/tests/prefix.test.css
index 10e75666618d..b749e1a9eec6 100644
--- a/tests/prefix.test.css
+++ b/tests/prefix.test.css
@@ -1,6 +1,51 @@
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;
diff --git a/tests/resolve-defaults-at-rules.test.js b/tests/resolve-defaults-at-rules.test.js
index d316a604ddc1..45f9872a03f4 100644
--- a/tests/resolve-defaults-at-rules.test.js
+++ b/tests/resolve-defaults-at-rules.test.js
@@ -16,7 +16,15 @@ test('basic utilities', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
@@ -68,7 +76,15 @@ test('with pseudo-class variants', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
@@ -118,7 +134,15 @@ test('with pseudo-element variants', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
@@ -164,7 +188,15 @@ test('with multi-class variants', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
@@ -210,7 +242,15 @@ test('with multi-class pseudo-element variants', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
@@ -262,7 +302,15 @@ test('with multi-class pseudo-element and pseudo-class variants', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
@@ -350,7 +398,15 @@ test('with apply', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
@@ -547,7 +603,16 @@ test('with shadows', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-ring-inset: ;
+        --tw-ring-offset-width: 0px;
+        --tw-ring-offset-color: #fff;
+        --tw-ring-color: rgb(59 130 246 / 0.5);
+        --tw-ring-offset-shadow: 0 0 #0000;
+        --tw-ring-shadow: 0 0 #0000;
+        --tw-shadow: 0 0 #0000;
+        --tw-shadow-colored: 0 0 #0000;
+      }
       ::backdrop {
         --tw-ring-inset: ;
         --tw-ring-offset-width: 0px;
@@ -606,7 +671,15 @@ test('when no utilities that need the defaults are used', async () => {
     expect(result.css).toMatchFormattedCss(css`
       *,
       ::before,
-      ::after,
+      ::after {
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+      }
       ::backdrop {
         --tw-translate-x: 0;
         --tw-translate-y: 0;
diff --git a/tests/util/defaults.js b/tests/util/defaults.js
index 061bcc854e98..bc65e2e8e646 100644
--- a/tests/util/defaults.js
+++ b/tests/util/defaults.js
@@ -9,7 +9,52 @@ export function defaults({ defaultRingColor = `rgb(59 130 246 / 0.5)` } = {}) {
   return css`
     *,
     ::before,
-    ::after,
+    ::after {
+      --tw-border-spacing-x: 0;
+      --tw-border-spacing-y: 0;
+      --tw-translate-x: 0;
+      --tw-translate-y: 0;
+      --tw-rotate: 0;
+      --tw-skew-x: 0;
+      --tw-skew-y: 0;
+      --tw-scale-x: 1;
+      --tw-scale-y: 1;
+      --tw-pan-x: ;
+      --tw-pan-y: ;
+      --tw-pinch-zoom: ;
+      --tw-scroll-snap-strictness: proximity;
+      --tw-ordinal: ;
+      --tw-slashed-zero: ;
+      --tw-numeric-figure: ;
+      --tw-numeric-spacing: ;
+      --tw-numeric-fraction: ;
+      --tw-ring-inset: ;
+      --tw-ring-offset-width: 0px;
+      --tw-ring-offset-color: #fff;
+      --tw-ring-color: ${defaultRingColor};
+      --tw-ring-offset-shadow: 0 0 #0000;
+      --tw-ring-shadow: 0 0 #0000;
+      --tw-shadow: 0 0 #0000;
+      --tw-shadow-colored: 0 0 #0000;
+      --tw-blur: ;
+      --tw-brightness: ;
+      --tw-contrast: ;
+      --tw-grayscale: ;
+      --tw-hue-rotate: ;
+      --tw-invert: ;
+      --tw-saturate: ;
+      --tw-sepia: ;
+      --tw-drop-shadow: ;
+      --tw-backdrop-blur: ;
+      --tw-backdrop-brightness: ;
+      --tw-backdrop-contrast: ;
+      --tw-backdrop-grayscale: ;
+      --tw-backdrop-hue-rotate: ;
+      --tw-backdrop-invert: ;
+      --tw-backdrop-opacity: ;
+      --tw-backdrop-saturate: ;
+      --tw-backdrop-sepia: ;
+    }
     ::backdrop {
       --tw-border-spacing-x: 0;
       --tw-border-spacing-y: 0;
diff --git a/tests/variants.test.css b/tests/variants.test.css
index 7debafd76e11..535ffa23177e 100644
--- a/tests/variants.test.css
+++ b/tests/variants.test.css
@@ -1,6 +1,51 @@
 *,
 ::before,
-::after,
+::after {
+  --tw-border-spacing-x: 0;
+  --tw-border-spacing-y: 0;
+  --tw-translate-x: 0;
+  --tw-translate-y: 0;
+  --tw-rotate: 0;
+  --tw-skew-x: 0;
+  --tw-skew-y: 0;
+  --tw-scale-x: 1;
+  --tw-scale-y: 1;
+  --tw-pan-x: ;
+  --tw-pan-y: ;
+  --tw-pinch-zoom: ;
+  --tw-scroll-snap-strictness: proximity;
+  --tw-ordinal: ;
+  --tw-slashed-zero: ;
+  --tw-numeric-figure: ;
+  --tw-numeric-spacing: ;
+  --tw-numeric-fraction: ;
+  --tw-ring-inset: ;
+  --tw-ring-offset-width: 0px;
+  --tw-ring-offset-color: #fff;
+  --tw-ring-color: rgb(59 130 246 / 0.5);
+  --tw-ring-offset-shadow: 0 0 #0000;
+  --tw-ring-shadow: 0 0 #0000;
+  --tw-shadow: 0 0 #0000;
+  --tw-shadow-colored: 0 0 #0000;
+  --tw-blur: ;
+  --tw-brightness: ;
+  --tw-contrast: ;
+  --tw-grayscale: ;
+  --tw-hue-rotate: ;
+  --tw-invert: ;
+  --tw-saturate: ;
+  --tw-sepia: ;
+  --tw-drop-shadow: ;
+  --tw-backdrop-blur: ;
+  --tw-backdrop-brightness: ;
+  --tw-backdrop-contrast: ;
+  --tw-backdrop-grayscale: ;
+  --tw-backdrop-hue-rotate: ;
+  --tw-backdrop-invert: ;
+  --tw-backdrop-opacity: ;
+  --tw-backdrop-saturate: ;
+  --tw-backdrop-sepia: ;
+}
 ::backdrop {
   --tw-border-spacing-x: 0;
   --tw-border-spacing-y: 0;

From c44dd7b8e70e9ab633a33b4f82b6f23c914d8f3d Mon Sep 17 00:00:00 2001
From: Jordan Pittman <jordan@cryptica.me>
Date: Thu, 9 Jun 2022 16:38:45 -0400
Subject: [PATCH 04/11] Fix postcss plugin type (#8564)

* Fix postcss plugin type

* Update changelog
---
 CHANGELOG.md     | 1 +
 types/index.d.ts | 8 +++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e47c13172cc7..15dd1f44146e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 - Fix candidate extractor regression ([#8558](https://github.com/tailwindlabs/tailwindcss/pull/8558))
 - Split `::backdrop`` into separate defaults group ([#8567](https://github.com/tailwindlabs/tailwindcss/pull/8567))
+- Fix postcss plugin type ([#8564](https://github.com/tailwindlabs/tailwindcss/pull/8564))
 
 ## [3.1.0] - 2022-06-08
 
diff --git a/types/index.d.ts b/types/index.d.ts
index 11bec63ff25b..131877e77868 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -1 +1,7 @@
-export type { Config } from './config.d'
+import { PluginCreator } from 'postcss'
+import type { Config } from './config.d'
+
+declare const plugin: PluginCreator<string | Config | { config: string | Config }>
+
+export { Config }
+export default plugin

From 0664aae901b7b162c3b030276c78d8c2f086ead6 Mon Sep 17 00:00:00 2001
From: Jordan Pittman <jordan@cryptica.me>
Date: Thu, 9 Jun 2022 16:53:02 -0400
Subject: [PATCH 05/11] Fix class detection in markdown code fences and slim
 templates (#8569)

* Fix detection of classes in markdown code fences

* Fix candidate detection in `.slim` templates

* Update changelog
---
 CHANGELOG.md                    |  1 +
 src/lib/defaultExtractor.js     | 14 +++++++-------
 tests/default-extractor.test.js | 27 +++++++++++++++++++++++----
 3 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 15dd1f44146e..279413af424e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Fix candidate extractor regression ([#8558](https://github.com/tailwindlabs/tailwindcss/pull/8558))
 - Split `::backdrop`` into separate defaults group ([#8567](https://github.com/tailwindlabs/tailwindcss/pull/8567))
 - Fix postcss plugin type ([#8564](https://github.com/tailwindlabs/tailwindcss/pull/8564))
+- Fix class detection in markdown code fences and slim templates ([#8569](https://github.com/tailwindlabs/tailwindcss/pull/8569))
 
 ## [3.1.0] - 2022-06-08
 
diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js
index 98bc7386baca..c3e5b642cc3f 100644
--- a/src/lib/defaultExtractor.js
+++ b/src/lib/defaultExtractor.js
@@ -25,7 +25,7 @@ function* buildRegExps(context) {
 
   let utility = regex.any([
     // Arbitrary properties
-    /\[[^\s:'"]+:[^\s\]]+\]/,
+    /\[[^\s:'"`]+:[^\s\]]+\]/,
 
     // Utilities
     regex.pattern([
@@ -43,7 +43,7 @@ function* buildRegExps(context) {
             /(?![{([]])/,
 
             // optionally followed by an opacity modifier
-            /(?:\/[^\s'"\\><$]*)?/,
+            /(?:\/[^\s'"`\\><$]*)?/,
           ]),
 
           regex.pattern([
@@ -54,11 +54,11 @@ function* buildRegExps(context) {
             /(?![{([]])/,
 
             // optionally followed by an opacity modifier
-            /(?:\/[^\s'"\\$]*)?/,
+            /(?:\/[^\s'"`\\$]*)?/,
           ]),
 
           // Normal values w/o quotes — may include an opacity modifier
-          /[-\/][^\s'"\\$={><]*/,
+          /[-\/][^\s'"`\\$={><]*/,
         ])
       ),
     ]),
@@ -69,8 +69,8 @@ function* buildRegExps(context) {
     '((?=((',
     regex.any(
       [
-        regex.pattern([/([^\s"'\[\\]+-)?\[[^\s"'\\]+\]/, separator]),
-        regex.pattern([/[^\s"'\[\\]+/, separator]),
+        regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`\\]+\]/, separator]),
+        regex.pattern([/[^\s"'`\[\\]+/, separator]),
       ],
       true
     ),
@@ -91,7 +91,7 @@ function* buildRegExps(context) {
   ])
 
   // 5. Inner matches
-  // yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
+  yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
 }
 
 // We want to capture any "special" characters
diff --git a/tests/default-extractor.test.js b/tests/default-extractor.test.js
index 4e1792e8e7b9..75abf4caebfd 100644
--- a/tests/default-extractor.test.js
+++ b/tests/default-extractor.test.js
@@ -415,28 +415,24 @@ test('with single quotes array within template literal', async () => {
   const extractions = defaultExtractor(`<div class=\`\${['pr-1.5']}\`></div>`)
 
   expect(extractions).toContain('pr-1.5')
-  expect(extractions).not.toContain('pr-1')
 })
 
 test('with double quotes array within template literal', async () => {
   const extractions = defaultExtractor(`<div class=\`\${["pr-1.5"]}\`></div>`)
 
   expect(extractions).toContain('pr-1.5')
-  expect(extractions).not.toContain('pr-1')
 })
 
 test('with single quotes array within function', async () => {
   const extractions = defaultExtractor(`document.body.classList.add(['pl-1.5'].join(" "));`)
 
   expect(extractions).toContain('pl-1.5')
-  expect(extractions).not.toContain('pl-1')
 })
 
 test('with double quotes array within function', async () => {
   const extractions = defaultExtractor(`document.body.classList.add(["pl-1.5"].join(" "));`)
 
   expect(extractions).toContain('pl-1.5')
-  expect(extractions).not.toContain('pl-1')
 })
 
 test('with angle brackets', async () => {
@@ -449,3 +445,26 @@ test('with angle brackets', async () => {
   expect(extractions).not.toContain('>shadow-xl')
   expect(extractions).not.toContain('shadow-xl<')
 })
+
+test('markdown code fences', async () => {
+  const extractions = defaultExtractor('<!-- this should work: `.font-bold`, `.font-normal` -->')
+
+  expect(extractions).toContain('font-bold')
+  expect(extractions).toContain('font-normal')
+  expect(extractions).not.toContain('.font-bold')
+  expect(extractions).not.toContain('.font-normal')
+})
+
+test('classes in slim templates', async () => {
+  const extractions = defaultExtractor(`
+    p.bg-red-500.text-sm
+      'This is a paragraph
+        small.italic.text-gray-500
+          '(Look mom, no closing tag!)
+  `)
+
+  expect(extractions).toContain('bg-red-500')
+  expect(extractions).toContain('text-sm')
+  expect(extractions).toContain('italic')
+  expect(extractions).toContain('text-gray-500')
+})

From 2a0415345e2a3a96303ccdec652f299a62f4047d Mon Sep 17 00:00:00 2001
From: Jordan Pittman <jordan@cryptica.me>
Date: Thu, 9 Jun 2022 16:55:25 -0400
Subject: [PATCH 06/11] Update changelog

---
 CHANGELOG.md | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 279413af424e..4986f9137736 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,10 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+- Nothing yet!
+
+## [3.1.1] - 2022-06-09
+
 ### Fixed
 
 - Fix candidate extractor regression ([#8558](https://github.com/tailwindlabs/tailwindcss/pull/8558))
-- Split `::backdrop`` into separate defaults group ([#8567](https://github.com/tailwindlabs/tailwindcss/pull/8567))
+- Split `::backdrop` into separate defaults group ([#8567](https://github.com/tailwindlabs/tailwindcss/pull/8567))
 - Fix postcss plugin type ([#8564](https://github.com/tailwindlabs/tailwindcss/pull/8564))
 - Fix class detection in markdown code fences and slim templates ([#8569](https://github.com/tailwindlabs/tailwindcss/pull/8569))
 
@@ -1957,7 +1961,8 @@ No release notes
 
 - Everything!
 
-[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.0...HEAD
+[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.1...HEAD
+[3.1.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.0...v3.1.1
 [3.1.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.24...v3.1.0
 [3.0.24]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.23...v3.0.24
 [3.0.23]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.22...v3.0.23

From 3f2e570ed49f1863a3b0d2a4cb3634fe2b1561d6 Mon Sep 17 00:00:00 2001
From: Jordan Pittman <jordan@cryptica.me>
Date: Thu, 9 Jun 2022 16:55:44 -0400
Subject: [PATCH 07/11] 3.1.1

---
 package-lock.json | 4 ++--
 package.json      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 72ddeaf5d25f..30dfbc39da76 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "tailwindcss",
-  "version": "3.1.0",
+  "version": "3.1.1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "tailwindcss",
-      "version": "3.1.0",
+      "version": "3.1.1",
       "license": "MIT",
       "dependencies": {
         "arg": "^5.0.1",
diff --git a/package.json b/package.json
index c93d04285ad3..39aac411ecb1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tailwindcss",
-  "version": "3.1.0",
+  "version": "3.1.1",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "main": "lib/index.js",

From d32728b433af5d0ac63e01915d27bd1157138f24 Mon Sep 17 00:00:00 2001
From: Robin Malfait <malfait.robin@gmail.com>
Date: Fri, 10 Jun 2022 10:51:16 +0200
Subject: [PATCH 08/11] Ensure `\` is a valid arbitrary variant token (#8576)

* `\` are valid arbitrary variant tokens

We use `\` for escaping `.` or `_` so they should be part of the
arbitrary variant regex.

* update changelog
---
 CHANGELOG.md                     |  4 +-
 src/lib/defaultExtractor.js      |  2 +-
 tests/arbitrary-variants.test.js | 88 ++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4986f9137736..9aa357f03839 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
-- Nothing yet!
+### Fixed
+
+- Ensure `\` is a valid arbitrary variant token ([#8576](https://github.com/tailwindlabs/tailwindcss/pull/8576))
 
 ## [3.1.1] - 2022-06-09
 
diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js
index c3e5b642cc3f..fa2cc92b8f17 100644
--- a/src/lib/defaultExtractor.js
+++ b/src/lib/defaultExtractor.js
@@ -69,7 +69,7 @@ function* buildRegExps(context) {
     '((?=((',
     regex.any(
       [
-        regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`\\]+\]/, separator]),
+        regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
         regex.pattern([/[^\s"'`\[\\]+/, separator]),
       ],
       true
diff --git a/tests/arbitrary-variants.test.js b/tests/arbitrary-variants.test.js
index ffa4a70732d4..d0f7d85b5482 100644
--- a/tests/arbitrary-variants.test.js
+++ b/tests/arbitrary-variants.test.js
@@ -405,3 +405,91 @@ test('with @apply', () => {
     `)
   })
 })
+
+test('keeps escaped underscores', () => {
+  let config = {
+    content: [
+      {
+        raw: '<div class="[&_.foo\\_\\_bar]:underline"></div>',
+      },
+    ],
+    corePlugins: { preflight: false },
+  }
+
+  let input = `
+    @tailwind base;
+    @tailwind components;
+    @tailwind utilities;
+  `
+
+  return run(input, config).then((result) => {
+    expect(result.css).toMatchFormattedCss(css`
+      ${defaults}
+
+      .\[\&_\.foo\\_\\_bar\]\:underline .foo__bar {
+        text-decoration-line: underline;
+      }
+    `)
+  })
+})
+
+test('keeps escaped underscores with multiple arbitrary variants', () => {
+  let config = {
+    content: [
+      {
+        raw: '<div class="[&_.foo\\_\\_bar]:[&_.bar\\_\\_baz]:underline"></div>',
+      },
+    ],
+    corePlugins: { preflight: false },
+  }
+
+  let input = `
+    @tailwind base;
+    @tailwind components;
+    @tailwind utilities;
+  `
+
+  return run(input, config).then((result) => {
+    expect(result.css).toMatchFormattedCss(css`
+      ${defaults}
+
+      .\[\&_\.foo\\_\\_bar\]\:\[\&_\.bar\\_\\_baz\]\:underline .bar__baz .foo__bar {
+        text-decoration-line: underline;
+      }
+    `)
+  })
+})
+
+test('keeps escaped underscores in arbitrary variants mixed with normal variants', () => {
+  let config = {
+    content: [
+      {
+        raw: `
+          <div class="[&_.foo\\_\\_bar]:hover:underline"></div>
+          <div class="hover:[&_.foo\\_\\_bar]:underline"></div>
+        `,
+      },
+    ],
+    corePlugins: { preflight: false },
+  }
+
+  let input = `
+    @tailwind base;
+    @tailwind components;
+    @tailwind utilities;
+  `
+
+  return run(input, config).then((result) => {
+    expect(result.css).toMatchFormattedCss(css`
+      ${defaults}
+
+      .\[\&_\.foo\\_\\_bar\]\:hover\:underline:hover .foo__bar {
+        text-decoration-line: underline;
+      }
+
+      .hover\:\[\&_\.foo\\_\\_bar\]\:underline .foo__bar:hover {
+        text-decoration-line: underline;
+      }
+    `)
+  })
+})

From 0d064ea032373223922cb17a8b7ece3b3a23c720 Mon Sep 17 00:00:00 2001
From: Robin Malfait <malfait.robin@gmail.com>
Date: Fri, 10 Jun 2022 11:33:35 +0200
Subject: [PATCH 09/11] Enable `postcss-import` in the CLI by default in watch
 mode (#8580)

* Add support for postcss-import in watch mode

* Add regression test

* Extract shared logic

* restructure test a little bit

Instead of relying on a arbitrary setTimout value, let's wait for the
file to be created instead.

* update changelog

Co-authored-by: Adam Bergman <adam@fransvilhelm.com>
---
 CHANGELOG.md                                  |  1 +
 .../tailwindcss-cli/tests/cli.test.js         | 42 +++++++++-
 src/cli.js                                    | 80 ++++++++++---------
 3 files changed, 85 insertions(+), 38 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9aa357f03839..a9bc9035bdc1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Fixed
 
 - Ensure `\` is a valid arbitrary variant token ([#8576](https://github.com/tailwindlabs/tailwindcss/pull/8576))
+- Enable `postcss-import` in the CLI by default in watch mode ([#8574](https://github.com/tailwindlabs/tailwindcss/pull/8574), [#8580](https://github.com/tailwindlabs/tailwindcss/pull/8580))
 
 ## [3.1.1] - 2022-06-09
 
diff --git a/integrations/tailwindcss-cli/tests/cli.test.js b/integrations/tailwindcss-cli/tests/cli.test.js
index 414dd2f40639..9ebcd3012b91 100644
--- a/integrations/tailwindcss-cli/tests/cli.test.js
+++ b/integrations/tailwindcss-cli/tests/cli.test.js
@@ -5,7 +5,14 @@ let resolveToolRoot = require('../../resolve-tool-root')
 
 let version = require('../../../package.json').version
 
-let { readOutputFile, writeInputFile, cleanupFile, fileExists, removeFile } = require('../../io')({
+let {
+  cleanupFile,
+  fileExists,
+  readOutputFile,
+  removeFile,
+  waitForOutputFileCreation,
+  writeInputFile,
+} = require('../../io')({
   output: 'dist',
   input: 'src',
 })
@@ -374,6 +381,39 @@ describe('Build command', () => {
     )
   })
 
+  test('postcss-import is supported by default in watch mode', async () => {
+    cleanupFile('src/test.css')
+
+    await writeInputFile('index.html', html`<div class="md:something-cool"></div>`)
+    await writeInputFile(
+      'test.css',
+      css`
+        @import 'tailwindcss/base';
+        @import 'tailwindcss/components';
+        @import 'tailwindcss/utilities';
+        @import './imported.css';
+      `
+    )
+
+    let runningProcess = $(
+      `${EXECUTABLE} --watch --input ./src/test.css --content ./src/index.html --output ./dist/main.css`
+    )
+
+    await waitForOutputFileCreation('main.css')
+
+    expect(await readOutputFile('main.css')).toIncludeCss(
+      css`
+        @media (min-width: 768px) {
+          .md\:something-cool {
+            color: red;
+          }
+        }
+      `
+    )
+
+    return runningProcess.stop()
+  })
+
   test('postcss-import is included when using a custom postcss configuration', async () => {
     cleanupFile('src/test.css')
 
diff --git a/src/cli.js b/src/cli.js
index 2c48af64514f..885f03399e5f 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -484,6 +484,45 @@ async function build() {
     return [beforePlugins, afterPlugins, config.options]
   }
 
+  function loadBuiltinPostcssPlugins() {
+    let postcss = loadPostcss()
+    let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: '
+    return [
+      [
+        (root) => {
+          root.walkAtRules('import', (rule) => {
+            if (rule.params.slice(1).startsWith('tailwindcss/')) {
+              rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params }))
+              rule.remove()
+            }
+          })
+        },
+        (() => {
+          try {
+            return require('postcss-import')
+          } catch {}
+
+          return lazyPostcssImport()
+        })(),
+        (root) => {
+          root.walkComments((rule) => {
+            if (rule.text.startsWith(IMPORT_COMMENT)) {
+              rule.after(
+                postcss.atRule({
+                  name: 'import',
+                  params: rule.text.replace(IMPORT_COMMENT, ''),
+                })
+              )
+              rule.remove()
+            }
+          })
+        },
+      ],
+      [],
+      {},
+    ]
+  }
+
   function resolveConfig() {
     let config = configPath ? require(configPath) : {}
 
@@ -568,44 +607,9 @@ async function build() {
 
     tailwindPlugin.postcss = true
 
-    let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: '
-
     let [beforePlugins, afterPlugins, postcssOptions] = includePostCss
       ? await loadPostCssPlugins()
-      : [
-          [
-            (root) => {
-              root.walkAtRules('import', (rule) => {
-                if (rule.params.slice(1).startsWith('tailwindcss/')) {
-                  rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params }))
-                  rule.remove()
-                }
-              })
-            },
-            (() => {
-              try {
-                return require('postcss-import')
-              } catch {}
-
-              return lazyPostcssImport()
-            })(),
-            (root) => {
-              root.walkComments((rule) => {
-                if (rule.text.startsWith(IMPORT_COMMENT)) {
-                  rule.after(
-                    postcss.atRule({
-                      name: 'import',
-                      params: rule.text.replace(IMPORT_COMMENT, ''),
-                    })
-                  )
-                  rule.remove()
-                }
-              })
-            },
-          ],
-          [],
-          {},
-        ]
+      : loadBuiltinPostcssPlugins()
 
     let plugins = [
       ...beforePlugins,
@@ -705,7 +709,9 @@ async function build() {
       return resolveConfig()
     }
 
-    let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [[], []]
+    let [beforePlugins, afterPlugins] = includePostCss
+      ? await loadPostCssPlugins()
+      : loadBuiltinPostcssPlugins()
 
     let plugins = [
       ...beforePlugins,

From 05f866dcb3eadb55d67d691cdea1343f5415cbce Mon Sep 17 00:00:00 2001
From: Robin Malfait <malfait.robin@gmail.com>
Date: Fri, 10 Jun 2022 11:54:47 +0200
Subject: [PATCH 10/11] update changelog

---
 CHANGELOG.md | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9bc9035bdc1..f6bd6023dac0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+- Nothing yet!
+
+## [3.1.2] - 2022-06-10
+
 ### Fixed
 
 - Ensure `\` is a valid arbitrary variant token ([#8576](https://github.com/tailwindlabs/tailwindcss/pull/8576))
@@ -1964,7 +1968,8 @@ No release notes
 
 - Everything!
 
-[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.1...HEAD
+[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.2...HEAD
+[3.1.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.1...v3.1.2
 [3.1.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.0...v3.1.1
 [3.1.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.24...v3.1.0
 [3.0.24]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.23...v3.0.24

From ce80574ff5ee43258410d5c44314e183b3618460 Mon Sep 17 00:00:00 2001
From: Robin Malfait <malfait.robin@gmail.com>
Date: Fri, 10 Jun 2022 11:54:47 +0200
Subject: [PATCH 11/11] 3.1.2

---
 package-lock.json | 4 ++--
 package.json      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 30dfbc39da76..1c71ffec7624 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "tailwindcss",
-  "version": "3.1.1",
+  "version": "3.1.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "tailwindcss",
-      "version": "3.1.1",
+      "version": "3.1.2",
       "license": "MIT",
       "dependencies": {
         "arg": "^5.0.1",
diff --git a/package.json b/package.json
index 39aac411ecb1..7c8e7ada3718 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tailwindcss",
-  "version": "3.1.1",
+  "version": "3.1.2",
   "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
   "license": "MIT",
   "main": "lib/index.js",