mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Don't create bare spacing utilities with invalid multiples (#14962)
Closes #14960 When we moved to the `--spacing` multiples scale, we seemingly overlooked a bail that caused us to use non-numerical values as a spacing multiple. This caused the `-translate-x-full` and `-translate-y-full` utilities to treat `full` as a valid multiple in our spacing scale and created invalid CSS: ```css .-translate-x-full { --tw-translate-x: calc(var(--spacing) * -x-full); --tw-translate-y: calc(var(--spacing) * -x-full); translate: var(--tw-translate-x) var(--tw-translate-y); } ``` ## Test plan I reproduced the issue in our Vite playground and then created a failing test case. It requires a `--spacing` `@theme` variable to be defined so I've added this as a test case now in the unit tests. I also audited all places that are using `calc()` and wrapping some numbers. In doing so I found a few other broken cases: - `-translate-x-full` - `-translate-y-full` - `-space-x-full` - `-space-y-full` - `-inset-full` I validated that the fix indeed works and no longer creates broken CSS definitions for these cases: <kbd><img width="1405" alt="Screenshot 2024-11-11 at 19 33 51" src="https://github.com/user-attachments/assets/99072112-9ed4-4456-bad8-5679679e7198"></kbd> --------- Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
This commit is contained in:
parent
50d7355f7f
commit
98c279d1fb
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
|
||||
- Don't reset horizontal padding on date/time pseudo-elements ([#14959](https://github.com/tailwindlabs/tailwindcss/pull/14959))
|
||||
- Don't emit `calc()` with invalid values for bare values that aren't integers in spacing utilities ([#14962](https://github.com/tailwindlabs/tailwindcss/pull/14962))
|
||||
|
||||
## [4.0.0-alpha.32] - 2024-11-11
|
||||
|
||||
|
||||
@ -3861,6 +3861,82 @@ test('translate-x', async () => {
|
||||
'-translate-x-[var(--value)]/foo',
|
||||
]),
|
||||
).toEqual('')
|
||||
|
||||
expect(
|
||||
await compileCss(
|
||||
css`
|
||||
@theme {
|
||||
--spacing: 0.25rem;
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['translate-x-full', '-translate-x-full', 'translate-x-px', '-translate-x-[var(--value)]'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root {
|
||||
--spacing: .25rem;
|
||||
}
|
||||
|
||||
.-translate-x-\\[var\\(--value\\)\\] {
|
||||
--tw-translate-x: calc(var(--value) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
.-translate-x-full {
|
||||
--tw-translate-x: -100%;
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
.translate-x-full {
|
||||
--tw-translate-x: 100%;
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
.translate-x-px {
|
||||
--tw-translate-x: 1px;
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
@supports (-moz-orient: inline) {
|
||||
@layer base {
|
||||
*, :before, :after, ::backdrop {
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-translate-z: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@property --tw-translate-x {
|
||||
syntax: "<length> | <percentage>";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
@property --tw-translate-y {
|
||||
syntax: "<length> | <percentage>";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
@property --tw-translate-z {
|
||||
syntax: "<length>";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}"
|
||||
`)
|
||||
expect(
|
||||
await run([
|
||||
'perspective',
|
||||
'-perspective',
|
||||
'perspective-potato',
|
||||
'perspective-123',
|
||||
'perspective-normal/foo',
|
||||
'perspective-dramatic/foo',
|
||||
'perspective-none/foo',
|
||||
'perspective-[456px]/foo',
|
||||
]),
|
||||
).toEqual('')
|
||||
})
|
||||
|
||||
test('translate-y', async () => {
|
||||
@ -3933,6 +4009,82 @@ test('translate-y', async () => {
|
||||
'-translate-y-[var(--value)]/foo',
|
||||
]),
|
||||
).toEqual('')
|
||||
|
||||
expect(
|
||||
await compileCss(
|
||||
css`
|
||||
@theme {
|
||||
--spacing: 0.25rem;
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['translate-y-full', '-translate-y-full', 'translate-y-px', '-translate-y-[var(--value)]'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root {
|
||||
--spacing: .25rem;
|
||||
}
|
||||
|
||||
.-translate-y-\\[var\\(--value\\)\\] {
|
||||
--tw-translate-y: calc(var(--value) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
.-translate-y-full {
|
||||
--tw-translate-y: -100%;
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
.translate-y-full {
|
||||
--tw-translate-y: 100%;
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
.translate-y-px {
|
||||
--tw-translate-y: 1px;
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
|
||||
@supports (-moz-orient: inline) {
|
||||
@layer base {
|
||||
*, :before, :after, ::backdrop {
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-translate-z: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@property --tw-translate-x {
|
||||
syntax: "<length> | <percentage>";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
@property --tw-translate-y {
|
||||
syntax: "<length> | <percentage>";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
@property --tw-translate-z {
|
||||
syntax: "<length>";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}"
|
||||
`)
|
||||
expect(
|
||||
await run([
|
||||
'perspective',
|
||||
'-perspective',
|
||||
'perspective-potato',
|
||||
'perspective-123',
|
||||
'perspective-normal/foo',
|
||||
'perspective-dramatic/foo',
|
||||
'perspective-none/foo',
|
||||
'perspective-[456px]/foo',
|
||||
]),
|
||||
).toEqual('')
|
||||
})
|
||||
|
||||
test('translate-z', async () => {
|
||||
|
||||
@ -387,6 +387,8 @@ export function createUtilities(theme: Theme) {
|
||||
handleNegativeBareValue: ({ value }) => {
|
||||
let multiplier = theme.resolve(null, ['--spacing'])
|
||||
if (!multiplier) return null
|
||||
if (!isValidSpacingMultiplier(value)) return null
|
||||
|
||||
return `calc(${multiplier} * -${value})`
|
||||
},
|
||||
handle,
|
||||
|
||||
@ -2,6 +2,7 @@ export function App() {
|
||||
return (
|
||||
<div className="m-3 p-3 border">
|
||||
<h1 className="text-blue-500">Hello World</h1>
|
||||
<div className="-inset-x-full -inset-y-full -space-x-full -space-y-full -inset-full"></div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user