0

I am developing a React-widget (step-by-step-wizard), which fetches and shows content from an API. I don't know, how long the texts, I am fetching from the API, are. So I don't know, the height of the widget. The widget should increase the height regarding to the content (like the default HTML-elements). There should be no scrolling.

I can not set a fixed height here. So I can not set position: absolute to the slides I want to animate.

At the moment the animation looks like the following:

The second slide appears below the first slide until the first slide disappears and the second one moves up. Of course, this is completely ugly.

If I set a fixed height and position absolute to the slides everything works fine and smooth.

You can see a demo of my problem here: https://codepen.io/anon/pen/jdQPRw

rakete
  • 2,953
  • 11
  • 54
  • 108
  • 2
    Please provide a [mcve] which reproduces the problem you’re having. – MTCoster Feb 13 '19 at 22:19
  • https://codepen.io/anon/pen/jdQPRw – rakete Feb 15 '19 at 21:42
  • Absolutely positioned elements don't need a height, they'll get it from the content. They DO need a width or stuff like text will collapse down to a single column. Are you just trying to do a cross fade? – Bryce Howitson Feb 16 '19 at 03:01
  • Yes you are right. They don’t need a height but what happens with the content, what is below the widget? If cross fade means an transition/animation from one slide to another (slide or fade - doesn’t matter): yes! – rakete Feb 16 '19 at 06:48
  • On you wrapper div you can use transition: all ease 0.5s; it will also show you the fade effect. – Piyush Verma Feb 22 '19 at 06:58

1 Answers1

0

TransitionGroup should be wrapper for multiple Transition or CSSTransition So first you should wrap each slide in CSSTransition. Second let "in" property to handle the "hide & show" for the component

<CSSTransition in={slide === 2}

Then use the property unmountOnExit to unmount the slide after animation done

I've forked your pen and edit it and it's working please check the changes https://codepen.io/anon/pen/yZZqKo

const { TransitionGroup, CSSTransition } = ReactTransitionGroup;

class Slide extends React.Component {
  render() {
    return <div 
               className="slide"
             style={{backgroundColor: this.props.bg}}
             >{this.props.content}</div>
  } 
}

const content1 = 'Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. ';
const content2 = 'Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. Demo Text with different Length. This will get fetched from API. ';

class Widget extends React.Component {

  state = { slide: 1 }

  render() {
    const slide = this.state.slide;
    return (
      <div className="widget">
          <TransitionGroup className="wrapper"><div>
            <CSSTransition
              in={slide === 1}
              classNames="fade"
              timeout={{ enter: 500, exit: 0 }}
              appear
              unmountOnExit
              ><Slide content={ content1 } bg="#fafafa" />
            </CSSTransition></div><div>
            <CSSTransition
              in={slide === 2}
              classNames="fade"
              timeout={{ enter: 500, exit: 0 }}
              appear
              unmountOnExit
              ><Slide content={ content2 } bg="#ccc" />
            </CSSTransition></div>
          </TransitionGroup>
          <div className="buttons">
            <button 
              className="next" 
              onClick={ () => this.setState({slide: 1})}
              >Slide 1</button>
            <button 
              className="next" 
              onClick={ () => this.setState({slide: 2})}
              >Slide 2</button>
          </div>
      </div>
    );
  }
} 


ReactDOM.render(
  <Widget />,
  document.getElementById('root')
);
body {
  background: #eee;
}

.page {
  max-width: 500px;
  margin: 30px auto;
}

.widget {
  padding: 20px;
  background: #fff;
  border-radius: 5px;
  overflow: hidden;
}

.slide {
  padding: 20px;
  border-radius: 3px;
}

.buttons {
  display: flex;
}

.next {
  display: flex;
  flex: 1;
  margin: 10px;
  background: blue;
  color: #fff;
  padding: 14px;
  margin-top: 10px;
  border: 0;
  border-radius: 3px;
  font-size: 20px;
  text-decoration: none;
  text-align: center;
}

.fade-enter {
  opacity: 0.01;
}
.fade-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}
.fade-enter-done {opacity:1}
.fade-exit {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0.01;
  transition: opacity 500ms ease-in;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-transition-group/2.5.3/react-transition-group.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.3.1/react-router-dom.js"></script>
<div class="page">
  <h1>Content</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ullamcorper ac tortor quis vulputate. Cras commodo dolor quis odio rutrum accumsan. Vestibulum aliquam bibendum odio vel auctor. In feugiat elit ac accumsan posuere. Donec facilisis tellus vitae faucibus pharetra. Aenean arcu dolor, molestie ut cursus vitae, congue id tortor. In scelerisque scelerisque dolor eget laoreet. Donec et consequat quam. Maecenas suscipit quis mi ac luctus. Aliquam aliquet vitae erat ut ultricies. Suspendisse laoreet lacinia nisl sit amet facilisis. Aliquam ac lorem leo. Etiam feugiat sagittis erat eget ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

<div id="root">
    <!-- This element's contents will be replaced with your component. -->
</div>
  
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ullamcorper ac tortor quis vulputate. Cras commodo dolor quis odio rutrum accumsan. Vestibulum aliquam bibendum odio vel auctor. In feugiat elit ac accumsan posuere. Donec facilisis tellus vitae faucibus pharetra. Aenean arcu dolor, molestie ut cursus vitae, congue id tortor. In scelerisque scelerisque dolor eget laoreet. Donec et consequat quam. Maecenas suscipit quis mi ac luctus. Aliquam aliquet vitae erat ut ultricies. Suspendisse laoreet lacinia nisl sit amet facilisis. Aliquam ac lorem leo. Etiam feugiat sagittis erat eget ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
Mina paulis
  • 392
  • 3
  • 14