Repository: tailwindlabs/tailwindcss

Problem statement:
Duplicated CSS rules in @media output
### What version of Tailwind CSS are you using?

2.2.4

### What build tool (or framework if it abstracts the build tool) are you using?

Gulp and tailwindcss-cli

### What version of Node.js are you using?

v14.17.2

### What browser are you using?

N/A

### What operating system are you using?

Windows 10

### Reproduction repository

https://play.tailwindcss.com/6re84tZQjw?file=css

### Describe your issue

Noticed this recently and just curious if this is the intended/expected behavior. In **JIT** mode, when using `@apply`, responsive variants (e.g. `md:`) are output as separate, duplicate CSS rules rather than combined into one (as is the case with non-responsive rules). _Note: This is the case whether one uses multiple `@apply` rules or combines all styles into one._

**Input:**
_CONFIG_
```
const colors = require('tailwindcss/colors')

module.exports = {
  mode: 'jit',
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
}
```

_HTML_
```
<div class="nav-main">
  <a href="#" class="nav-item">nav</a>
</div>
```

_CSS_
```
@tailwind base;
@tailwind components;
@tailwind utilities;

.nav-main {
  @apply bg-gray-200 w-full;
  @apply md:w-1/2 md:px-5 md:bg-blue-200;
}

.nav-item {
  @apply uppercase text-sm tracking-wider font-semibold flex py-2 px-4 border-b-2 border-transparent;
  @apply md:text-blue-600 md:font-bold md:tracking-widest;
}
```
_or_
```
.nav-main {
  @apply bg-gray-200 w-full md:w-1/2 md:px-5 md:bg-blue-200;
}

.nav-item {
  @apply uppercase text-sm tracking-wider font-semibold flex py-2 px-4 border-b-2 border-transparent md:text-blue-600 md:font-bold md:tracking-widest;
}
```

Output:
```
.nav-main {
  width: 100%;
  --tw-bg-opacity: 1;
  background-color: rgba(229, 231, 235, var(--tw-bg-opacity));
}

@media (min-width: 768px) {
  .nav-main {
    width: 50%;
  }
  
  .nav-main {
    --tw-bg-opacity: 1;
    background-color: rgba(191, 219, 254, var(--tw-bg-opacity));
  }
  
  .nav-main {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }
}

.nav-item {
  display: flex;
  border-bottom-width: 2px;
  border-color: transparent;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  padding-left: 1rem;
  padding-right: 1rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

@media (min-width: 768px) {
  .nav-item {
    font-weight: 700;
  }
  
  .nav-item {
    letter-spacing: 0.1em;
  }
  
  .nav-item {
    --tw-text-opacity: 1;
    color: rgba(37, 99, 235, var(--tw-text-opacity));
  }
}
```

Output **without** `mode: 'jit'`
```
.nav-main {
  width: 100%;
  --tw-bg-opacity: 1;
  background-color: rgba(229, 231, 235, var(--tw-bg-opacity));
}

@media (min-width: 768px) {
  .nav-main {
    width: 50%;
    --tw-bg-opacity: 1;
    background-color: rgba(191, 219, 254, var(--tw-bg-opacity));
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }
}

.nav-item {
  display: flex;
  border-bottom-width: 2px;
  border-color: transparent;
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

@media (min-width: 768px) {
  .nav-item {
    font-weight: 700;
    letter-spacing: 0.1em;
    --tw-text-opacity: 1;
    color: rgba(37, 99, 235, var(--tw-text-opacity));
  }
}
```

https://play.tailwindcss.com/6re84tZQjw?file=css

I'm a huge fan of tailwindcss and newly getting familiar with JIT so I appreciate any help or clarification that is offered!


Hints:
Updating this issue with some additional observations from my local development.

When running JIT watch mode (via `npx tailwindcss`), I get many duplicated CSS rules. Still trying to drilldown to what specific actions cause this, but it seems to be related to tailwind watching my content files (Blade views in this case). When a utility class is added to the Blade file, if that utility is not yet present in the base file, it is added (as expected) but many existing rules get duplicated in the process.

I end up with a file that looks like this:

```
#app .pointer-events-none {
  pointer-events: none;
  pointer-events: none;
  pointer-events: none;
  pointer-events: none;
  pointer-events: none;
  pointer-events: none;
}

#app .absolute {
  position: absolute;
  position: absolute;
  position: absolute;
  position: absolute;
  position: absolute;
  position: absolute;
}

#app .relative {
  position: relative;
  position: relative;
  position: relative;
  position: relative;
  position: relative;
  position: relative;
}

#app .sticky {
  position: sticky;
}

#app .top-0 {
  top: 0px;
}

#app .left-0 {
  left: 0px;
}

#app .bottom-0 {
  bottom: 0px;
}

#app .top-4 {
  top: 1rem;
}

#app .top-0 {
  top: 0px;
}

#app .left-0 {
  left: 0px;
}

#app .bottom-0 {
  bottom: 0px;
}

#app .top-5 {
  top: 1.25rem;
}

#app .top-0 {
  top: 0px;
}

#app .left-0 {
  left: 0px;
}

#app .bottom-0 {
  bottom: 0px;
}

#app .top-7 {
  top: 1.75rem;
}

#app .top-0 {
  top: 0px;
}

#app .left-0 {
  left: 0px;
}

#app .bottom-0 {
  bottom: 0px;
}

#app .top-2 {
  top: 0.5rem;
}

#app .top-0 {
  top: 0px;
}

#app .left-0 {
  left: 0px;
}

#app .bottom-0 {
  bottom: 0px;
}

#app .top-2 {
  top: 0.5rem;
}

#app .top-0 {
  top: 0px;
}

#app .left-0 {
  left: 0px;
}

#app .bottom-0 {
  bottom: 0px;
}

#app .top-3 {
  top: 0.75rem;
```
Triggering a re-processing of the primary CSS file that contains the calls to `@tailwind base; @tailwind components; @tailwind utilities;` seems to fix the issue and remove the duplicates so the issue is avoided in final production builds. However, it can be an obstacle when developing because the flood of duplicate rules makes debugging styles via DevTools quite difficult.

If I'm missing something here and inadvertently causing the issue, I'd welcome any insight!
I'm a novice, but confirm your tailwind.config.js file's "purge" settings are complete and correct
Just thought I'd note that I'm experiencing the same thing with duplicate CSS, and I happen to have all these things in common with the OP, though I'm not sure which of these are relevant just yet:

- JIT mode enabled
- templates are also Blade (with some straight PHP also included in the purge)
- also happen to be using `#app` as an `important` qualifier in `tailwind.config.js`

However, I'm using Laravel Mix + BrowserSync to watch files and recompile as needed. Duplicate rules seem to accumulate during a single BrowserSync session. If I restart my watch task, the duplicate rules get cleaned up.
if you have already node js installed or after installing open node command prompt window by typing node( on windows machine) in start.
[krogereschedule](https://www.krogereschedule.org/)

Patch:
diff --git a/src/lib/collapseAdjacentRules.js b/src/lib/collapseAdjacentRules.js
--- a/src/lib/collapseAdjacentRules.js
+++ b/src/lib/collapseAdjacentRules.js
@@ -5,7 +5,7 @@ let comparisonMap = {
 let types = new Set(Object.keys(comparisonMap))
 
 export default function collapseAdjacentRules() {
-  return (root) => {
+  function collapseRulesIn(root) {
     let currentRule = null
     root.each((node) => {
       if (!types.has(node.type)) {
@@ -35,5 +35,20 @@ export default function collapseAdjacentRules() {
         currentRule = node
       }
     })
+
+    // After we've collapsed adjacent rules & at-rules, we need to collapse
+    // adjacent rules & at-rules that are children of at-rules.
+    // We do not care about nesting rules because Tailwind CSS
+    // explicitly does not handle rule nesting on its own as
+    // the user is expected to use a nesting plugin
+    root.each((node) => {
+      if (node.type === 'atrule') {
+        collapseRulesIn(node)
+      }
+    })
+  }
+
+  return (root) => {
+    collapseRulesIn(root)
   }
 }


Test patch:
diff --git a/tests/apply.test.js b/tests/apply.test.js
--- a/tests/apply.test.js
+++ b/tests/apply.test.js
@@ -1289,9 +1289,6 @@ it('apply partitioning works with media queries', async () => {
       body {
         --tw-text-opacity: 1;
         color: rgb(220 38 38 / var(--tw-text-opacity));
-      }
-      html,
-      body {
         font-size: 2rem;
       }
     }
diff --git a/tests/collapse-adjacent-rules.test.css b/tests/collapse-adjacent-rules.test.css
--- a/tests/collapse-adjacent-rules.test.css
+++ b/tests/collapse-adjacent-rules.test.css
@@ -72,6 +72,29 @@
   color: black;
   font-weight: 700;
 }
+@supports (foo: bar) {
+  .some-apply-thing {
+    font-weight: 700;
+    --tw-text-opacity: 1;
+    color: rgb(0 0 0 / var(--tw-text-opacity));
+  }
+}
+@media (min-width: 768px) {
+  .some-apply-thing {
+    font-weight: 700;
+    --tw-text-opacity: 1;
+    color: rgb(0 0 0 / var(--tw-text-opacity));
+  }
+}
+@supports (foo: bar) {
+  @media (min-width: 768px) {
+    .some-apply-thing {
+      font-weight: 700;
+      --tw-text-opacity: 1;
+      color: rgb(0 0 0 / var(--tw-text-opacity));
+    }
+  }
+}
 @media (min-width: 640px) {
   .sm\:text-center {
     text-align: center;
diff --git a/tests/collapse-adjacent-rules.test.html b/tests/collapse-adjacent-rules.test.html
--- a/tests/collapse-adjacent-rules.test.html
+++ b/tests/collapse-adjacent-rules.test.html
@@ -19,5 +19,6 @@
     <div class="md:text-center"></div>
     <div class="lg:font-bold"></div>
     <div class="lg:text-center"></div>
+    <div class="some-apply-thing"></div>
   </body>
 </html>
diff --git a/tests/collapse-adjacent-rules.test.js b/tests/collapse-adjacent-rules.test.js
--- a/tests/collapse-adjacent-rules.test.js
+++ b/tests/collapse-adjacent-rules.test.js
@@ -8,7 +8,11 @@ test('collapse adjacent rules', () => {
     content: [path.resolve(__dirname, './collapse-adjacent-rules.test.html')],
     corePlugins: { preflight: false },
     theme: {},
-    plugins: [],
+    plugins: [
+      function ({ addVariant }) {
+        addVariant('foo-bar', '@supports (foo: bar)')
+      },
+    ],
   }
 
   let input = css`
@@ -45,6 +49,9 @@ test('collapse adjacent rules', () => {
     .bar {
       font-weight: 700;
     }
+    .some-apply-thing {
+      @apply foo-bar:md:text-black foo-bar:md:font-bold foo-bar:text-black foo-bar:font-bold md:font-bold md:text-black;
+    }
   `
 
   return run(input, config).then((result) => {
diff --git a/tests/kitchen-sink.test.css b/tests/kitchen-sink.test.css
--- a/tests/kitchen-sink.test.css
+++ b/tests/kitchen-sink.test.css
@@ -498,8 +498,6 @@ div {
       transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
       transition-duration: 150ms;
     }
-  }
-  @media (prefers-reduced-motion: no-preference) {
     .dark .md\:dark\:motion-safe\:foo\:active\:custom-util:active {
       background: #abcdef !important;
     }