2

I am trying to re-create Twitch's hover effect when hovering over game art.

https://i.stack.imgur.com/lxipo.jpg

I have tried using clip-path, but cannot get the correct shape I am looking for. I'm not even sure if clip-path is what I should be using nor if my code would be the best for re-creating this type of effect.

https://codepen.io/thomaschsu/pen/Rwwwgex

.img-full {
  position: absolute;
  width: 18rem;
  margin: 50px;
  transition: transform 0.1s ease;
  max-height: 50vh;
  max-width: 35vh;
}

.box {
  position: relative;
  top: 11vh;
  left: 11vh;
  height: 47vh;
  width: 35vh;
  background-color: #9147ff;
  z-index: -1;
  display: none;
  clip-path: polygon(100% 0, 100% 85%, 92% 100%, 0 100%, 0 20%, 20% 0);
}

.img-full:hover {
   transform: translate(5%, -2%);
}

.img-full:hover + .box {
  display: block;
}
Mr. Hugo
  • 11,887
  • 3
  • 42
  • 60
Tom Hsu
  • 39
  • 6

4 Answers4

2

Here is an idea with border and gradient:

img {
 width:150px;
 margin:20px;
 border:0 solid transparent;  
 border-image:linear-gradient(-45deg,transparent 14px,red 15px calc(100% - 15px), transparent calc(100% - 14px)) 10;
 transition:0.3s all;
}
img:hover {
  border-left-width:10px;
  border-bottom-width:10px;
  margin-top:10px;
}
<img src="https://i.imgur.com/cFeWhuf.jpg">

Same trick with padding and background:

img {
 width:150px;
 margin:20px;
 padding:0;  
 background:linear-gradient(-45deg,transparent 6px,red 7px calc(100% - 7px), transparent calc(100% - 6px));
 transition:0.3s all;
}
img:hover {
  padding:0 0 10px 10px;
  margin-top:10px;
}
<img src="https://i.imgur.com/cFeWhuf.jpg">
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

I've been taking a look at the website and I think they are using two invisible corners that turn to visible and flipped when the image is hovered.

I've forked your codepen and did something with this idea, check out: https://codepen.io/ograu/pen/xxxxLLX

.img-banner {
  background: #9147ff;
  position: relative;
  max-height: 50vh;
  max-width: 35vh;    
  width: 18rem;
  margin: 50px;
}

.img-banner:hover .corner {
  transform: rotate(-45deg) scaleX(1);
  transition-delay: 75ms;
  display: block;
}

.img-full {
  width: 100%;
  height: 100%;
  transition: transform 0.1s ease;
  display: block;
}

.img-full:hover {
  transform: translate(9px, -9px);
}

.corner {
  background: #9147ff;
  height: .8rem;
  transition: transform .1s ease;
  width: .8rem;
  position: absolute;
  display: none;
}

.top-left {
  top: -5px;
  left: 2px;
}

.bottom-right {
  bottom: 4px;
  right: -5px;
}
Oriol Grau
  • 609
  • 6
  • 8
1

you can also use a shadow

.img-banner {
float:left;/* ?? for the demo */
}
.img-full {
  width: 18rem;
  margin: 20px;
  transition:  0.1s ease;
  max-height: 50vh;
  max-width: 35vh;
  display:block;
  
}

.img-full:hover {
   transform: translate(5%, -2%);
 box-shadow:-1px 1px  #9147ff, -2px 2px  #9147ff, -3px 3px  #9147ff, -4px 4px  #9147ff, -5px 5px  #9147ff, -6px 6px  #9147ff, -7px 7px  #9147ff, -8px 8px  #9147ff;
}
<div class="img-banner">
  <img class="img-full" src="https://i.imgur.com/cFeWhuf.jpg">
</div>
<div class="img-banner">
  <img class="img-full" src="https://i.imgur.com/cFeWhuf.jpg">
</div>
<div class="img-banner">
  <img class="img-full" src="https://i.imgur.com/cFeWhuf.jpg">
</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
0

1. The obvious solution (with bad performance)

You could do this with box-shadow and triangular before and after pseudo elements. The bad thing here is the performance. The good thing is that if pseudo elements OR transitions are not supported, you still get a nice result (a purple box shadow).

.imgholder {display: inline-block; position: relative; left: 0; bottom: 0; box-shadow: 0px 0px 0px 0px #9147ff;}
.imgholder img {display: block; width: 200px; height: 100px;}
.imgholder:hover {box-shadow: -6px 6px 0px 0px #9147ff; position: relative; left: 6px; bottom: 6px;}
.imgholder::after {content: ""; position: absolute; right: 0; width: 0; height: 0; border: 0px solid transparent; border-top: 0px solid #9147ff;}
.imgholder:hover::after {border: 6px solid transparent; border-top: 6px solid #9147ff;}
.imgholder::before {content: ""; position: absolute; top: 0;left: 0; width: 0; height: 0; border: 0px solid transparent; border-right: 0px solid #9147ff; margin-left: 0px;}
.imgholder:hover::before {border: 6px solid transparent; border-right: 6px solid #9147ff; margin-left: -12px;}
.imgholder, .imgholder::before, .imgholder::after {transition: all 0.1s linear;}
<br /><div class="imgholder"><img src="https://i.imgur.com/ukqAxha.gif" /></div>

2. The solution Twitch used (with good performance)

This one is really clever. It uses 'scale' and a small rotated square (45 degrees). Note that the squares have a different transform-origin and a different rotation (direction). Performance and graceful degredation are both pretty good. This seems like the optimal solution to me.

*{font-size: 14px;}
.imgholder {
  background: #9147ff; 
  display: inline-block;
  position: relative;
}
.imgholder img {
  transition: all 0.1s ease; 
  display: block; 
  width: 200px; 
  height: 100px; 
  transform: translate3d(0,0,0);
}
.imgholder:hover img {
  transform: translate3d(.6rem,-.6rem,0); 
  transition-delay: 75ms;
}
.corner_bottom_right, .corner_top_left {
  left: 0; 
  top: 0; 
  width: .8rem;
  height: .8rem; 
  transition: all 0.1s ease; 
  transform: rotate(-45deg) scale(0);
  background: #9147ff; 
  position: absolute; z-index: 0;
  transform-origin: 0% 0%;
}
.corner_bottom_right {
  left: auto; 
  top: auto; 
  right: 0; 
  bottom: 0; 
  transform: rotate(45deg) scale(0);
  transform-origin: 100% 100%;
}
.imgholder:hover .corner_bottom_right,
.imgholder:hover .corner_top_left {
  transform: rotate(-45deg) scale(1); 
  transition-delay: 75ms;
}
.imgholder:hover .corner_bottom_right {
  transform: rotate(45deg) scale(1);
}
<br /><div class="imgholder">
  <div class="corner_top_left"></div>
  <div class="corner_bottom_right"></div>
  <img src="https://i.imgur.com/ukqAxha.gif" />
</div>

3. Minimum amount of code (with some glitches)

The previous solutions required a lot of code. This one uses a minimum amount of code and uses the box-shadow property. I like the simplicity, but note that this solution might not look smooth on a retina display. Additionally, hovering the bottom shadow glitches and the timing seems a bit off in Firefox.

img {width: 200px; height: 100px; transition: all 0.1s ease;}
img:hover {
   transform: translate(8px, -8px);
   box-shadow: -1px 1px  #9147ff, 
               -2px 2px  #9147ff, 
               -3px 3px  #9147ff, 
               -4px 4px  #9147ff, 
               -5px 5px  #9147ff, 
               -6px 6px  #9147ff, 
               -7px 7px  #9147ff, 
               -8px 8px  #9147ff;
}
<br /><img src="https://i.imgur.com/ukqAxha.gif" />

4. Using clip-path (great performance)

The question really inspired me to create a clip-path solution. I used fixed sizes to make it easier to understand. The solution requires some smart cropping, using overflow: hidden.

.imgholder {
  position: relative; 
  display: inline-block;
  width: 200px;
  height: 100px;
  overflow: hidden;
  transition: all 0.1s ease;
  bottom: 0;
}
.imgholder img {
  margin-top: -8px;
  margin-right: -8px;
  position: relative;
  display: block;
  width: 200px;
  height: 100px;
  transition: all 0.1s ease;
  border-right: 8px solid transparent;
  border-top: 8px solid transparent;
}

.clippath {
  margin-top: -8px;
  margin-right: -8px;
  position: absolute;
  top: 0;
  left: 0;
  width: 208px;
  height: 108px;
  background-color: #9147ff;
  clip-path: polygon(0px 108px, 200px 108px, 208px 100px, 208px 0px, 8px 0px, 0px 8px);
  transition: all 0.1s ease;
}

.imgholder:hover img,
.imgholder:hover .clippath {
  margin-top: 0;
}
.imgholder:hover img {
   transform: translate(8px, -8px);
}
.imgholder:hover {
  width: 208px;
  height: 108px;
  bottom: 8px;
  margin-bottom: -8px;
}
<br />
<div class="imgholder">
  <div class="clippath"></div>
  <img src="https://i.imgur.com/ukqAxha.gif">
</div>

<br /><br />
<div class="clippath" style="position: relative;"></div>
Mr. Hugo
  • 11,887
  • 3
  • 42
  • 60