<div class="container">
  <h1>Dramatic Effect Sections</h1>
  <p>Mouse over or tap on the section card to view effect.</p>
  <div class="row">
    <div class="col-12 col-sm-6 col-lg-3 section-card" id="section-1">
      <div class="img-container" id="section-1-image">
        <img src="https://images.pexels.com/photos/712521/pexels-photo-712521.jpeg" id="test-img" alt="" />
      </div>
      <h3>Default Behavior</h3>
      <p>The default behavior consists of a slightly sepia image that grows while regaining all its color.</p>
      <p><strong>Results may vary for Internet Explorer users because IE does not support CSS variables or <code>clip-path</code></strong>.</p>
    </div>
    <div class="col-12 col-sm-6 col-lg-3 section-card" id="section-2">
      <div class="img-container">
        <img src="https://images.pexels.com/photos/712521/pexels-photo-712521.jpeg" id="test-img" alt="" />
      </div>
      <h3>...with <code>clip-path</code></h3>
      <p>If you add a <code>clip-path</code>, then only the clipped/highlighted area of the front will grow and regain color. The background will go darker and blurrier to create a dramatic effect</p>
    </div>
    <div class="col-12 col-sm-6 col-lg-3 section-card" id="section-3">
      <div class="img-container">
        <img src="https://images.pexels.com/photos/712521/pexels-photo-712521.jpeg" id="test-img" alt="" />
      </div>
      <h3>Change the effects</h3>
      <p>By specifying the initial and hover values for the animation (based on CSS filters and transformations), you can create different effects for each image. You can use: blur, brightness, grayscale, or sepia.</p>
    </div>
    <div class="col-12 col-sm-6 col-lg-3 section-card" id="section-4">
      <div class="img-container">
        <img src="https://images.pexels.com/photos/712521/pexels-photo-712521.jpeg" id="test-img" alt="" />
      </div>
      <h3>Responsive</h3>
      <p>If the <code>clip-path</code> value is in percentages, it will behave in a responsive way. You can see an example by resizing this window (Bootstrap was used as a base for the demo, but it is not needed for the code to run.)</p>
    </div>
  </div>
</div>
.img-container {
  width: 100%;
  height: 0;
  padding-top: 66.66%;
  position: relative;
  overflow: hidden;
}

.img-container img {
  position: absolute;
  width: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);
}

.section-card { 
  /*border: 4px solid transparent;*/ 
  padding-top: 15px; 
  transition: all 0.5s;
  display: inline-block;
  cursor: pointer;
}

.section-card:hover {
  /*border: 4px solid #beeeef;*/
  background: #f8f8f8;
}

.section-card h3 {
  margin-top: 0.5em;
}


/** DREFF STYLES **/
.dreff-holder {
  position: relative;
  overflow: hidden;
}

.dreff-holder .dreff-img {
  --blur: 0;
  --brightness: 1;
  --grayscale: 0;
  --scale: 1;
  --sepia: 0.5;
  --front-blur: 0;
  --front-brightness: 1;
  --front-grayscale: 0;
  --front-scale: 1;
  --front-sepia: 0.5;
  --duration: 0.5s;
  --hover-blur: 3px;
  --hover-brightness: 0.6;
  --hover-grayscale: 1;
  --hover-scale: 1;
  --hover-sepia: 0;
  --hover-duration: 2s;
  --hover-front-blur: 0;
  --hover-front-brightness: 1;
  --hover-front-grayscale: 0;
  --hover-front-scale: 1.15;
  --hover-front-sepia: 0;
  --hover-front-duration: 3s;
  --hover-front-clippath: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(var(--scale));
  -webkit-transform: translate(-50%, -50%) scale(var(--scale));
  filter: blur(var(--blur)) brightness(var(--brightness)) grayscale(var(--grayscale)) sepia(var(--sepia));
  -webkit-filter: blur(var(--blur)) brightness(var(--brightness)) grayscale(var(--grayscale)) sepia(var(--sepia));
  transition: var(--duration);
  -webkit-transition: var(--duration);
}

.dreff-holder .dreff-front {
  transform: translate(-50%, -50%) scale(var(--front-scale));
  -webkit-transform: translate(-50%, -50%) scale(var(--front-scale));
  filter: blur(var(--front-blur)) brightness(var(--front-brightness)) grayscale(var(--front-grayscale)) sepia(var(--front-sepia));
  -webkit-filter: blur(var(--front-blur)) brightness(var(--front-brightness)) grayscale(var(--front-grayscale)) sepia(var(--front-sepia));
  clip-path: var(--hover-front-clippath);
  -webkit-clip-path: var(--hover-front-clippath);
}

.dreff-holder:hover .dreff-back {
  filter: blur(var(--hover-blur)) brightness(var(--hover-brightness)) grayscale(var(--hover-grayscale)) sepia(var(--hover-sepia));
  -webkit-filter: blur(var(--hover-blur)) brightness(var(--hover-brightness)) grayscale(var(--hover-grayscale)) sepia(var(--hover-sepia));
  transform: translate(-50%, -50%) scale(var(--hover-scale));
  -webkit-transform: translate(-50%, -50%) scale(var(--hover-scale));
  transition: all var(--hover-duration);
}

.dreff-holder:hover .dreff-front {
  filter: blur(var(--hover-front-blur)) brightness(var(--hover-front-brightness)) grayscale(var(--hover-front-grayscale)) sepia(var(--hover-front-sepia));
  -webkit-filter: blur(var(--hover-front-blur)) brightness(var(--hover-front-brightness)) grayscale(var(--hover-front-grayscale)) sepia(var(--hover-front-sepia));
  transform: translate(-50%, -50%) scale(var(--hover-front-scale));
  -webkit-transform: translate(-50%, -50%) scale(var(--hover-front-scale));
  transition: all var(--hover-front-duration);
}
/**
 ** Dreff: a function to create dramatic effects on images
 **/
const Dreff = (arg) => {

  // some basic values
  let init = ".dreff";
  let clipPath = "";
  let clipType = "polygon";
  
  // if no values are specified, create a fake object (it will default)
  let args = arg || { };
  if (!args.hover) { args.hover = { back:{}, front:{} } }
  if (!args.hover.back) { args.hover.back = {} }
  if (!args.hover.front) { args.hover.front = {} }
  if (!args.initial) { args.initial = { back:{}, front:{} } }
  if (!args.initial.back) { args.initial.back = {} }
  if (!args.initial.front) { args.initial.front = {} }

  // update default settings
  init = args.init ? args.init : init;

  // apply all to the selectors
  let elements = document.querySelectorAll(init);
  elements.forEach((el) => {
    
    // add the dreff classes, and duplicate image
    el.classList.add("dreff-holder")
    let img = el.querySelector("img");
    let parent = img.parentNode;
    let clone = img.cloneNode(true);
    img.classList.add("dreff-back");
    img.classList.add("dreff-img");
    clone.classList.add("dreff-front");
    clone.classList.add("dreff-img");
    
    // generate clip-path if specified
    if (args.clipPath) {
      clipType = args.clipType ? args.clipType : "polygon";
      clipPath = args.clipPath ? clipType + "(" + args.clipPath + ")" : "";
      clone.style.setProperty("--hover-front-clippath", clipPath);
    }
    
    // set initial state for front and back images
    if (args.initial.back.hasOwnProperty("blur")) { img.style.setProperty("--blur", args.initial.back.blur); }
    if (args.initial.back.hasOwnProperty("brightness")) { img.style.setProperty("--brightness", args.initial.back.brightness); }
    if (args.initial.back.hasOwnProperty("grayscale")) { img.style.setProperty("--grayscale", args.initial.back.grayscale); }
    if (args.initial.back.hasOwnProperty("scale")) { img.style.setProperty("--scale", args.initial.back.scale); }
    if (args.initial.back.hasOwnProperty("sepia")) { img.style.setProperty("--sepia", args.initial.back.sepia); }
    
    if (args.initial.front.hasOwnProperty("blur")) { clone.style.setProperty("--front-blur", args.initial.front.blur); }
    if (args.initial.front.hasOwnProperty("brightness")) { clone.style.setProperty("--front-brightness", args.initial.front.brightness); }
    if (args.initial.front.hasOwnProperty("grayscale")) { clone.style.setProperty("--front-grayscale", args.initial.front.grayscale); }
    if (args.initial.front.hasOwnProperty("scale")) { clone.style.setProperty("--front-scale", args.initial.front.scale); }
    if (args.initial.front.hasOwnProperty("sepia")) { clone.style.setProperty("--front-sepia", args.initial.front.sepia); }
    
    // set hover state for front and back images
    if (args.hover.back.duration) { img.style.setProperty("--hover-duration", args.hover.back.duration); }
    if (args.hover.back.hasOwnProperty("blur")) { img.style.setProperty("--hover-blur", args.hover.back.blur); }
    if (args.hover.back.hasOwnProperty("brightness")) { img.style.setProperty("--hover-brightness", args.hover.back.brightness); }
    if (args.hover.back.hasOwnProperty("grayscale")) { img.style.setProperty("--hover-grayscale", args.hover.back.grayscale); }
    if (args.hover.back.hasOwnProperty("scale")) { img.style.setProperty("--hover-scale", args.hover.back.scale); }
    if (args.hover.back.hasOwnProperty("sepia")) { img.style.setProperty("--hover-sepia", args.hover.back.sepia); }
    
    if (args.hover.front.duration) { clone.style.setProperty("--hover-front-duration", args.hover.front.duration); }
    if (args.hover.front.hasOwnProperty("blur")) { clone.style.setProperty("--hover-front-blur", args.hover.front.blur); }
    if (args.hover.front.hasOwnProperty("brightness")) { clone.style.setProperty("--hover-front-brightness", args.hover.front.brightness); }
    if (args.hover.front.hasOwnProperty("grayscale")) { clone.style.setProperty("--hover-front-grayscale", args.hover.front.grayscale); }
    if (args.hover.front.hasOwnProperty("scale")) { clone.style.setProperty("--hover-front-scale", args.hover.front.scale); }
    if (args.hover.front.hasOwnProperty("sepia")) { clone.style.setProperty("--hover-front-sepia", args.hover.front.sepia); }

    // add the second picture to the container
    parent.appendChild(clone);
  })
}
/** END **/

// #section-1 will be default: only grow front image
Dreff({ init: "#section-1" });

// #section-2 will be default, but the front will be clipped to create an effect
Dreff({ init: "#section-2", clipPath: "22% 100%,22% 84%,25% 70%,29% 60%,34% 47%,36% 32%,40% 18%,45% 13%,51% 12%,55% 16%,59% 22%,60% 29%,59% 38%,58% 48%,58% 55%,57% 60%,55% 61%,57% 71%,61% 79%,65% 100%" });

// #section-3 will start as a shadow and will reveal front as the effect
Dreff({
  init: "#section-3",
  initial: {
    back: {
      grayscale: 1,
      brightness: 0.4,
      sepia: 0,
    },
    front: {
      brightness: 0,
      grayscale: 1,
      sepia: 0
    }
  },
  hover: {
    front: {
      grayscale: 0,
      scale: 1.6
    },
    back: {
      blur: 0,
      grayscale: 0,
      sepia: 0.7
    }
  },
  clipPath: "22% 100%,22% 84%,25% 70%,29% 60%,34% 47%,36% 32%,40% 18%,45% 13%,51% 12%,55% 16%,59% 22%,60% 29%,59% 38%,58% 48%,58% 55%,57% 60%,55% 61%,57% 71%,61% 79%,65% 100%"
}); 

Dreff({
  init: "#section-4",
  clipPath: "22% 100%,22% 84%,25% 70%,29% 60%,34% 47%,36% 32%,40% 18%,45% 13%,51% 12%,55% 16%,59% 22%,60% 29%,59% 38%,58% 48%,58% 55%,57% 60%,55% 61%,57% 71%,61% 79%,65% 100%",
  initial: {
    back: { sepia: 0 },
    front: { sepia: 0 }
  },
  hover: {
    back: {
      blur: 0
    },
    front: {
      scale: 1,
      sepia: 0.3,
      duration: "0.6s"
    }
  }
});
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.2/css/bootstrap.min.css

External JavaScript

This Pen doesn't use any external JavaScript resources.