SOURCE

console 命令行工具 X clear

                    
>
console
const confettiShower = [];
const numConfettis = 200;
const container = document.body;
const colors = [
  "#f2abe7",
  "#9fa3ec",
  "#86d2e1 ",
  "#fec31e "
];

class Confetti {
  constructor(x, y, w, h, c) {
    this.w = Math.floor(Math.random() * 10 + 5);
    this.h = this.w*1;
    this.x = Math.floor(Math.random() * 100);
    this.y = Math.floor(Math.random() * 100);
    this.c = colors[Math.floor(Math.random() * colors.length)];
  }
  create() {
			var newConfetti = '<div class="confetti" style="bottom:' + this.y +'%; left:' + this.x +'%;width:' +
				this.w +'px; height:' + this.h +'px;"><div class="rotate"><div class="askew" style="background-color:' + this.c + '"></div></div></div>';
      container.innerHTML+= newConfetti; 
      }
  };

function animateConfetti() {
  for (var i = 1; i <= numConfettis; i++) {
    var confetti = new Confetti();
    confetti.create();
  }
  var confettis = document.querySelectorAll('.confetti');
  for (var i = 0; i < confettis.length; i++) {
    var opacity = Math.random() + 0.1;
    var animated = confettis[i].animate([
      { transform: 'translate3d(0,0,0)', opacity: opacity },
      { transform: 'translate3d(20vw,100vh,0)', opacity: 1 }
    ], {
      duration: Math.random() * 3000 + 3000,
      iterations: Infinity,
      delay: -(Math.random() * 5000)
    });
   confettiShower.push(animated);
  }
}
animateConfetti();
.container
	.cake
		.tier.tier-1
			.filling
			.icing-group
				- for (var i = 1; i < 10; i++)
					.icing
		.tier.tier-2
			.filling
			.icing-group
				- for (var i = 1; i < 8; i++)
					.icing
		.tier.tier-3
			.filling
			.icing-group
				- for (var i = 1; i < 6; i++)
					.icing
		.candles
			.candle
				.flame
					.flame-in
$bg: #f4f5fb;

html,
body {
	height: 100%;
	width: 100%;
	overflow: hidden;
	padding: 0;
	margin: 0;
}
body {
	position: relative;
	background: $bg;
	display: flex;
	align-items: center;
	justify-content: center;
}

html {
	box-sizing: border-box;
}
*,
*:before,
*:after {
	box-sizing: inherit;
}
* {
	position: absolute;
}
*:before,
*:after {
	content: "";
	position: absolute;
}

.container {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 200px;
	height: 200px;
	display: flex;
	align-items: center;
	justify-content: center;
}
.cake {
	width: 80%;
	height: 80%;
	left: 10%;
	bottom: 15%;
}
.filling {
	height: 10px;
	width: 100%;
	background-color: rgba(black, 0.1);
	top: 50%;
}

.tier {
	left: 10%;
	width: 80%;
	height: 50px;
	border-radius: 5px;
	.icing-group {
		width: 100%;
		height: 30px;
		overflow: hidden;
		.icing {
			border-radius: 0 0 20px 20px;
			width: 40px;
			height: 20px;
			background-color: $bg;
		}
	}
	&:after {
		border-radius: 0 5px 5px 0;
		right: 0;
		width: 50%;
		height: 100%;
		background-color: rgba(black, 0.05);
	}
}
.tier-1 {
	background-color: #f2abe7;
	bottom: 0;
	.filling {
		background-color: darken(#f2abe7, 10%);
	}
}
.tier-2 {
	bottom: 50px;
	width: 60%;
	height:45px;
	left: 20%;
	background-color: #9fa3ec;
	.filling {
		background-color: darken(#9fa3ec, 10%);
	}
}
.tier-3 {
	bottom: 95px;
	width: 40%;
	height:40px;
	left: 30%;
	background-color: #86d2e1;
	.filling {
		background-color: darken(#86d2e1, 10%);
	}
}
.icing:nth-child(1) {
	left: -20px;
}
.icing:nth-child(2) {
	left: 10px;
}
.icing:nth-child(3) {
	left: 40px;
}
.icing:nth-child(4) {
	left: 70px;
}
.icing:nth-child(5) {
	left: 100px;
}
.icing:nth-child(6) {
	left: 130px;
}
.icing:nth-child(7) {
	left: 160px;
}
.icing:nth-child(8) {
	left: 190px;
}
.icing:nth-child(9) {
	left: 220px;
}

.candles {
	width: 40%;
	left: 30%;
	height: 30px;
	bottom: 135px;
	.candle {
		background-color: #f2abe7;
		left: 27px;
		width: 10px;
		height: 25px;
    bottom:0;
		&:after {
			width: 50%;
			height: 100%;
			right: 0;
			background-color: rgba(black, 0.1);
		}
		.flame {
			width: 15px;
			height: 15px;
			bottom: 30px;
			left: -3px;
			.flame-in {
				width: 100%;
				height: 100%;
				background-color: #fec31e;
				border-radius: 0 50% 50%;
				transform: rotate(45deg);
				animation: flame 2s linear infinite;
			}
		}
	}
}

@keyframes flame {
  50% {
    transform: scale(0.8) rotate(45deg);
  }
}

//confetti
.confetti {
  position: absolute;
  z-index: 999;
}
.confetti .rotate {
  animation: driftRotate 1s infinite both ease-in-out;
  width: 100%;
  height: 100%;
}
.confetti .askew {
  width: 100%;
  height: 100%;
  animation: drift 1s infinite alternate both ease-in-out;
}
@for $i from 0 to 200 {  
  .confetti:nth-child(#{$i}) .askew {
    $time: 1s + random(100)*.01s;
    animation-duration: $time;
    animation-delay: -$time*random(100)*.01;
	}
  .confetti:nth-child(#{$i}) .rotate {
    $time: 1s + random(100)*.01s;
    animation-duration: $time;
    animation-delay: -$time*random(100)*.01;
	}
}

@keyframes drift {
  0% {
    transform: skewY(10deg) translate3d(-250%, 0, 0);
  }
  100% {
    transform: skewY(-10deg) translate3d(250%, 0, 0);
  }
}
@keyframes driftRotate {
  0% {
    transform: rotateX(0) ;
  }
  100% {
    transform: rotateX(360deg);
  }
}