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>