Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Motion adheres to [Semantic Versioning](http://semver.org/).

Undocumented APIs should be considered internal and may change without warning.

- Fix missing px conversion for CSS logical properties (`paddingBlock`, `paddingInline`, `marginBlock`, `marginInline`) when using numeric ranges in `useTransform`.

## [12.23.28] 2026-01-05

### Fixed
Expand Down
100 changes: 100 additions & 0 deletions packages/framer-motion/src/value/__tests__/use-transform.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,103 @@ test("can be re-pointed to another `MotionValue`", async () => {
"transform: translateX(2px)"
)
})

describe("CSS logical properties", () => {
test("support numeric values with useTransform", async () => {
const Component = () => {
const scrollY = useMotionValue(0)
const paddingBlock = useTransform(scrollY, [0, 100], [0, 100])
return <motion.div style={{ paddingBlock }} />
}

const { container } = render(<Component />)
expect(container.firstChild).toHaveStyle("padding-block: 0px")
})

test("updates paddingBlock when MotionValue changes", async () => {
const scrollY = motionValue(0)

const Component = () => {
const paddingBlock = useTransform(scrollY, [0, 100], [0, 100])
return <motion.div style={{ paddingBlock }} />
}

const { container } = render(<Component />)

await nextFrame()
expect(container.firstChild).toHaveStyle("padding-block: 0px")

scrollY.set(50)
await nextFrame()
expect(container.firstChild).toHaveStyle("padding-block: 50px")
})

test("supports other CSS logical properties", async () => {
const Component = () => {
const v = useMotionValue(25)

return (
<motion.div
style={{
paddingInline: useTransform(v, [0, 100], [0, 100]),
marginBlock: useTransform(v, [0, 100], [0, 100]),
}}
/>
)
}

const { container } = render(<Component />)

expect(container.firstChild).toHaveStyle("padding-inline: 25px")
expect(container.firstChild).toHaveStyle("margin-block: 25px")
})

test("supports inset shorthand with numeric values", async () => {
const Component = () => {
const scrollY = useMotionValue(0)
const inset = useTransform(scrollY, [0, 100], [0, 100])
return <motion.div style={{ inset }} />
}

const { container } = render(<Component />)
expect(container.firstChild).toHaveStyle("inset: 0px")
})

test("updates inset when MotionValue changes", async () => {
const scrollY = motionValue(0)

const Component = () => {
const inset = useTransform(scrollY, [0, 100], [0, 100])
return <motion.div style={{ inset }} />
}

const { container } = render(<Component />)

await nextFrame()
expect(container.firstChild).toHaveStyle("inset: 0px")

scrollY.set(50)
await nextFrame()
expect(container.firstChild).toHaveStyle("inset: 50px")
})

test("supports other inset logical properties", async () => {
const Component = () => {
const v = useMotionValue(30)

return (
<motion.div
style={{
insetBlock: useTransform(v, [0, 100], [0, 100]),
insetInline: useTransform(v, [0, 100], [0, 100]),
}}
/>
)
}

const { container } = render(<Component />)

expect(container.firstChild).toHaveStyle("inset-block: 30px")
expect(container.firstChild).toHaveStyle("inset-inline: 30px")
})
})
19 changes: 19 additions & 0 deletions packages/motion-dom/src/animation/waapi/utils/px-values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,36 @@ export const pxValues = new Set([
"right",
"bottom",
"left",
"inset",
"insetBlock",
"insetBlockStart",
"insetBlockEnd",
"insetInline",
"insetInlineStart",
"insetInlineEnd",
// Spacing props
"padding",
"paddingTop",
"paddingRight",
"paddingBottom",
"paddingLeft",
"paddingBlock",
"paddingBlockStart",
"paddingBlockEnd",
"paddingInline",
"paddingInlineStart",
"paddingInlineEnd",
"margin",
"marginTop",
"marginRight",
"marginBottom",
"marginLeft",
"marginBlock",
"marginBlockStart",
"marginBlockEnd",
"marginInline",
"marginInlineStart",
"marginInlineEnd",
// Misc
"backgroundPositionX",
"backgroundPositionY",
Expand Down
19 changes: 19 additions & 0 deletions packages/motion-dom/src/value/types/maps/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,37 @@ export const numberValueTypes: ValueTypeMap = {
right: px,
bottom: px,
left: px,
inset: px,
insetBlock: px,
insetBlockStart: px,
insetBlockEnd: px,
insetInline: px,
insetInlineStart: px,
insetInlineEnd: px,

// Spacing props
padding: px,
paddingTop: px,
paddingRight: px,
paddingBottom: px,
paddingLeft: px,
paddingBlock: px,
paddingBlockStart: px,
paddingBlockEnd: px,
paddingInline: px,
paddingInlineStart: px,
paddingInlineEnd: px,
margin: px,
marginTop: px,
marginRight: px,
marginBottom: px,
marginLeft: px,
marginBlock: px,
marginBlockStart: px,
marginBlockEnd: px,
marginInline: px,
marginInlineStart: px,
marginInlineEnd: px,

// Misc
backgroundPositionX: px,
Expand Down