<h1>Duotone Experiment</h1>
<div class="image-container">
<div class="layer layer1"></div>
<div class="layer layer2"></div>
<div class="layer layer3"></div>
</div>
<div class="container">
<div class="group">
<label for="grayscale1">Grayscale (Layer 1):</label>
<input type="range" id="grayscale1" min="0" max="1" step="0.1" value=".5">
<label for="brightness1">Brightness (Layer 1):</label>
<input type="range" id="brightness1" min="0" max="150" value="100">
<p>Layer 1 Filter: <span id="layer1-filter"></span></p>
</div>
<div class="group">
<label for="l2">Lightness (Layer 2):</label>
<input type="range" id="l2" min="0" max="150" value="50">
<label for="c2">Chroma (Layer 2):</label>
<input type="range" id="c2" min="0" max="100" value="50">
<label for="h2">Hue (Layer 2):</label>
<input type="range" id="h2" min="0" max="360" value="0">
<label for="blendMode2">Blend Mode (Layer 2):</label>
<select id="blendMode2">
<option value="normal">Normal</option>
<option value="multiply">Multiply</option>
<option value="screen" selected>Screen</option>
<option value="overlay">Overlay</option>
<option value="darken">Darken</option>
<option value="lighten">Lighten</option>
<option value="color-dodge">Color Dodge</option>
<option value="color-burn">Color Burn</option>
<option value="hard-light">Hard Light</option>
<option value="soft-light">Soft Light</option>
<option value="difference">Difference</option>
<option value="exclusion">Exclusion</option>
<option value="hue">Hue</option>
<option value="saturation">Saturation</option>
<option value="color">Color</option>
<option value="luminosity">Luminosity</option>
</select>
<p>Layer 2 Color: <span id="layer2-color"></span></p>
</div>
<div class="group">
<label for="l3">Lightness (Layer 3):</label>
<input type="range" id="l3" min="0" max="100" value="50">
<label for="c3">Chroma (Layer 3):</label>
<input type="range" id="c3" min="0" max="100" value="50">
<label for="h3">Hue (Layer 3):</label>
<input type="range" id="h3" min="0" max="360" value="0">
<label for="blendMode3">Blend Mode (Layer 3):</label>
<select id="blendMode3">
<option value="normal">Normal</option>
<option value="multiply" selected>Multiply</option>
<option value="screen">Screen</option>
<option value="overlay">Overlay</option>
<option value="darken">Darken</option>
<option value="lighten">Lighten</option>
<option value="color-dodge">Color Dodge</option>
<option value="color-burn">Color Burn</option>
<option value="hard-light">Hard Light</option>
<option value="soft-light">Soft Light</option>
<option value="difference">Difference</option>
<option value="exclusion">Exclusion</option>
<option value="hue">Hue</option>
<option value="saturation">Saturation</option>
<option value="color">Color</option>
<option value="luminosity">Luminosity</option>
</select>
<p>Layer 3 Color: <span id="layer3-color"></span></p>
</div>
<div class="css-output group">
<h2>Generated CSS:</h2>
<pre id="generated-css"></pre>
</div>
</div>
* {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
}
body {
display: flex;
flex-direction: column;
align-items: center;
font-family: Arial, sans-serif;
}
h1 {
margin: 20px 0;
}
.image-container {
position: relative;
width: 800px;
aspect-ratio: 16 / 9;
margin-bottom: 20px;
}
.layer {
position: absolute;
width: 100%;
height: 100%;
}
.layer1 {
background-image: url(https://assets.codepen.io/32795/waves.webp);
background-size: cover;
filter: grayscale(0.5) brightness(110%);
}
.layer2 {
background: oklch(45.93% 0.308 265.15);
mix-blend-mode: screen;
}
.layer3 {
background: oklch(73.12% 0.1946 351.856);
mix-blend-mode: multiply;
}
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 4rem;
}
.group {
display: flex;
flex-direction: column;
}
document.addEventListener("DOMContentLoaded", () => {
const layer1 = document.querySelector(".layer1");
const layer2 = document.querySelector(".layer2");
const layer3 = document.querySelector(".layer3");
const layer1FilterDisplay = document.getElementById("layer1-filter");
const layer2ColorDisplay = document.getElementById("layer2-color");
const layer3ColorDisplay = document.getElementById("layer3-color");
const generatedCssDisplay = document.getElementById("generated-css");
const updateLayer1Filter = (grayscale, brightness) => {
const brightnessValue = brightness + "%";
const filterValue = `grayscale(${grayscale}) brightness(${brightnessValue})`;
layer1.style.filter = filterValue;
layer1FilterDisplay.textContent = filterValue;
updateGeneratedCss();
};
const updateLayerColor = (layer, l, c, h, displayElement) => {
const color = `oklch(${l} ${c / 100} ${h})`;
layer.style.backgroundColor = color;
displayElement.textContent = color;
updateGeneratedCss();
};
const updateBlendMode = (layer, blendMode) => {
layer.style.mixBlendMode = blendMode;
updateGeneratedCss();
};
const updateGeneratedCss = () => {
const layer1Filter = layer1.style.filter;
const layer2Color = layer2.style.backgroundColor;
const layer2BlendMode = layer2.style.mixBlendMode;
const layer3Color = layer3.style.backgroundColor;
const layer3BlendMode = layer3.style.mixBlendMode;
const css = `
.layer1 {
filter: ${layer1Filter};
}
.layer2 {
background-color: ${layer2Color};
mix-blend-mode: ${layer2BlendMode};
}
.layer3 {
background-color: ${layer3Color};
mix-blend-mode: ${layer3BlendMode};
}
`;
generatedCssDisplay.textContent = css.trim();
};
document.getElementById("grayscale1").addEventListener("input", (event) => {
const grayscale = event.target.value;
const brightness = document.getElementById("brightness1").value;
updateLayer1Filter(grayscale, brightness);
});
document.getElementById("brightness1").addEventListener("input", (event) => {
const brightness = event.target.value;
const grayscale = document.getElementById("grayscale1").value;
updateLayer1Filter(grayscale, brightness);
});
document.getElementById("l2").addEventListener("input", (event) => {
const l = event.target.value;
const c = document.getElementById("c2").value;
const h = document.getElementById("h2").value;
updateLayerColor(layer2, l, c, h, layer2ColorDisplay);
});
document.getElementById("c2").addEventListener("input", (event) => {
const c = event.target.value;
const l = document.getElementById("l2").value;
const h = document.getElementById("h2").value;
updateLayerColor(layer2, l, c, h, layer2ColorDisplay);
});
document.getElementById("h2").addEventListener("input", (event) => {
const h = event.target.value;
const l = document.getElementById("l2").value;
const c = document.getElementById("c2").value;
updateLayerColor(layer2, l, c, h, layer2ColorDisplay);
});
document.getElementById("blendMode2").addEventListener("change", (event) => {
const blendMode = event.target.value;
updateBlendMode(layer2, blendMode);
});
document.getElementById("l3").addEventListener("input", (event) => {
const l = event.target.value;
const c = document.getElementById("c3").value;
const h = document.getElementById("h3").value;
updateLayerColor(layer3, l, c, h, layer3ColorDisplay);
});
document.getElementById("c3").addEventListener("input", (event) => {
const c = event.target.value;
const l = document.getElementById("l3").value;
const h = document.getElementById("h3").value;
updateLayerColor(layer3, l, c, h, layer3ColorDisplay);
});
document.getElementById("h3").addEventListener("input", (event) => {
const h = event.target.value;
const l = document.getElementById("l3").value;
const c = document.getElementById("c3").value;
updateLayerColor(layer3, l, c, h, layer3ColorDisplay);
});
document.getElementById("blendMode3").addEventListener("change", (event) => {
const blendMode = event.target.value;
updateBlendMode(layer3, blendMode);
});
// Initial colors and blend modes update
updateLayer1Filter(0.5, 100);
updateLayerColor(layer2, 50, 50, 10, layer2ColorDisplay);
updateLayerColor(layer3, 50, 50, 180, layer3ColorDisplay);
updateBlendMode(layer2, document.getElementById("blendMode2").value);
updateBlendMode(layer3, document.getElementById("blendMode3").value);
updateGeneratedCss();
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.