Repository: tailwindlabs/tailwindcss (TypeScript)

Issue:
[Bug]: border-opacity doesn't work with default border color
### What version of Tailwind CSS are you using?

2.1.1

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

play.tailwind.com

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

play.tailwind.com

### What browser are you using?

Safari 14.1 and Brave 1.23.75 using Chromium: 90.0.4430.93

### What operating system are you using?

macOS 11.3.1

### Reproduction repository

https://play.tailwindcss.com/8qs2AKmp9g

### Describe your issue

Border opacity doesn't work with the default border color.

For instance, I'd expect to not see a border on this div since the `border-opacity` is 0. However, can still see a border.

```html
<main class='w-screen h-screen p-8'>
    <div class='w-full h-full border border-opacity-0'></div>
</main>
```

However, adding a border color (e.g., `border-red-500`) lets the opacity work correctly.

If for some reason the playground link doesn't work, just start with a new playground and replace the HTML with the HTML above.


Hints:
> However, adding a border color (e.g., border-red-500) lets the opacity work correctly.

I have the exact same issue but with custom colors as well.

Patch:
diff --git a/src/plugins/borderColor.js b/src/plugins/borderColor.js
--- a/src/plugins/borderColor.js
+++ b/src/plugins/borderColor.js
@@ -2,7 +2,23 @@ import flattenColorPalette from '../util/flattenColorPalette'
 import withAlphaVariable from '../util/withAlphaVariable'
 
 export default function () {
-  return function ({ matchUtilities, theme, variants, corePlugins }) {
+  return function ({ addBase, matchUtilities, theme, variants, corePlugins }) {
+    if (!corePlugins('borderOpacity')) {
+      addBase({
+        '*, ::before, ::after': {
+          'border-color': theme('borderColor.DEFAULT', 'currentColor'),
+        },
+      })
+    } else {
+      addBase({
+        '*, ::before, ::after': withAlphaVariable({
+          color: theme('borderColor.DEFAULT', 'currentColor'),
+          property: 'border-color',
+          variable: '--tw-border-opacity',
+        }),
+      })
+    }
+
     matchUtilities(
       {
         border: (value) => {


Test patch:
diff --git a/tests/fixtures/tailwind-output-flagged.css b/tests/fixtures/tailwind-output-flagged.css
--- a/tests/fixtures/tailwind-output-flagged.css
+++ b/tests/fixtures/tailwind-output-flagged.css
@@ -410,7 +410,7 @@ body {
   box-sizing: border-box; /* 1 */
   border-width: 0; /* 2 */
   border-style: solid; /* 2 */
-  border-color: #e5e7eb; /* 2 */
+  border-color: currentColor; /* 2 */
 }
 
 /*
@@ -539,6 +539,11 @@ video {
   height: auto;
 }
 
+*, ::before, ::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
+
 .container {
   width: 100%;
 }
diff --git a/tests/fixtures/tailwind-output-important.css b/tests/fixtures/tailwind-output-important.css
--- a/tests/fixtures/tailwind-output-important.css
+++ b/tests/fixtures/tailwind-output-important.css
@@ -410,7 +410,7 @@ body {
   box-sizing: border-box; /* 1 */
   border-width: 0; /* 2 */
   border-style: solid; /* 2 */
-  border-color: #e5e7eb; /* 2 */
+  border-color: currentColor; /* 2 */
 }
 
 /*
@@ -539,6 +539,11 @@ video {
   height: auto;
 }
 
+*, ::before, ::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
+
 .container {
   width: 100%;
 }
diff --git a/tests/fixtures/tailwind-output-no-color-opacity.css b/tests/fixtures/tailwind-output-no-color-opacity.css
--- a/tests/fixtures/tailwind-output-no-color-opacity.css
+++ b/tests/fixtures/tailwind-output-no-color-opacity.css
@@ -410,7 +410,7 @@ body {
   box-sizing: border-box; /* 1 */
   border-width: 0; /* 2 */
   border-style: solid; /* 2 */
-  border-color: #e5e7eb; /* 2 */
+  border-color: currentColor; /* 2 */
 }
 
 /*
@@ -539,6 +539,10 @@ video {
   height: auto;
 }
 
+*, ::before, ::after {
+  border-color: #e5e7eb;
+}
+
 .container {
   width: 100%;
 }
diff --git a/tests/fixtures/tailwind-output.css b/tests/fixtures/tailwind-output.css
--- a/tests/fixtures/tailwind-output.css
+++ b/tests/fixtures/tailwind-output.css
@@ -410,7 +410,7 @@ body {
   box-sizing: border-box; /* 1 */
   border-width: 0; /* 2 */
   border-style: solid; /* 2 */
-  border-color: #e5e7eb; /* 2 */
+  border-color: currentColor; /* 2 */
 }
 
 /*
@@ -539,6 +539,11 @@ video {
   height: auto;
 }
 
+*, ::before, ::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
+
 .container {
   width: 100%;
 }
diff --git a/tests/jit/apply.test.css b/tests/jit/apply.test.css
--- a/tests/jit/apply.test.css
+++ b/tests/jit/apply.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/arbitrary-values.test.css b/tests/jit/arbitrary-values.test.css
--- a/tests/jit/arbitrary-values.test.css
+++ b/tests/jit/arbitrary-values.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/basic-usage.test.css b/tests/jit/basic-usage.test.css
--- a/tests/jit/basic-usage.test.css
+++ b/tests/jit/basic-usage.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/collapse-adjacent-rules.test.css b/tests/jit/collapse-adjacent-rules.test.css
--- a/tests/jit/collapse-adjacent-rules.test.css
+++ b/tests/jit/collapse-adjacent-rules.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/custom-extractors.test.css b/tests/jit/custom-extractors.test.css
--- a/tests/jit/custom-extractors.test.css
+++ b/tests/jit/custom-extractors.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/import-syntax.test.css b/tests/jit/import-syntax.test.css
--- a/tests/jit/import-syntax.test.css
+++ b/tests/jit/import-syntax.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/important-boolean.test.css b/tests/jit/important-boolean.test.css
--- a/tests/jit/important-boolean.test.css
+++ b/tests/jit/important-boolean.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/important-modifier-prefix.test.css b/tests/jit/important-modifier-prefix.test.css
--- a/tests/jit/important-modifier-prefix.test.css
+++ b/tests/jit/important-modifier-prefix.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/important-modifier.test.css b/tests/jit/important-modifier.test.css
--- a/tests/jit/important-modifier.test.css
+++ b/tests/jit/important-modifier.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/important-selector.test.css b/tests/jit/important-selector.test.css
--- a/tests/jit/important-selector.test.css
+++ b/tests/jit/important-selector.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/kitchen-sink.test.css b/tests/jit/kitchen-sink.test.css
--- a/tests/jit/kitchen-sink.test.css
+++ b/tests/jit/kitchen-sink.test.css
@@ -126,6 +126,12 @@
     }
   }
 }
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/opacity.test.css b/tests/jit/opacity.test.css
--- a/tests/jit/opacity.test.css
+++ b/tests/jit/opacity.test.css
@@ -1,3 +1,8 @@
+*,
+::before,
+::after {
+  border-color: #e5e7eb;
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/prefix.test.css b/tests/jit/prefix.test.css
--- a/tests/jit/prefix.test.css
+++ b/tests/jit/prefix.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
@@ -73,7 +79,7 @@
 .tw-group:hover .group-hover\:focus-within\:tw-text-left:focus-within {
   text-align: left;
 }
-[dir="rtl"] .rtl\:active\:tw-text-center:active {
+[dir='rtl'] .rtl\:active\:tw-text-center:active {
   text-align: center;
 }
 @media (prefers-reduced-motion: no-preference) {
diff --git a/tests/jit/raw-content.test.css b/tests/jit/raw-content.test.css
--- a/tests/jit/raw-content.test.css
+++ b/tests/jit/raw-content.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/raw-content.test.js b/tests/jit/raw-content.test.js
--- a/tests/jit/raw-content.test.js
+++ b/tests/jit/raw-content.test.js
@@ -71,6 +71,12 @@ test('raw content with extension', () => {
 
   return run(tailwind, css, config).then((result) => {
     expect(result.css).toMatchFormattedCss(`
+      *,
+      ::before,
+      ::after {
+        --tw-border-opacity: 1;
+        border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+      }
       * {
         --tw-shadow: 0 0 #0000;
         --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/relative-purge-paths.test.css b/tests/jit/relative-purge-paths.test.css
--- a/tests/jit/relative-purge-paths.test.css
+++ b/tests/jit/relative-purge-paths.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/responsive-and-variants-atrules.test.css b/tests/jit/responsive-and-variants-atrules.test.css
--- a/tests/jit/responsive-and-variants-atrules.test.css
+++ b/tests/jit/responsive-and-variants-atrules.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/svelte-syntax.test.css b/tests/jit/svelte-syntax.test.css
--- a/tests/jit/svelte-syntax.test.css
+++ b/tests/jit/svelte-syntax.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
diff --git a/tests/jit/variants.test.css b/tests/jit/variants.test.css
--- a/tests/jit/variants.test.css
+++ b/tests/jit/variants.test.css
@@ -1,3 +1,9 @@
+*,
+::before,
+::after {
+  --tw-border-opacity: 1;
+  border-color: rgba(229, 231, 235, var(--tw-border-opacity));
+}
 * {
   --tw-shadow: 0 0 #0000;
   --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);