3

I'm working on some basic FreeCodeCamp challenges, and I'm trying to use React Transition Group to achieve some pretty simple animations. Here's the CodePen.

What I've run in to is that I can't find out how to have the "quote card" horizontally and vertically centered, and also have my animations (that I'm using React Transition Group to trigger) perform a translation on it. I have the element that I'm trying to move (#quote-box) centered with the following css:

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

Here're the "move" CSS classes that I'm using with the Transition Group:

.move-enter {
  opacity: 0.01;
  transform: translate(-200px, 0);
}

.move-enter-active {
  opacity: 1;
  transform: translate(0, 0);
  transition: all 500ms ease-in 200ms;
}

.move-exit {
  opacity: 1;
  transform: translate(0, 0);
}

.move-exit-active {
  opacity: 0.01;
  transform: translate(200px, 0);
  transition: all 500ms ease-in 200ms;
}

I assume that I should be setting the transition properties to be left instead of all, but I'm a little lost in what is preventing the movement from happening. Should I also have a move-exited and move-entered class with the appropriate positioning? Thanks in advance!

Gus Murphy
  • 318
  • 3
  • 11

1 Answers1

3

There is a pretty major hint as to what might be going wrong here, and that is the fact that in your CodePen, the cards successfully animate their opacity but not their transform. That tells you that something is working as expected, just not all of the transition.

So, our first step would be to investigate the transition as it happens. Indeed, if we slow down the CSS transition duration to 20 seconds and set the <ReactTransitionGroup.CSSTransition> timeout also to 20 seconds, and inspect the element div#quote-box with devtools as the transition is happening, we see something fishy:

enter image description here

Your CSS transform property for #quote-box is overriding the transition group transform property for .move-enter-active (as expected - see CSS selector specificity) (you can tell because the transform property in .move-enter-active is crossed out). In other words, your CSS transition group transform is never applied, but the opacity transition is unaffected because #quote-box does not set that property.

There are a few potential solutions here. One of the most simple involves two steps:

  1. Change #quote-box from an ID to a class (.quote-box) - (you should absolutely do this anyway, and also for any IDs on the page, because you should only ever have a single instance of the same named ID on the page, and with CSS transition group you will have at least two at some points.) This will also ensure that your CSS transition group .move-* selectors will have the proper priority.
// CSS
.quote-box {
  // etc
}

// JSX
<div className="quote-box" >
  {/* etc */}
</div>
  1. Adjust your CSS to use the calc() function to calculate the position of the quote box. This is because normally you would not be able to center the quote box with transform(-50%, -50%) and offset its position for the transition with transform(-200px, 0) at the same time. To do so, we must use calc() to combine both the centering transform and the transition offset at the same time, i.e. transform: translate(calc(-50% - 200px), -50%);:
.move-enter {
  opacity: 0.01;
  transform: translate(calc(-50% - 200px), -50%);
}

.move-enter-active {
  opacity: 1;
  transform: translate(-50%, -50%);
  transition: all 500ms ease-in 200ms;
}

.move-exit {
  opacity: 1;
  transform: translate(-50%, -50%);
}

.move-exit-active {
  opacity: 0.01;
  transform: translate(calc(-50% + 200px), -50%);
  transition: all 500ms ease-in 200ms;
}

https://codepen.io/_jered/pen/KKPomVK

jered
  • 11,220
  • 2
  • 23
  • 34
  • Wow, thanks so much for such a clear and well-explained answer! This all makes a lot of sense, thanks for pointing out the feature in the debugging tool to see when a property has been overridden. One point that I'm not fully understanding, though, is never using IDs for a single-instance. I believe that this is important, but I don't fully get the reasoning, are there any good resources you know of that could explain this more fully? Thanks again! – Gus Murphy Sep 11 '19 at 16:20
  • @GoodTimeHaver For any given `id` string, there must be only a single unique element on the page that is assigned that `id`. As opposed to `class` which is fine to share across multiple elements. The reasons for this are numerous, perhaps the most compelling being that it is part of the HTML specification itself: https://html.spec.whatwg.org/multipage/dom.html#global-attributes:html-elements-5 – jered Sep 11 '19 at 19:06