Open evayde opened 2 years ago
@bramus any idea why translate-x
isn't a thing?
It wasn't part of the initial use-cases that we designed the individual transform properties for.
So it could be added in future?
I think so – Can’t think of a reason why it wouldn’t be possible.
As far as I understand it, the reason for creating individual transform properties was so that we can animate stuff without writing everything again, so:
div {
transform: translate(0,100px) scale(1.2) rotate(20deg);
}
div:hover {
transform: translate(10px,200px) scale(1.2) rotate(20deg);
}
Can be written like this:
div {
transform: translate(0,100px) scale(1.2) rotate(20deg);
}
div:hover {
translate: 10px 200px;
}
For the same reasons, we could argue that this would be even better (more granular):
div {
transform: translate(0,100px) scale(1.2) rotate(20deg);
}
div:hover {
translate-y: 200px;
}
Also it is more consistent with how other CSS properties and their shorthand syntax works.
In addition to translate-x
and translate-y
, would it also make sense to have translate-inline
and translate-block
? Same for scale-*
/rotate-*
, knowing that for the *-z
properties there would be no logical counterpart.
We don't have corresponding functions for those; I'm uncomfortable adding properties that are genuinely unexpressible in 'transform' itself.
The CSS Working Group just discussed [css-transforms-2] Syntax of individual transforms should reflect general CSS syntax
, and agreed to the following:
RESOLVED: add the longhands to these properties as discussed above
This would be changing the decomposition a little, tho not in a way that's observably different from what we have today.
Currently the three transform properties insert three transform functions into the transform stack. Now they'll insert 7: 3 translates, a rotate, and 3 scales. If you continue to use the (now) shorthands the behavior is identical, since translates and scales are order-independent between themselves.
So I think there's a definitely nontrivial cost to adding these, in particular because it requires adding support for separately animating translate-x, translate-y, and translate-z, etc., on the compositor.
If there are strong use cases for the splitting I think that complexity could be justified, but I don't think we should do this just "because a lot of other CSS properties do it", since I think it has significantly more implementation cost than for many other CSS properties.
The CSS Working Group just discussed [css-transforms-2] Syntax of individual transforms should reflect general CSS syntax
, and agreed to the following:
RESOLVED: undo previous resolution, do not add the longhands to the rotate, translate, and scale properties
To note, [css-logical][css-images] flow-relative gradients
I'm not sure we've resolved how transform-origin
would work yet.
Got another request from an author for this today:
well, I think the problem with those properties is that they still don't give you individual transforms, e.g. translateX and Y separately... so back to square one I guess.
This was explicitly in response to the existence of the current individual transform properties.
Quoting @birtles on Twitter:
Maybe we need to introduce translateX and translateY properties 😅
This was sparked by a tweet by author @mattgperry. For their framework Framer Motion, IUC, they internally pipe the passed in x
/y
/etc. options to Custom Properties, which they then use to build a transform
themselves. This has the downside of not being hardware accelerated.
With translateX/translateY/etc. this would not be a problem, as Framer Motion could then pass these props straight into the individual transform properties.
As Matthew put it in a follow-up tweet:
Yes it would be amazing to be able to set each axis directly!
In terms of use-case, thinking from the perspective of gestures and/or velocity-based animations, the very first problem I’ve had to solve with every animation library I’ve written is per-axis transform animation. I was surprised when transform/scale/rotate were implemented that they weren’t per-axis. This is a big reason why people choose JS libraries over CSS.
For Motion One, which is based purely on WAAPI, the approach has been via custom properties but of course these aren’t accelerated.
They actually perform worse than the approach taken in Framer Motion. This library constructs a new transform at the end of every animation frame but of course has to run on the main thread. Framer Motion uses WAAPI when values can be hardware accelerated and if transforms could be set per axis, many more animations would be.
So I think there are two things we could reasonably do here:
translate-x
and translate-y
and translate-z
properties, and make translate
a shorthand for themscale-x
and scale-y
and scale-z
properties and make scale
a shorthand for themI'm curious how strong the use cases are for each of these things. It sounds like separate translate properties are quite valuable. Are there similarly strong use cases for the scale properties?
I think its less clear what to do about the rotate properties. The earlier proposal above was to split into rotate-angle
and rotate-axis
, but it's not clear to me how strong the use cases for such a split are.
We can't make the existing rotate
property a shorthand for rotate-x
/rotate-y
/rotate-z
since it supports a syntax that allows rotations around arbitrary vectors, and non-axis-aligned rotations can't be mapped to separate rotate-x
/rotate-y
/rotate-z
properties. So if we wanted such properties I think we'd have to make them additional properties, and then define the order of operations across all four rotation properties. I'd also note that the order of operations just between rotate-x
/rotate-y
/rotate-z
is not obvious.
I'd also note that the order of operations just between rotate-x/rotate-y/rotate-z is not obvious.
Yes, this is why I'd object to rotate-x
/etc properties (and why we didn't do skew
/etc properties). The TSR order gets you the least-surprising result; anything else will produce surprises at least some of the time.
My suggestion on Twitter was partly in jest. I think many of these use cases can already be addressed using animation composition. What is missing there is a better way to control the composite order of the animations.
Here is a demo showing independently animated translateX and translateY on the same element. At least in Firefox, both animations are accelerated: https://codepen.io/birtles/pen/mdaGydp
However, the order of composition for script-generated animations is currently based on the order in which the animations are created.
For libraries, I believe they would like to, for example, add a translateX
animation after the fact and have it composite in a specific order. In the past we've discussed this and decided we could add methods to adjust an animation's relative composite order when the need arose.
It would indeed probably be enough to be able to manually set transform order rather than rely on animation creation.
On rotateX
etc I'm not sure I understand why it's complicated. I've always just enforced X - Y - Z and I don't think I've had a comment or complaint in almost ten years. There is a way to define your own order already, via transform
.
I'm here for accessibility/localization moreso than animation.
For RTL languages we don't want to touch translate-y
. We only care to modify translate-x
. There's a lot of rule rewriting with translate
alone.
I've always just enforced X - Y - Z and I don't think I've had a comment or complaint in almost ten years.
If an author writes .foo { rotate-y: 30deg; }
, it's reasonable to assume they expect it to rotate 30deg around the Y axis, aka the vertical line parallel with the page. But if another class has set rotate-x: 45deg;
, they won't get that result - it'll rotate around the 45deg-canted Y axis instead. That's pretty surprising!
The existing TSR order doesn't result in such surprises - without knowing anything about what other transform properties are set, you can safely set any individual one and get the result you'd expect from thinking solely about that property in a vacuum - 'rotate' spins the element around regardless of what 'translate' is, 'translate' moves it the specified distance even if it's scaled or rotated, etc.
I think it's fairly useful to maintain this property if we can, and ask authors to write 'transform' if they do want transforms that are less "separable" in this way. It might not be a property we can maintain forever! But it's one we should discard only with caution, and with significant author benefit justifying it, to overcome the downside of author confusion.
(As has been noted, we can safely split up 'translate' and 'scale' if desired; the individual effects are independent of each other and maintain the "local" property. We could split 'rotate' into 'rotate-axis' and 'rotate-angle', as those are clearly components of a rotation rather than independent operations on their own, and thus aren't expected to be understood on their own in a vacuum, but as @dbaron says it's unclear how strong the use-cases are for that particular control.)
For example: Individual translate is only usable like so:
translate: 0 0 10px
Buttranslate
as an individual property should be a shorthand fortranslate-x
,translate-y
, andtranslate-z
In my opinion, this would reflect the current CSS syntax with other properties, likeoverflow
,background-position
,scroll-snap-type
, and so on. Otherwise, it feels kind of inconsistent to me.Or is there any technical reason that we cannot provide that syntax for individual transforms?
Spec: https://www.w3.org/TR/css-transforms-2/#individual-transforms