Search code examples
cssreactjsecmascript-6transition

react, css) transition css for fade in and out, when background image is changed with className


I change my className of one div for every 3 seconds(with state change, using setInterval). And each classes has different background-image.

I want to fade in and out that background images whenever they change, with transition css. I saw some examples for more simple cases, but I have more than two elements to change/ and change pictures with state change.

How can I do that?

I uploaded my code on: https://stackblitz.com/edit/react-ubxffz But I cannot upload images on this page so temporarily replaced it to background-color in this page.

this is Image Slide component.

const imgUrls = [
    1,2,3
];

class ImageSlide extends Component {

render() {
    const { url } = this.props;
    const Text=...
    return (          
        <div>
            <div className={`pic${url}`}>
                <p className="p1_1">{Text.p1_1}</p>
            </div>
        </div>      
    );
}

this is App component, which calls ImageSlide.

class App extends Component {
constructor (props) {
    super(props);
        currentImageIndex: 0,
    };
}

// ...

componentDidMount() {
    this.interval = setInterval(() => {
        this.nextSlide(); //this function change the index state. 
        }, 3000);   
}

componentWillUnmount() {
clearInterval(this.interval);
}

// ...

<ImageSlide url={imgUrls[this.state.currentImageIndex]} />

this is css for each class, setting background image.

.pic1 {
  background-image: url('images/img_01.png');
}

.pic2 {
  background-image: url('images/img_02.png');
}

.pic3 {
  background-image: url('images/img_03.png');
}

Solution

  • It works like this: To fade backgrounds: you need to have two elements with different background-images that are stacked on top of each other and wich then are cross faded

    Working code in stackblitz.

    Working code without framework:

    const imgUrls = [
        1,2,3
    ];
    let currentIndex = 0;
    const lastIndex = imgUrls.length - 1;
    
    const nextSlide = () => {
      currentIndex++;
      currentIndex = currentIndex % (lastIndex + 1)
      
      // @See https://css-tricks.com/restart-css-animation/
      const elm = document.getElementById('root')
        .querySelector('[class^="pic"],[class*=" pix"]');
      elm.className = `pic${currentIndex+1}`
      const newone = elm.cloneNode(true);
      elm.parentNode.replaceChild(newone, elm);
    }
    
    interval = setInterval(() => {
      console.log()
      nextSlide(); //this function change the index state. 
    }, 3000);
    #root {
      position: relative;
      width: 640px;
      height: 480px;
    }
    #root .front,
    #root .back {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
    }
    #root .front {
      z-index: 2;
      opacity: 0;
    }
    #root .back {
      z-index: 1;
      opacity: 1;
    }
    #root [class^="pic"] .front,
    #root [class*=" pic"] .front {
      -webkit-animation: in 3s 0s;
              animation: in 3s 0s;
    }
    #root .pic1 .front,
    #root .pic2 .back {
      background-image: url("https://picsum.photos/640/480?image=1");
    }
    #root .pic1.init .back {
      background-image: none;
    }
    #root .pic2 .front,
    #root .pic3 .back {
      background-image: url("https://picsum.photos/640/480?image=2");
    }
    #root .pic3 .front,
    #root .pic1 .back {
      background-image: url("https://picsum.photos/640/480?image=3");
    }
    
    @-webkit-keyframes in {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
    
    @keyframes in {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
    <div id="root">
      <div class="pic1 init">
        <div class="front"></div>
        <div class="back"></div>
      </div>
    </div>