Skip to content
Home » All Blogs » Changing Face Rating Using HTML, CSS & JS

Changing Face Rating Using HTML, CSS & JS

This project involves the development of a web application that allows users to rate and modify the facial expressions of a character using HTML, CSS, and JavaScript. The application provides a user-friendly interface where individuals can choose from a range of facial expressions such as happiness, sadness, anger, surprise, and more.

HTML is used to structure the webpage, including the canvas area where the character’s face is displayed. CSS is employed to style the elements, enhancing the visual appeal and usability of the application.

JavaScript is an integral part of this project as it enables dynamic functionality. Users can interact with the character’s face by selecting different expressions from buttons or dropdown menus. When a new expression is chosen, JavaScript updates the character’s face, adjusting the facial features to reflect the selected emotion.

The project leverages JavaScript’s event listeners to capture user actions and trigger the appropriate responses. For instance, when a user clicks on a button representing a specific emotion, the associated event listener activates a JavaScript function that updates the character’s face with the chosen expression.

In summary, this project showcases the combined potential of HTML, CSS, and JavaScript in creating an interactive web application where users can modify and rate various facial expressions.

Demo

I would recommend you don’t just copy and paste the code, just look at the code and type by understanding it.

HTML – Starter Template

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSS -->
    <link rel="stylesheet" href="style.css">

    <title>Changing Face Rating - Anoncodes</title>
</head>

<body>
    <!-- Further code here -->

     <script src="script.js"></script>
</body>

</html>

Paste the below code in your <body> tag.

<form class="fr" action="">
	<label class="fr__label" for="face-rating">How was your experience?</label>
	<div class="fr__face" role="img" aria-label="Straight face">
		<div class="fr__face-right-eye" data-right></div>
		<div class="fr__face-left-eye" data-left></div>
		<div class="fr__face-mouth-lower" data-mouth-lower></div>
		<div class="fr__face-mouth-upper" data-mouth-upper></div>
	</div>
	<input class="fr__input" id="face-rating" type="range" value="2.5" min="0" max="5" step="0.1">
</form>

CSS Code

Create a file style.css and paste the code below.

* {
	border: 0;
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}
:root {
	--hue: 223;
	--white: hsl(var(--hue),10%,100%);
	--lt-gray: hsl(var(--hue),10%,95%);
	--gray1: hsl(var(--hue),10%,90%);
	--gray2: hsl(var(--hue),10%,80%);
	--gray7: hsl(var(--hue),10%,30%);
	--gray9: hsl(var(--hue),10%,10%);
	--primary: hsl(var(--hue),90%,55%);
	--trans-dur: 0.3s;
	font-size: calc(16px + (24 - 16) * (100vw - 320px) / (1280 - 320));
}
body,
input {
	font: 1em/1.5 "DM Sans", sans-serif;
}
body {
	background-color: var(--white);
	color: var(--gray9);
	height: 100vh;
	display: grid;
	place-items: center;
	transition:
		background-color var(--trans-dur),
		color var(--trans-dur);
}

/* Main styles */
.fr {
	animation: fade-slide-in 0.6s ease-out;
	padding: 0 1.5em;
	max-width: 20em;
}
.fr__face {
	--face-hue1: 60;
	--face-hue2: 30;
	background-image:
		linear-gradient(
			135deg,
			hsl(var(--face-hue1),90%,55%),
			hsl(var(--face-hue2),90%,45%)
		);
	border-radius: 50%;
	box-shadow: 0 0.5em 0.75em hsla(var(--face-hue2),90%,55%,0.3);
	margin: 0 auto 2em;
	position: relative;
	width: 3em;
	height: 3em;
}
.fr__face-right-eye,
.fr__face-left-eye,
.fr__face-mouth-lower,
.fr__face-mouth-upper {
	position: absolute;
	transition:
		background-color var(--trans-dur),
		box-shadow var(--trans-dur),
		color var(--trans-dur);
}
.fr__face-right-eye,
.fr__face-left-eye {
	background-color: var(--white);
	border-radius: 50%;
	top: 0.75em;
	width: 0.6em;
	height: 0.6em;
}
.fr__face-right-eye {
	--delay-right: 0s;
	animation: right-eye 1s var(--delay-right) linear paused;
	clip-path: polygon(0 75%,100% 0,100% 100%,0 100%);
	left: 0.6em;
}
.fr__face-left-eye {
	--delay-left: 0s;
	animation: left-eye 1s var(--delay-left) linear paused;
	clip-path: polygon(0 0,100% 75%,100% 100%,0 100%);
	right: 0.6em;
}
.fr__face-mouth-lower,
.fr__face-mouth-upper {
	color: var(--white);
	top: 1.75em;
	left: 0.75em;
	width: 1.5em;
	height: 0.75em;
}
.fr__face-mouth-lower {
	--delay-mouth-lower: 0s;
	animation: mouth-lower 1s var(--delay-mouth-lower) linear paused;
	border-radius: 50% 50% 0 0 / 100% 100% 0 0;
	box-shadow: 0 0.125em 0 inset;
}
.fr__face-mouth-upper {
	--delay-mouth-upper: 0s;
	animation: mouth-upper 1s var(--delay-mouth-upper) linear paused;
	border-radius: 0 0 50% 50% / 0 0 100% 100%;
	box-shadow: 0 -0.125em 0 inset;
}
.fr__label {
	display: block;
	margin-bottom: 1.5em;
	text-align: center;
}
.fr__input {
	--input-hue: 60;
	--percent: 50%;
	background-color: var(--gray1);
	background-image: linear-gradient(hsl(var(--input-hue),90%,45%),hsl(var(--input-hue),90%,45%));
	background-size: var(--percent) 100%;
	background-repeat: no-repeat;
	border-radius: 0.25em;
	display: block;
	margin: 0.5em auto;
	width: 100%;
	max-width: 10em;
	height: 0.5em;
	transition: background-color var(--trans-dur);
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
}
.fr__input:focus {
	outline: transparent;
}

/* WebKit */
.fr__input::-webkit-slider-thumb {
	background-color: var(--white);
	border: 0;
	border-radius: 50%;
	box-shadow: 0 0.125em 0.5em hsl(0,0%,0%,0.3);
	width: 1.5em;
	height: 1.5em;
	transition: background-color 0.15s linear;
	-webkit-appearance: none;
	appearance: none;
}
.fr__input:focus::-webkit-slider-thumb,
.fr__input::-webkit-slider-thumb:hover {
	background-color: var(--lt-gray);
}

/* Firefox */
.fr__input::-moz-range-thumb {
	background-color: var(--white);
	border: 0;
	border-radius: 50%;
	box-shadow: 0 0.125em 0.5em hsl(0,0%,0%,0.3);
	width: 1.5em;
	height: 1.5em;
	transition: background-color 0.15s linear;
}
.fr__input:focus::-moz-range-thumb,
.fr__input::-moz-range-thumb:hover {
	background-color: var(--lt-gray);
}

/* `:focus-visible` support */
@supports selector(:focus-visible) {
	.fr__input:focus::-webkit-slider-thumb {
		background-color: var(--white);
	}
	.fr__input:focus-visible::-webkit-slider-thumb,
	.fr__input::-webkit-slider-thumb:hover {
		background-color: var(--lt-gray);
	}
	.fr__input:focus::-moz-range-thumb {
		background-color: var(--white);
	}
	.fr__input:focus-visible::-moz-range-thumb,
	.fr__input::-moz-range-thumb:hover {
		background-color: var(--lt-gray);
	}
}

/* Dark theme */
@media (prefers-color-scheme: dark) {
	body {
		background-color: var(--gray9);
		color: var(--gray1);
	}
	.fr__face-right-eye,
	.fr__face-left-eye {
		background-color: var(--gray9);
	}
	.fr__face-mouth-lower,
	.fr__face-mouth-upper {
		color: var(--gray9);
	}
	.fr__input {
		background-color: var(--gray7);
	}
}

/* Animations */
@keyframes fade-slide-in {
	from,
	16.67% {
		opacity: 0;
		transform: translateY(25%);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}
@keyframes right-eye {
	from { clip-path: polygon(0 75%,100% 0,100% 100%,0 100%); }
	50%, to { clip-path: polygon(0 0,100% 0,100% 100%,0 100%); }
}
@keyframes left-eye {
	from { clip-path: polygon(0 0,100% 75%,100% 100%,0 100%); }
	50%, to { clip-path: polygon(0 0,100% 0,100% 100%,0 100%); }
}
@keyframes mouth-lower {
	from {
		border-radius: 50% 50% 0 0 / 100% 100% 0 0;
		top: 1.75em;
		height: 0.75em;
		visibility: visible;
	}
	40% {
		border-radius: 50% 50% 0 0 / 100% 100% 0 0;
		top: 1.95em;
		height: 0.25em;
		visibility: visible;
	}
	50%,
	to {
		border-radius: 0;
		top: 2em;
		height: 0.125em;
		visibility: hidden;
	}
}
@keyframes mouth-upper {
	from,
	50% {
		border-radius: 0;
		box-shadow: 0 -0.125em 0 inset;
		top: 2em;
		height: 0.125em;
		visibility: hidden;
	}
	62.5% {
		border-radius: 0 0 50% 50% / 0 0 100% 100%;
		box-shadow: 0 -0.125em 0 inset;
		top: 1.95em;
		height: 0.25em;
		visibility: visible;
	}
	75% {
		border-radius: 0 0 50% 50% / 0 0 100% 100%;
		box-shadow: 0 -0.125em 0 inset;
		top: 1.825em;
		height: 0.5em;
		visibility: visible;
	}
	to {
		border-radius: 0 0 50% 50% / 0 0 100% 100%;
		box-shadow: 0 -0.8em 0 inset;
		top: 1.75em;
		height: 0.75em;
		visibility: visible;
	}
}

Javascript Code

Create a file index.js and paste the code below.

window.addEventListener("DOMContentLoaded",() => {
	const fr = new FaceRating("#face-rating");
});

class FaceRating {
	constructor(qs) {
		this.input = document.querySelector(qs);
		this.input?.addEventListener("input",this.update.bind(this));
		this.face = this.input?.previousElementSibling;
		this.update();
	}
	update(e) {
		let value = this.input.defaultValue;

		// when manually set
		if (e) value = e.target?.value;
		// when initiated
		else this.input.value = value;

		const min = this.input.min || 0;
		const max = this.input.max || 100;
		const percentRaw = (value - min) / (max - min) * 100;
		const percent = +percentRaw.toFixed(2);

		this.input?.style.setProperty("--percent",`${percent}%`);

		// face and range fill colors
		const maxHue = 120;
		const hueExtend = 30;
		const hue = Math.round(maxHue * percent / 100);

		let hue2 = hue - hueExtend;
		if (hue2 < 0) hue2 += 360;

		const hues = [hue,hue2];
		hues.forEach((h,i) => {
			this.face?.style.setProperty(`--face-hue${i + 1}`,h);
		});

		this.input?.style.setProperty("--input-hue",hue);

		// emotions
		const duration = 1;
		const delay = -(duration * 0.99) * percent / 100;
		const parts = ["right","left","mouth-lower","mouth-upper"];

		parts.forEach(p => {
			const el = this.face?.querySelector(`[data-${p}]`);
			el?.style.setProperty(`--delay-${p}`,`${delay}s`);
		});

		// aria label
		const faces = [
			"Sad face",
			"Slightly sad face",
			"Straight face",
			"Slightly happy face",
			"Happy face"
		];
		let faceIndex = Math.floor(faces.length * percent / 100);
		if (faceIndex === faces.length) --faceIndex;

		this.face?.setAttribute("aria-label",faces[faceIndex]);
	}
}

Written By : @anoncodes

Code Credit : @jkantner

Hope you find this post helpful 💖🔥

Show Some Love and Support On These Social Media🔥💖


Latest Post

Leave a Reply

Your email address will not be published. Required fields are marked *

www.000webhost.com