<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Editor</title>
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Rubik:wght@400;600&display=swap" rel="stylesheet">
<!-- Stylesheet -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<div class="editor">
<div class="filter">
<label for="blur">Blur</label>
<input type="range" min="0" max="5" value="0" step="0.1" id="blur">
</div>
<div class="filter">
<label for="contrast">Contrast</label>
<input type="range" min="0" max="200" value="100" id="contrast">
</div>
<div class="filter">
<label for="hue-rotate">Hue-Rotate</label>
<input type="range" min="0" max="360" value="0" id="hue-rotate">
</div>
<div class="filter">
<label for="sepia">Sepia</label>
<input type="range" min="0" max="100" value="0" id="sepia">
</div>
<div class="flip-buttons">
<div class="flip-option">
<input type="radio" name="flip" id="no-flip" checked>
<label for="no-flip">No Flip</label>
</div>
<div class="flip-option">
<input type="radio" name="flip" id="flip-x">
<label for="flip-x">Flip Horizontal</label>
</div>
<div class="flip-option">
<input type="radio" name="flip" id="flip-y">
<label for="flip-y">Flip Vertical</label>
</div>
</div>
</div>
<div class="result">
<figure class="image-container">
<img id="chosen-image">
</figure>
<input type="file" id="upload-button" accept="Image/*">
<label for="upload-button">Choose An Image</label>
</div>
</div>
<!-- Script -->
<script src="script.js"></script>
</body>
</html>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Rubik",sans-serif;
}
body{
background-color: #d3e8f5;
}
.wrapper{
width: 85vw;
min-height: 50vmin;
padding: 50px 30px;
background-color: #ffffff;
position: absolute;
transform: translate(-50%,-50%);
top: 50%;
left: 50%;
border-radius: 10px;
box-shadow: 0 20px 35px rgba(0,0,0,0.15);
display: grid;
grid-template-columns: 5fr 7fr;
}
.editor{
min-height: 35vmin;
display: flex;
flex-direction: column;
justify-content: space-around;
gap: 20px;
}
.editor label{
font-size: 2.8vmin;
color: #2a292a;
font-weight: 400;
}
.editor input[type="range"]{
display: block;
width: 100%;
position: relative;
margin-top: 5px;
}
.flip-buttons{
display: flex;
flex-direction: column;
margin-top: 10px;
}
.flip-buttons .flip-option{
margin-top: 10px;
}
.result{
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
gap: 20px;
}
.result img{
display: block;
position: relative;
max-width: calc(100% - 4vmin);
max-height: 45vmin;
margin: auto;
}
.image-container{
display: none;
}
input[type="file"]{
display: none;
}
.result label{
display: block;
position: relative;
margin: 0 auto;
width: 220px;
background-color: #025bee;
color: #ffffff;
text-align: center;
padding: 16px 0;
border-radius: 5px;
font-size: 2.8vmin;
font-weight: 400;
cursor: pointer;
}
@media screen and (max-width: 620px) {
.wrapper{
width: 95vw;
grid-template-columns: 1fr;
padding: 30px 20px;
gap: 10px;
}
.editor{
grid-row: 2;
}
.flip-buttons{
flex-direction: row;
justify-content: space-between;
}
.flip-buttons .flip-option{
margin-top: 0;
}
}
let filterA = document.getElementById("blur");
let filterB = document.getElementById("contrast");
let filterC = document.getElementById("hue-rotate");
let filterD = document.getElementById("sepia");
let noFlipBtn = document.getElementById("no-flip");
let flipXBtn = document.getElementById("flip-x");
let flipYBtn = document.getElementById("flip-y");
let uploadButton = document.getElementById("upload-button");
let image = document.getElementById("chosen-image");
function resetFilter(){
filterA.value = "0";
filterB.value = "100";
filterC.value = "0";
filterD.value = "0";
noFlipBtn.checked = true;
addFilter();
flipImage();
}
uploadButton.onchange = () => {
resetFilter();
document.querySelector(".image-container").style.display = "block";
let reader = new FileReader();
reader.readAsDataURL(uploadButton.files[0]);
reader.onload = () => {
image.setAttribute("src", reader.result);
}
}
let sliders = document.querySelectorAll(".filter input[type='range']");
sliders.forEach( slider => {
slider.addEventListener("input", addFilter);
});
function addFilter(){
image.style.filter = `blur(${filterA.value}px) contrast(${filterB.value}%) hue-rotate(${filterC.value}deg) sepia(${filterD.value}%)`;
}
let radioBtns = document.querySelectorAll(".flip-option input[type='radio']");
radioBtns.forEach( radioBtn => {
radioBtn.addEventListener("click", flipImage);
});
function flipImage(){
if(flipXBtn.checked){
image.style.transform = "scaleX(-1)";
}
else if(flipYBtn.checked){
image.style.transform = "scaleY(-1)";
}
else{
image.style.transform = "scale(1,1)";
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.