2

I am trying to add a sliding hover filter effect to image. My original filter is grayscale(1).

So I need to the filter to transition with direction instead of the Slider overlay effect to have it to become colored: "grayscale(0)".

Basically i want the filter to be affected.

Is it possible?

Thank you in advance.

* {
  box-sizing: border-box;
}

body {
  background: #fefefe;
  color: #333;
  font: 14px/1.5 "Fira Sans", sans-serif;
}

h1 {
  font-size: 2.5rem;
  font-weight: 300;
  margin: 1.5em 0.5rem 1em;
  text-align: center;
}

.container {
  margin: 0 auto;
  padding: 2rem;
  max-width: 1200px;
}

.row {
  display: flex;
}

.col {
  color: #fff;
  flex: 1 1 auto;
  min-height: 260px;
  position: relative;
}

.col h2 {
  font-weight: 300;
  font-size: 1.33333rem;
  line-height: 1.25;
  margin: 0;
  position: absolute;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 0;
}

.col:nth-child(2) {
  min-width: 20%;
}

.col:nth-child(4) {
  min-width: 33%;
}

.col:nth-child(3)+.col:nth-child(3) {
  min-width: 50%;
}

.img-container {
  background: #0f0523 50% 50%/cover;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  transition: 1s;
  transform-origin: bottom right;
  filter: grayscale(1);
}

.img-container::before {
  background: linear-gradient(transparent, rgba(67, 17, 51, 0.5), #000320);
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.col:hover .photo-container {
  transform: scale(1.25);
}

.slide {
  background: rgba(0, 0, 0, 0.4);
  padding: 0 1.5rem;
}


/* THE EFFECT */

.col {
  overflow: hidden;
  position: relative;
}

.slide {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  transition: all 0.275s ease-in-out, visibility 0s 0.275s;
  visibility: hidden;
  will-change: transform;
  transform: translateY(100%);
}

.row:hover~.row .slide {
  transform: translateY(-100%);
}

.row:hover .slide {
  transform: translateX(100%);
}

.row:hover .col:hover~.col .slide {
  transform: translateX(-100%);
}

.row:hover .col:hover .slide {
  transform: none;
  visibility: visible;
  transition-delay: 0s;
}
<div class="container">
  <div class="row">
    <div class="col">
      <div class="img-container" style="background-image:url(https://source.unsplash.com/600x250/?sig=80);"></div>
      <h2>1 </h2>
      <div class="slide"></div>
    </div>
  </div>
  <div class="row">
    <div class="col">
      <div class="img-container" style="background-image:url(https://source.unsplash.com/600x250/?sig=212);"></div>
      <h2>2 </h2>
      <div class="slide"></div>
    </div>
    <div class="col">
      <div class="img-container" style="background-image:url(https://source.unsplash.com/600x250/?sig=242);"></div>
      <h2>3 </h2>
      <div class="slide"></div>
    </div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Rita
  • 37
  • 6
  • u have made slideoverlay effect now u want to have that effect in particular direction i'm right ? – Amaresh S M Jan 23 '20 at 07:34
  • Hello Amaresh, I want the effect direction on the filter. So when it gets back to its color, it gets back with a direction transition... sorry I hope I am explaining what I need right. I don't want the slider overlay color. I want the image color to change like the slider. – Rita Jan 23 '20 at 07:39
  • I know what you want to do Rita i've come up with some code for the moment that does somewhat the same but its not directional filter but still it works here you go : `.row:hover .col:hover .slide { transform: none; visibility: visible; transition-delay: 0s; }` if i find some free time later this day i'll come up with something. – Dev Kosov Jan 23 '20 at 08:01
  • Thank you Dev Kosov, i already have it written there. If you could figure it out I would be grateful. I am currently trying to use some Javascript or trying to find out if I could figure out, I am not very familiar with JS as I am still studying it. – Rita Jan 23 '20 at 09:08
  • Unfortunately, here is no way to do this with CSS. `filter` applies to *whole elements* not part of them. – Paulie_D Jan 23 '20 at 13:01
  • Paulie_D I do know but I want the filter on hover to move in a directional way just like the overlay but instead of the overlay the image would change back to color depends on the direction of the mouse. I am only stuck at applying the mouse direction to the filter(hover) – Rita Jan 23 '20 at 13:15
  • Hey @Rita sorry when i commented before i didn't copy the code i wrote i accidentualy copied something else so here is the code i wanted to send you before in the morning `.row:hover .col:hover .img-container { filter: grayscale(0); }` as i said before this will work but not with the directional filter. I'm now trying to make this work with directional filter. – Dev Kosov Jan 23 '20 at 18:52
  • So i've been playing with it around for 30mins and i don't think that i can do it but i can do the reverse of what you ask grayscale color pictures with directional hover by using `backdrop-filter:grayscale(1);` to slider here's the [codepen](https://codepen.io/DevKosov/pen/ZEYwJXV) – Dev Kosov Jan 23 '20 at 19:14
  • yea I have tried the reverse in a different way by playing with he overlay color mix. Would it be by any chance possible with jQuery or JS? Or is there any ways youc can add CSS to a filter... – Rita Jan 23 '20 at 21:50

1 Answers1

1

Here is an idea using mask where you can animate the mask-position. You can also rely on pseudo element for the image to avoid extra elements. The trick is to have two images above each other and we adjust the masking on the top to show the bottom one.

I removed the text to keep only the code related to the filter effect:

* {
  box-sizing: border-box;
}

body {
  background: #fefefe;
}

.container {
  margin: 0 auto;
  padding: 2rem;
  max-width: 1200px;
}

.row {
  display: flex;
}

.col {
  color: #fff;
  flex: 1 1 auto;
  min-height: 260px;
  position: relative;
}

.img-container {
  background-size:0 0;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.img-container::before,
.img-container::after {
  content: "";
  background-image: inherit;
  background-size:cover;
  background-position:center;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;

}
.img-container::before {
  filter: grayscale(1);
}

.img-container::after {
  transition: all 0.275s ease-in-out, visibility 0s 0.275s;
  visibility: hidden;
  -webkit-mask: linear-gradient(#fff,#fff);
  -webkit-mask-size: 200% 200%;
  -webkit-mask-position:left 0 bottom 200%;
  -webkit-mask-repeat: no-repeat;
  mask: linear-gradient(#fff,#fff);
  mask-size: 200% 200%;
  mask-position:left 0 bottom 200%;
  mask-repeat: no-repeat;
}


.row:hover~.row .img-container::after {
  -webkit-mask-position:left 0 top 200%;
  mask-position:left 0 top 200%;
}

.row:hover .img-container::after {
  -webkit-mask-position:right 200% top 0;
  mask-position:right 200% top 0;

}

.row:hover .col:hover~.col .img-container::after {
  -webkit-mask-position:left 200% top 0;
  mask-position:left 200% top 0;
}

.row:hover .col:hover .img-container::after {
  visibility: visible;
  transition-delay: 0s;
  -webkit-mask-position:0 0%;
  mask-position:0 0%;
  
}
<div class="container">
  <div class="row">
    <div class="col">
      <div class="img-container" style="background-image:url(https://picsum.photos/id/1012/800/800);"></div>
    </div>
  </div>
  <div class="row">
    <div class="col">
      <div class="img-container" style="background-image:url(https://picsum.photos/id/1014/800/800);"></div>
    </div>
    <div class="col">
      <div class="img-container" style="background-image:url(https://picsum.photos/id/16/800/800);"></div>
    </div>
  </div>
</div>

mask in this case works the same way as background so you can check this question/answer to get more details about the calculation: Using percentage values with background-position on a linear gradient

Changing mask with background to better see the trick:

* {
  box-sizing: border-box;
}

body {
  background: grey;
}

.container {
  margin: 0 auto;
  padding: 2rem;
  max-width: 1200px;
}

.row {
  display: flex;
}

.col {
  color: #fff;
  flex: 1 1 auto;
  min-height: 260px;
  position: relative;
}


.col:nth-child(2) {
  min-width: 20%;
}

.col:nth-child(4) {
  min-width: 33%;
}

.col:nth-child(3)+.col:nth-child(3) {
  min-width: 50%;
}

.img-container {
  background-position:center;
  background-size:0 0;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  transition: 1s;
  transform-origin: bottom right;
}

.img-container::before {
  background: inherit;
  background-size:cover;
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  filter: grayscale(1);
}

.img-container::after {
  content:"";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  transition: all 0.275s ease-in-out, visibility 0s 0.275s;
  visibility: hidden;
  background: linear-gradient(#fff,#fff);
  background-size: 200% 200%;
  background-position:left 0 bottom 200%;
  background-repeat: no-repeat;
}


.col {
  overflow: hidden;
  position: relative;
}

.row:hover~.row .img-container::after {
  background-position:left 0 top 200%;
}

.row:hover .img-container::after {
  background-position:right 200% top 0;

}

.row:hover .col:hover~.col .img-container::after {
  background-position:left 200% top 0;
}

.row:hover .col:hover .img-container::after {
  visibility: visible;
  transition-delay: 0s;
  background-position:0 0%;
  
}
<div class="container">
  <div class="row">
    <div class="col">
      <div class="img-container" style="background-image:url(https://picsum.photos/id/1012/800/800);"></div>
    </div>
  </div>
  <div class="row">
    <div class="col">
      <div class="img-container" style="background-image:url(https://picsum.photos/id/1014/800/800);"></div>
    </div>
    <div class="col">
      <div class="img-container" style="background-image:url(https://picsum.photos/id/16/800/800);"></div>
    </div>
  </div>
</div>

Basically the white color is the visible part of the image, so sliding it will make our image without filter visible.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415