<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)";
    }
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.