Skip to content

Conversation

@adamwathan
Copy link
Member

Our original implementation of 3D rotations was limited to the rotate property in CSS, which only allows specifying a single angle around either a specified axis or vector.

The more I played with this the less intuitive I found it to be, so we've decided to support composable 3D rotations via transform that let you do stuff like this:

<div class="rotate-x-30 rotate-y-12 rotate-z-45">

The order of rotations matters in transforms, so I looked to Framer Motion to see what order they use, which is X → Y → Z.

I think you can make arguments for a variety of orders, but I've decided to use the same one as Framer Motion just because I think it's nice to be able to build something with Tailwind, then later move those styles to Framer Motion because you have some idea for some interesting effect and be able to reuse all of the same values.

Importantly, I've kept the rotate-* utilities as well which still use the rotate property. It can also be composed with rotate-x-* and rotate-y-* because it's a separate property, but generally I think it will make more sense to use rotate-z-* explicitly when trying to compose a 3D rotation, as the order of operations feels more intuitive to me at least.

@thecrypticace
Copy link
Contributor

This looks good but I think it's weird that md:rotate-none wouldn't cancel out rotate-x/y/z-*. Do you think that's worth changing?

@KrisBraun
Copy link
Contributor

Do we want to reconsider whether arbitrary transform values should be in addition to contributions from utilities like rotate-x rather than overwrite them? I can see folks wanting to add an arbitrary transform where an existing rotation has already been applied, and being surprised (since they don't know the implementation uses transform).

@adamwathan
Copy link
Member Author

This looks good but I think it's weird that md:rotate-none wouldn't cancel out rotate-x/y/z-*. Do you think that's worth changing?

@thecrypticace tough one — I agree overall but it also means it wouldn't be possible to cancel something on the rotate property without cancelling transform-based rotations, and it's kinda weird that that's the only rotate-* root utility that touches those variables when the other ones don't. Tricky too because there's no real equivalent of none for the transform version other than 0 which still creates a stacking context if the transform property is set to read those variables, whereas rotate: none doesn't.

I think my gut here is to leave it as-is to avoid backing ourselves into a corner by being too clever, even if it could be helpful. Easier to add later than to take away I think? I dunno.

@adamwathan
Copy link
Member Author

Do we want to reconsider whether arbitrary transform values should be in addition to contributions from utilities like rotate-x rather than overwrite them? I can see folks wanting to add an arbitrary transform where an existing rotation has already been applied, and being surprised (since they don't know the implementation uses transform).

@KrisBraun I think I still feel like transform with an arbitrary value should act as a pure override, and be consistent with how blur-sm filter-[contrast(200%)] also overrides the blur.

Copy link
Contributor

@KrisBraun KrisBraun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@adamwathan adamwathan force-pushed the composable-rotations branch from c6cdafb to 0e8292b Compare March 22, 2024 16:26
@adamwathan adamwathan merged commit 0f69d4f into next Mar 22, 2024
@adamwathan adamwathan deleted the composable-rotations branch March 22, 2024 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants