1

I am having trouble creating a box with an inner shadow of a gradient that I want to be animated. I have attempted using a box-shadow which gives me the desired effect (Glow & Transparent center) but doesn't support a gradient. Does anyone have any idea?

My goal:

Goal

My current code so far:

.grid-element:hover {
  box-shadow:
    inset 0.3rem 0.3rem 0.3rem #CF77F3,
    inset -0.3rem 0.3rem 0.3rem #009BFF,
    inset 0.3rem -0.3rem 0.3rem #2AC9DB;
}
Benjamin Urquhart
  • 1,626
  • 12
  • 18
Adam
  • 13
  • 3

2 Answers2

1

You can rely on border-image and blur() filter to approximate this:

.box {
  margin: 20px;
  width: 150px;
  height: 150px;
  position: relative;
  overflow:hidden;
}
.box:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  border:5px solid transparent;
  border-image:linear-gradient(to bottom left,red,#009BFF,orange) 5;
  filter:blur(5px);
}

body {
 background:#f2f2f2;
}
<div class="box">

</div>

If you want to animate it you can consider multiple background where you can animate the position but you won't have transparency:

.box {
  margin: 20px;
  width: 150px;
  height: 150px;
  position: relative;
  overflow:hidden;
}
.box:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  border:5px solid transparent;
  background:
    linear-gradient(#fff,#fff) padding-box,
    linear-gradient(to bottom left,red,#009BFF,orange) border-box;
  background-size:200% 200%;
  background-position:top right;
  filter:blur(5px);
  animation:change 3s linear infinite alternate;
}

@keyframes change{
  to {
   background-position:bottom left;
  }
}
<div class="box">

</div>

To have transparency I would consider an extra element in order to build the borders with 4 pseudo elements:

.box {
  margin: 20px;
  width: 150px;
  height: 150px;
  position: relative;
  overflow:hidden;
  background-image:
    linear-gradient(to bottom left,pink 40%,blue 40% 60%,orange 60%);
  background-size: 0 0; 
  z-index:0;
}
.box span {
  background-image:inherit;
}
.box:before,
.box:after,
.box span:before,
.box span:after{
  content:"";
  position:absolute;
  z-index:0;
  background-image:inherit;
  background-size:300px 300px;
  filter:blur(5px);
  animation:change3 3s linear infinite alternate;
}
.box:before {
  top:0;
  left:0;
  right:0;
  height:5px; 
  background-position:left center;
}
.box:after {
  bottom:0;
  left:0;
  right:0;
  height:5px; 
  background-position:bottom left;
  animation-name:change1;
}
.box span:before {
  left:0;
  top:0;
  bottom:0;
  width:5px; 
  background-position:bottom left;
  animation-name:change2;
}
.box span:after {
  right:0;
  top:0;
  bottom:0;
  width:5px;
  background-position:bottom center;
}

@keyframes change1{
  to {background-position:center right;}
}
@keyframes change2{
  to {background-position:center top;}
}
@keyframes change3{
  to {background-position:top right;}
}


img {
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
}
<div class="box">
<img src="https://picsum.photos/id/37/200/300"/>
<span></span>
</div>

I used a different gradient to better see the animation. The trick is to use the same gradient with the same dimension on the 4 elements then we move them differently to create the illusion of one continuous move.

Check this to get more details about the background-position values: Using percentage values with background-position on a linear gradient


Another simplier idea is to consider clip-path:

.box {
  margin: 20px;
  width: 150px;
  height: 150px;
  position: relative;
  overflow: hidden;
}

.box span {
  filter: blur(5px);
  content: "";
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.box span:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: linear-gradient(to bottom left, pink 40%, blue 40% 60%, orange 60%);
  background-size: 200% 200%;
  background-position: top right;
  animation: change 3s linear infinite alternate;
  clip-path: polygon(0% 0%, 0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), 5px calc(100% - 5px), 5px 100%, 100% 100%, 100% 0%);
}

@keyframes change {
  to {
    background-position: bottom left;
  }
}

img {
  display: block;
  width: 100%;
  height: 100%;
}
<div class="box">
  <img src="https://picsum.photos/id/37/200/300" />
  <span></span>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Is there any way to make the center background transparent rather than white so I am able to show a background image through it? – Adam Jun 22 '19 at 20:36
  • @Adam with the animation I don't think so, probably I will find another trick later – Temani Afif Jun 22 '19 at 20:43
  • Alrighty, Been trying for a while now. Really trying to accomplish this. Starting to think this is impossible. – Adam Jun 22 '19 at 20:45
  • @Adam will find a solution, don't worry ;) I will ping when I find it – Temani Afif Jun 22 '19 at 20:47
  • Wow. This works great. How would I make the animation go infinitely in one direction rather than going back on itself? – Adam Jun 22 '19 at 23:21
  • @Adam remove `alternate` and change the gradient to have a smooth animation. adjust the colors and percentage until you get what you want. – Temani Afif Jun 22 '19 at 23:25
0

It's not completely clear from your example what animation you want to achieve.

However I hope that with some modifications this could help you:

.grid-element {
  width: 100px;
  height: 100px;
  animation-name: gradientAnimation;
  animation-duration: 4s;
  animation-iteration-count: infinite;
}

@keyframes gradientAnimation {
  0%,
  100% {
    box-shadow: inset 0.3rem 0.3rem 0.3rem #CF77F3,
                inset -0.3rem 0.3rem 0.3rem #009BFF,
                inset 0.3rem -0.3rem 0.3rem #2AC9DB;
  }
  50% {
    box-shadow: inset -0.3rem 0.3rem 0.3rem #009BFF,
                inset 0.3rem -0.3rem 0.3rem #2AC9DB,
                inset 0.3rem 0.3rem 0.3rem #CF77F3
  }
}
<div class="grid-element">
</div>
GalAbra
  • 5,048
  • 4
  • 23
  • 42
  • To get closer to my goal. I am wanting to use a linear-gradient and I don't think box-shadow is the way to go as it doesn't support linear-gradient which I'm wishing to use. Any other ideas? – Adam Jun 22 '19 at 17:25
  • The picture within my post is what I'm wanting to achieve. The animation is not exactly the issue. It's how would you put the gradient outline inside of a div with the desired glow effect. – Adam Jun 22 '19 at 17:37