Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use translate3d() #1380

Merged
merged 7 commits into from Oct 18, 2020
Merged

Conversation

slavanossar
Copy link
Contributor

@slavanossar slavanossar commented Feb 11, 2020

When transitioning a transform, translate3d gives better performance (i.e. a smoother transition) than translateX and translateY.

@luukdv
Copy link

luukdv commented Feb 29, 2020

My two cents would be to use properties what they were intended for (so translateX/Y for 2D translations and translate3d for 3D translations).

I'm not an expert, but translate3d will force a GPU animation which is more resource-intensive and requires a separate render layer for each instance.

@slavanossar
Copy link
Contributor Author

slavanossar commented Mar 3, 2020

That's a fair point, maybe this should exist as an option in tailwind.config.js to toggle output between

translateX(var(--transform-translate-x)) translateY(var(--transform-translate-y))

and

translate3d(var(--transform-translate-x), var(--transform-translate-y), 0)

Although I'd argue that the translate utility classes would almost always be used in conjunction with transition and be triggered by user input. It's fairly common practice to use translate3d to ensure smooth transitions for things like hover effects and showing modals/panels, even though they are just transforms in the X and Y planes.

translate3d does force GPU rendering, but it's 2020 and Tailwind is a framework for building modern UI, so it's safe to assume the majority of devices being targeted are more than capable of handling it.

@adamwathan
Copy link
Member

adamwathan commented Jul 8, 2020

Gathering some feedback here then can decide if we should merge this 👍

https://twitter.com/adamwathan/status/1280902295081926656

@GeoffSelby
Copy link
Contributor

GeoffSelby commented Jul 8, 2020

Commenting here as well for those that don’t see the Twitter thread.

This link compares performance for both translate3D and translateX/Y. At least on mobile, translate3d is around 7% slower. The most recent revision to the test was on in October last year.

https://jsperf.com/translate3d-vs-xy/147

@owlnai
Copy link

owlnai commented Jul 8, 2020

I would just use translateX/Y; since relying on hardware acceleration is not always a good thing. However, it could be an opt-in feature. My idea is something like:

<div class="enable-gpu">
    <div class="transform translate-y-6">
</div>
.enable-gpu { 
  transform: translateZ(0); /* equivalent to translate3d(0, 0, 0) */
}

Some developers might prefer a toggle in tailwind.config.js, like @slavanossar mentioned, but a global toggle might not be the best for everyone. Maybe we could have both?

@luukdv
Copy link

luukdv commented Jul 8, 2020

This is an important consideration as well (caused by the GPU rendering things differently): https://twitter.com/krijassnica/status/1280909655879880704. More information here: https://frippz.se/2016/02/04/fixing-blurry-text-on-hardware-accelerated-elements/

Lastly, like Donald Knuth stated: "premature optimization is the root of all evil". 🙂

@merelinguist
Copy link

merelinguist commented Jul 8, 2020

I think having both would be a bad idea. Tailwind is nice for its defaults, and people can always extend the config as they wish.

@teserak
Copy link

teserak commented Jul 9, 2020

Intel(R) Core(TM) i7-8705G CPU
ATI Polaris 22 XL [Radeon RX Vega M GL] + Intel HD Graphics 630
Ubuntu 5.4.0-40-generic

image

@felixhaeberle
Copy link

felixhaeberle commented Jul 9, 2020

I came across such an issue because I wanted to move a big background-image with transform: background-position. Turns out to be a very bad idea, it stutters and the browser couldn't handle it. Tried translateX/translateY, but there was some stutter left, but better performance in general.

I got it completely fixed with transform3d and the will-change property, because of hardware acceleration with transform3d and performance optimizations with will-change.

Good article about will-change
https://css-tricks.com/almanac/properties/w/will-change/

@slavanossar
Copy link
Contributor Author

slavanossar commented Jul 9, 2020

Having thought about this some more, I think this would be better solved by just having a transform-gpu utility that replicates the existing transform but uses translate3d() instead. Up to the maintainers if they want to add it, pretty simple for us to add as our own custom utility. I think a lot of people would find it useful though.

For anyone who wants to create their own:

/* utilities.css */

.transform-gpu {
  --transform-translate-x: 0;
  --transform-translate-y: 0;
  --transform-rotate: 0;
  --transform-skew-x: 0;
  --transform-skew-y: 0;
  --transform-scale-x: 1;
  --transform-scale-y: 1;
  transform: translate3d(var(--transform-translate-x), var(--transform-translate-y), 0) rotate(var(--transform-rotate)) skewX(var(--transform-skew-x)) skewY(var(--transform-skew-y)) scaleX(var(--transform-scale-x)) scaleY(var(--transform-scale-y));
}

EDIT: changed 3d to gpu, since it could imply the existence of translate-z utilities and get confusing.

@royvanv
Copy link

royvanv commented Aug 26, 2020

Since you are using translate3d, you could define variables for the z axes to the transform property as well.

.transform-gpu {
    --transform-translate-x: 0;
    --transform-translate-y: 0;
    --transform-translate-z: 0;
    --transform-rotate: 0;
    --transform-skew-x: 0;
    --transform-skew-y: 0;
    --transform-scale-x: 1;
    --transform-scale-y: 1;
    --transform-scale-z: 1;
    transform: translate3d(var(--transform-translate-x), var(--transform-translate-y), var(--transform-translate-z))
        rotate(var(--transform-rotate))
        skew(var(--transform-skew-x), var(--transform-skew-y)) 
        scale3d(var(--transform-scale-x), var(--transform-scale-y), var(--transform-scale-z));
  }

I've added scale3d() and it uses shorthand methods where possible.

@adamwathan
Copy link
Member

adamwathan commented Oct 17, 2020

Really like the idea of a separate .transform-gpu class 👍 if you'd like to update the PR to use that implementation I'm happy to merge it @slavanossar.

slavanossar added 3 commits Oct 18, 2020
# By Adam Wathan (307) and others
# Via GitHub (131) and Adam Wathan (10)
* master: (488 commits)
  Update changelog
  Using CSS Logical Properties in space and divide layout utilities (#1883)
  Update changelog
  Ensure changes to withOptions plugins trigger rebuilds
  Update changelog
  Update postcss-nested to version 5.0.1 (#2595)
  Update postcss-js to version 3.0.1 (#2594)
  Remove eslint-config-postcss
  Update autoprefixer
  Bust module cache
  Trigger CI
  Upgrade postcss: 7.0.32 → 8.1.1 (major) (#2593)
  Update changelog
  Remove word-wrap fallback for IE11
  Prettier likes parens a lot now
  Upgrade @fullhuman/postcss-purgecss: 2.3.0 → 3.0.0 (major) (#2589)
  Don't warn about future flags
  Revert "Automatically add `featureFlags.future` flags to the configuration files whenever the `init` command is ran (#2379)"
  Update changelog
  Add SFMono-Regular to default mono font stack
  ...
@slavanossar
Copy link
Contributor Author

slavanossar commented Oct 18, 2020

@adamwathan Done, thanks!

@adamwathan adamwathan merged commit d38c358 into tailwindlabs:master Oct 18, 2020
2 checks passed
@adamwathan
Copy link
Member

adamwathan commented Oct 18, 2020

Awesome thanks!

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.

None yet

9 participants