<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>CodePen - Feedback Reactions</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<ul class="feedback">
<li class="angry">
<div>
<svg class="eye left">
<use xlink:href="#eye">
</svg>
<svg class="eye right">
<use xlink:href="#eye">
</svg>
<svg class="mouth">
<use xlink:href="#mouth">
</svg>
</div>
</li>
<li class="sad">
<div>
<svg class="eye left">
<use xlink:href="#eye">
</svg>
<svg class="eye right">
<use xlink:href="#eye">
</svg>
<svg class="mouth">
<use xlink:href="#mouth">
</svg>
</div>
</li>
<li class="ok">
<div></div>
</li>
<li class="good active">
<div>
<svg class="eye left">
<use xlink:href="#eye">
</svg>
<svg class="eye right">
<use xlink:href="#eye">
</svg>
<svg class="mouth">
<use xlink:href="#mouth">
</svg>
</div>
</li>
<li class="happy">
<div>
<svg class="eye left">
<use xlink:href="#eye">
</svg>
<svg class="eye right">
<use xlink:href="#eye">
</svg>
</div>
</li>
</ul>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7 4" id="eye">
<path d="M1,1 C1.83333333,2.16666667 2.66666667,2.75 3.5,2.75 C4.33333333,2.75 5.16666667,2.16666667 6,1"></path>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 7" id="mouth">
<path d="M1,5.5 C3.66666667,2.5 6.33333333,1 9,1 C11.6666667,1 14.3333333,2.5 17,5.5"></path>
</symbol>
</svg>
<!-- dribbble - twitter -->
<a class="dribbble" href="https://dribbble.com/shots/9828547-Feedback-Reactions" target="_blank"><img src="https://cdn.dribbble.com/assets/dribbble-ball-mark-2bd45f09c2fb58dbbfb44766d5d1d07c5a12972d602ef8b32204d28fa3dda554.svg" alt=""></a>
<a class="twitter" target="_blank" href="https://twitter.com/aaroniker_me"><svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" viewBox="0 0 72 72"><path d="M67.812 16.141a26.246 26.246 0 0 1-7.519 2.06 13.134 13.134 0 0 0 5.756-7.244 26.127 26.127 0 0 1-8.313 3.176A13.075 13.075 0 0 0 48.182 10c-7.229 0-13.092 5.861-13.092 13.093 0 1.026.118 2.021.338 2.981-10.885-.548-20.528-5.757-26.987-13.679a13.048 13.048 0 0 0-1.771 6.581c0 4.542 2.312 8.551 5.824 10.898a13.048 13.048 0 0 1-5.93-1.638c-.002.055-.002.11-.002.162 0 6.345 4.513 11.638 10.504 12.84a13.177 13.177 0 0 1-3.449.457c-.846 0-1.667-.078-2.465-.231 1.667 5.2 6.499 8.986 12.23 9.09a26.276 26.276 0 0 1-16.26 5.606A26.21 26.21 0 0 1 4 55.976a37.036 37.036 0 0 0 20.067 5.882c24.083 0 37.251-19.949 37.251-37.249 0-.566-.014-1.134-.039-1.694a26.597 26.597 0 0 0 6.533-6.774z"></path></svg></a>
<!-- partial -->
<script src="./script.js"></script>
</body>
</html>
.feedback {
--normal: #ECEAF3;
--normal-shadow: #D9D8E3;
--normal-mouth: #9795A4;
--normal-eye: #595861;
--active: #F8DA69;
--active-shadow: #F4B555;
--active-mouth: #F05136;
--active-eye: #313036;
--active-tear: #76b5e7;
--active-shadow-angry: #e94f1d;
margin: 0;
padding: 0;
list-style: none;
display: -webkit-box;
display: flex;
}
.feedback li {
position: relative;
border-radius: 50%;
background: var(--sb, var(--normal));
box-shadow: inset 3px -3px 4px var(--sh, var(--normal-shadow));
-webkit-transition: background .4s, box-shadow .4s, -webkit-transform .3s;
transition: background .4s, box-shadow .4s, -webkit-transform .3s;
transition: background .4s, box-shadow .4s, transform .3s;
transition: background .4s, box-shadow .4s, transform .3s, -webkit-transform .3s;
-webkit-tap-highlight-color: transparent;
}
.feedback li:not(:last-child) {
margin-right: 20px;
}
.feedback li div {
width: 40px;
height: 40px;
position: relative;
-webkit-transform: perspective(240px) translateZ(4px);
transform: perspective(240px) translateZ(4px);
}
.feedback li div svg, .feedback li div:before, .feedback li div:after {
display: block;
position: absolute;
left: var(--l, 9px);
top: var(--t, 13px);
width: var(--w, 8px);
height: var(--h, 2px);
-webkit-transform: rotate(var(--r, 0deg)) scale(var(--sc, 1)) translateZ(0);
transform: rotate(var(--r, 0deg)) scale(var(--sc, 1)) translateZ(0);
}
.feedback li div svg {
fill: none;
stroke: var(--s);
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
-webkit-transition: stroke .4s;
transition: stroke .4s;
}
.feedback li div svg.eye {
--s: var(--e, var(--normal-eye));
--t: 17px;
--w: 7px;
--h: 4px;
}
.feedback li div svg.eye.right {
--l: 23px;
}
.feedback li div svg.mouth {
--s: var(--m, var(--normal-mouth));
--l: 11px;
--t: 23px;
--w: 18px;
--h: 7px;
}
.feedback li div:before, .feedback li div:after {
content: '';
z-index: var(--zi, 1);
border-radius: var(--br, 1px);
background: var(--b, var(--e, var(--normal-eye)));
-webkit-transition: background .4s;
transition: background .4s;
}
.feedback li.angry {
--step-1-rx: -24deg;
--step-1-ry: 20deg;
--step-2-rx: -24deg;
--step-2-ry: -20deg;
}
.feedback li.angry div:before {
--r: 20deg;
}
.feedback li.angry div:after {
--l: 23px;
--r: -20deg;
}
.feedback li.angry div svg.eye {
stroke-dasharray: 4.55;
stroke-dashoffset: 8.15;
}
.feedback li.angry.active {
-webkit-animation: angry 1s linear;
animation: angry 1s linear;
}
.feedback li.angry.active div:before {
--middle-y: -2px;
--middle-r: 22deg;
-webkit-animation: toggle .8s linear forwards;
animation: toggle .8s linear forwards;
}
.feedback li.angry.active div:after {
--middle-y: 1px;
--middle-r: -18deg;
-webkit-animation: toggle .8s linear forwards;
animation: toggle .8s linear forwards;
}
.feedback li.sad {
--step-1-rx: 20deg;
--step-1-ry: -12deg;
--step-2-rx: -18deg;
--step-2-ry: 14deg;
}
.feedback li.sad div:before, .feedback li.sad div:after {
--b: var(--active-tear);
--sc: 0;
--w: 5px;
--h: 5px;
--t: 15px;
--br: 50%;
}
.feedback li.sad div:after {
--l: 25px;
}
.feedback li.sad div svg.eye {
--t: 16px;
}
.feedback li.sad div svg.mouth {
--t: 24px;
stroke-dasharray: 9.5;
stroke-dashoffset: 33.25;
}
.feedback li.sad.active div:before, .feedback li.sad.active div:after {
-webkit-animation: tear .6s linear forwards;
animation: tear .6s linear forwards;
}
.feedback li.ok {
--step-1-rx: 4deg;
--step-1-ry: -22deg;
--step-1-rz: 6deg;
--step-2-rx: 4deg;
--step-2-ry: 22deg;
--step-2-rz: -6deg;
}
.feedback li.ok div:before {
--l: 12px;
--t: 17px;
--h: 4px;
--w: 4px;
--br: 50%;
box-shadow: 12px 0 0 var(--e, var(--normal-eye));
}
.feedback li.ok div:after {
--l: 13px;
--t: 26px;
--w: 14px;
--h: 2px;
--br: 1px;
--b: var(--m, var(--normal-mouth));
}
.feedback li.ok.active div:before {
--middle-s-y: .35;
-webkit-animation: toggle .2s linear forwards;
animation: toggle .2s linear forwards;
}
.feedback li.ok.active div:after {
--middle-s-x: .5;
-webkit-animation: toggle .7s linear forwards;
animation: toggle .7s linear forwards;
}
.feedback li.good {
--step-1-rx: -14deg;
--step-1-rz: 10deg;
--step-2-rx: 10deg;
--step-2-rz: -8deg;
}
.feedback li.good div:before {
--b: var(--m, var(--normal-mouth));
--w: 5px;
--h: 5px;
--br: 50%;
--t: 22px;
--zi: 0;
opacity: .5;
box-shadow: 16px 0 0 var(--b);
-webkit-filter: blur(2px);
filter: blur(2px);
}
.feedback li.good div:after {
--sc: 0;
}
.feedback li.good div svg.eye {
--t: 15px;
--sc: -1;
stroke-dasharray: 4.55;
stroke-dashoffset: 8.15;
}
.feedback li.good div svg.mouth {
--t: 22px;
--sc: -1;
stroke-dasharray: 13.3;
stroke-dashoffset: 23.75;
}
.feedback li.good.active div svg.mouth {
--middle-y: 1px;
--middle-s: -1;
-webkit-animation: toggle .8s linear forwards;
animation: toggle .8s linear forwards;
}
.feedback li.happy div {
--step-1-rx: 18deg;
--step-1-ry: 24deg;
--step-2-rx: 18deg;
--step-2-ry: -24deg;
}
.feedback li.happy div:before {
--sc: 0;
}
.feedback li.happy div:after {
--b: var(--m, var(--normal-mouth));
--l: 11px;
--t: 23px;
--w: 18px;
--h: 8px;
--br: 0 0 8px 8px;
}
.feedback li.happy div svg.eye {
--t: 14px;
--sc: -1;
}
.feedback li.happy.active div:after {
--middle-s-x: .95;
--middle-s-y: .75;
-webkit-animation: toggle .8s linear forwards;
animation: toggle .8s linear forwards;
}
.feedback li:not(.active) {
cursor: pointer;
}
.feedback li:not(.active):active {
-webkit-transform: scale(0.925);
transform: scale(0.925);
}
.feedback li.active {
--sb: var(--active);
--sh: var(--active-shadow);
--m: var(--active-mouth);
--e: var(--active-eye);
}
.feedback li.active div {
-webkit-animation: shake .8s linear forwards;
animation: shake .8s linear forwards;
}
@-webkit-keyframes shake {
30% {
-webkit-transform: perspective(240px) rotateX(var(--step-1-rx, 0deg)) rotateY(var(--step-1-ry, 0deg)) rotateZ(var(--step-1-rz, 0deg)) translateZ(10px);
transform: perspective(240px) rotateX(var(--step-1-rx, 0deg)) rotateY(var(--step-1-ry, 0deg)) rotateZ(var(--step-1-rz, 0deg)) translateZ(10px);
}
60% {
-webkit-transform: perspective(240px) rotateX(var(--step-2-rx, 0deg)) rotateY(var(--step-2-ry, 0deg)) rotateZ(var(--step-2-rz, 0deg)) translateZ(10px);
transform: perspective(240px) rotateX(var(--step-2-rx, 0deg)) rotateY(var(--step-2-ry, 0deg)) rotateZ(var(--step-2-rz, 0deg)) translateZ(10px);
}
100% {
-webkit-transform: perspective(240px) translateZ(4px);
transform: perspective(240px) translateZ(4px);
}
}
@keyframes shake {
30% {
-webkit-transform: perspective(240px) rotateX(var(--step-1-rx, 0deg)) rotateY(var(--step-1-ry, 0deg)) rotateZ(var(--step-1-rz, 0deg)) translateZ(10px);
transform: perspective(240px) rotateX(var(--step-1-rx, 0deg)) rotateY(var(--step-1-ry, 0deg)) rotateZ(var(--step-1-rz, 0deg)) translateZ(10px);
}
60% {
-webkit-transform: perspective(240px) rotateX(var(--step-2-rx, 0deg)) rotateY(var(--step-2-ry, 0deg)) rotateZ(var(--step-2-rz, 0deg)) translateZ(10px);
transform: perspective(240px) rotateX(var(--step-2-rx, 0deg)) rotateY(var(--step-2-ry, 0deg)) rotateZ(var(--step-2-rz, 0deg)) translateZ(10px);
}
100% {
-webkit-transform: perspective(240px) translateZ(4px);
transform: perspective(240px) translateZ(4px);
}
}
@-webkit-keyframes tear {
0% {
opacity: 0;
-webkit-transform: translateY(-2px) scale(0) translateZ(0);
transform: translateY(-2px) scale(0) translateZ(0);
}
50% {
-webkit-transform: translateY(12px) scale(0.6, 1.2) translateZ(0);
transform: translateY(12px) scale(0.6, 1.2) translateZ(0);
}
20%,
80% {
opacity: 1;
}
100% {
opacity: 0;
-webkit-transform: translateY(24px) translateX(4px) rotateZ(-30deg) scale(0.7, 1.1) translateZ(0);
transform: translateY(24px) translateX(4px) rotateZ(-30deg) scale(0.7, 1.1) translateZ(0);
}
}
@keyframes tear {
0% {
opacity: 0;
-webkit-transform: translateY(-2px) scale(0) translateZ(0);
transform: translateY(-2px) scale(0) translateZ(0);
}
50% {
-webkit-transform: translateY(12px) scale(0.6, 1.2) translateZ(0);
transform: translateY(12px) scale(0.6, 1.2) translateZ(0);
}
20%,
80% {
opacity: 1;
}
100% {
opacity: 0;
-webkit-transform: translateY(24px) translateX(4px) rotateZ(-30deg) scale(0.7, 1.1) translateZ(0);
transform: translateY(24px) translateX(4px) rotateZ(-30deg) scale(0.7, 1.1) translateZ(0);
}
}
@-webkit-keyframes toggle {
50% {
-webkit-transform: translateY(var(--middle-y, 0)) scale(var(--middle-s-x, var(--middle-s, 1)), var(--middle-s-y, var(--middle-s, 1))) rotate(var(--middle-r, 0deg));
transform: translateY(var(--middle-y, 0)) scale(var(--middle-s-x, var(--middle-s, 1)), var(--middle-s-y, var(--middle-s, 1))) rotate(var(--middle-r, 0deg));
}
}
@keyframes toggle {
50% {
-webkit-transform: translateY(var(--middle-y, 0)) scale(var(--middle-s-x, var(--middle-s, 1)), var(--middle-s-y, var(--middle-s, 1))) rotate(var(--middle-r, 0deg));
transform: translateY(var(--middle-y, 0)) scale(var(--middle-s-x, var(--middle-s, 1)), var(--middle-s-y, var(--middle-s, 1))) rotate(var(--middle-r, 0deg));
}
}
@-webkit-keyframes angry {
40% {
background: var(--active);
}
45% {
box-shadow: inset 3px -3px 4px var(--active-shadow), inset 0 8px 10px var(--active-shadow-angry);
}
}
@keyframes angry {
40% {
background: var(--active);
}
45% {
box-shadow: inset 3px -3px 4px var(--active-shadow), inset 0 8px 10px var(--active-shadow-angry);
}
}
html {
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
}
* {
box-sizing: inherit;
}
*:before, *:after {
box-sizing: inherit;
}
body {
min-height: 100vh;
display: -webkit-box;
display: flex;
font-family: 'Roboto', Arial;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
background: #F9F9FC;
}
body .dribbble {
position: fixed;
display: block;
right: 20px;
bottom: 20px;
}
body .dribbble img {
display: block;
height: 28px;
}
body .twitter {
position: fixed;
display: block;
right: 64px;
bottom: 14px;
}
body .twitter svg {
width: 32px;
height: 32px;
fill: #1da1f2;
}
document.querySelectorAll('.feedback li').forEach(entry => entry.addEventListener('click', e => {
if(!entry.classList.contains('active')) {
document.querySelector('.feedback li.active').classList.remove('active');
entry.classList.add('active');
}
e.preventDefault();
}));