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

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.