diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index 66b051d57961..7d8d80e347a3 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -19,6 +19,10 @@ test('sr-only', async () => {
position: absolute;
overflow: hidden;
}
+
+ .sr-only > caption {
+ clip-path: inset(50%);
+ }
"
`)
expect(await run(['-sr-only', 'sr-only-[var(--value)]', 'sr-only/foo'])).toEqual('')
@@ -37,6 +41,10 @@ test('not-sr-only', async () => {
position: static;
overflow: visible;
}
+
+ .not-sr-only > caption {
+ clip-path: none;
+ }
"
`)
expect(await run(['-not-sr-only', 'not-sr-only-[var(--value)]', 'not-sr-only/foo'])).toEqual('')
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index 477559d7ea67..b4a254aa4cd0 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -599,6 +599,10 @@ export function createUtilities(theme: Theme) {
['clip-path', 'inset(50%)'],
['white-space', 'nowrap'],
['border-width', '0'],
+ // Firefox applies the `clip-path` of a `
` to its inner grid box, so
+ // a `` (which lives in the outer table wrapper box) is not clipped
+ // and stays visible. Clip the caption itself to cover that case.
+ () => styleRule('& > caption', [decl('clip-path', 'inset(50%)')]),
])
staticUtility('not-sr-only', [
['position', 'static'],
@@ -609,6 +613,8 @@ export function createUtilities(theme: Theme) {
['overflow', 'visible'],
['clip-path', 'none'],
['white-space', 'normal'],
+ // `sr-only` also clips the caption of a table, so undo that here
+ () => styleRule('& > caption', [decl('clip-path', 'none')]),
])
/**
diff --git a/packages/tailwindcss/tests/ui.spec.ts b/packages/tailwindcss/tests/ui.spec.ts
index e5da091d8ce4..5e2629b216b7 100644
--- a/packages/tailwindcss/tests/ui.spec.ts
+++ b/packages/tailwindcss/tests/ui.spec.ts
@@ -1513,6 +1513,58 @@ test.skip("::file-selector-button can receive a border with just the 'border' ut
)
})
+test('sr-only also hides the caption of a table', async ({ page }) => {
+ let { getPropertyValue } = await render(
+ page,
+ html`
+
+
+ Caption
+
+
+
+ | Cell |
+
+
+
+ `,
+ )
+
+ // Firefox applies the `clip-path` of the `` to its inner grid box, and
+ // a `` is rendered in the outer table wrapper box, so the caption is
+ // not clipped by the table itself and must be clipped explicitly. Asserting
+ // the rule that does it is all that can run here: the bug only reproduces in
+ // Firefox, which is not available in this environment.
+ expect(await getPropertyValue('#caption', 'clip-path')).toEqual('inset(50%)')
+})
+
+test('not-sr-only also unclips the caption of a table', async ({ page }) => {
+ let { getPropertyValue } = await render(
+ page,
+ html`
+
+
+ Caption
+
+
+
+ | Cell |
+
+
+
+ `,
+ )
+
+ // the caption must become visible again together with the table it reveals,
+ // so the responsive reset has to win over the base `sr-only` rule
+ await page.setViewportSize({ width: 640, height: 768 })
+ expect(await getPropertyValue('#caption', 'clip-path')).toEqual('inset(50%)')
+
+ await page.setViewportSize({ width: 1024, height: 768 })
+ expect(await getPropertyValue('#table', 'clip-path')).toEqual('none')
+ expect(await getPropertyValue('#caption', 'clip-path')).toEqual('none')
+})
+
test('composing shadow, inset shadow, ring, and inset ring', async ({ page }) => {
let { getPropertyList } = await render(
page,