JSFiddle - React, Tailwind, and code Playground

by Chris Ball

HTML

<div class="parent">
	<div class="box box1"><p>1</p></div>
	<div class="box box2"><p>2</p></div>
</div>

<button class="btn1">Box 1</button>
<button class="btn2">Box 2</button>

SCSS

body {
	font-family: sans-serif;
}

.box {
	align-content: center;
	color: #fff;
	display: flex;
	font-size: 2rem;
	height: 5rem;
	justify-content: center;
	margin: 1rem;
	width: 5rem;
	p {
		line-height: 0.5;
	}
}

.box1 {
	background: #00ff80;
}

.box2 {
	background: #0080ff;
}

JavaScript

function fade(el) {

	this.out = (duration, cb) => {
		this.starttime
		requestAnimationFrame((timestamp) => {
			this.starttime = timestamp
			this.__out(timestamp, el, duration, cb)
		})
	}

	this.in = (duration, display ) => {
		el.style.display = display || 'block'
		this.starttime
		requestAnimationFrame((timestamp) => {
			this.starttime = timestamp
			this.__in(timestamp, el, duration)
		})
	}

	this.__out = (timestamp, el, duration) => {
		let runtime = timestamp - this.starttime
		let progress = runtime / duration
		progress = Math.min(progress, 1)
		el.style.opacity = (1 - progress).toFixed(2)
		if (runtime < duration){
			requestAnimationFrame((timestamp) => {
				__out(timestamp, el, duration)
			})
		} else {
			el.style.display = 'none'
		}
	}

	this.__in = (timestamp, el, duration, cb) => {
		let runtime = timestamp - this.starttime
		let progress = runtime / duration
		progress = Math.min(progress, 1)
		el.style.opacity = (0 + progress).toFixed(2)
		if (runtime < duration){
			requestAnimationFrame((timestamp) => {
				__in(timestamp, el, duration)
			})
		}
	}

	return this
}

let box1 = document.querySelector('.box1')
let box2 = document.querySelector('.box2')
let btn1 = document.querySelector('.btn1')
let btn2 = document.querySelector('.btn2')

btn1.addEventListener('click', ()=>{
	fade(box1).out(300)
})

btn2.addEventListener('click', ()=>{
	fade(box1).in(300, 'flex')
})