Related
I'm trying to create a "cycling rainbow glow" effect for text in CSS. I've more or less accomplished that, but I've ran into something I can't explain. When I remove the superfluous filter: blur(0px) from the parent element the ::after psudo-element collapses to the left.
.rainbow {
display: inline-block;
color: white;
filter: blur(0px);
}
.rainbow::after {
content: attr(data-text);
z-index: -1;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: linear-gradient(90deg,
hsl(0, 100%, 50%),
hsl(30, 100%, 50%),
hsl(60, 100%, 50%),
hsl(90, 100%, 50%),
hsl(120, 100%, 50%),
hsl(150, 100%, 50%),
hsl(180, 100%, 50%),
hsl(210, 100%, 50%),
hsl(240, 100%, 50%),
hsl(270, 100%, 50%),
hsl(300, 100%, 50%),
hsl(330, 100%, 50%),
hsl(360, 100%, 50%))
0 0 / 200% 100%;
-webkit-background-clip: text;
-moz-background-clip: text;
-webkit-text-fill-color: transparent;
-moz-text-fill-color: transparent;
filter: blur(10px);
animation: scroll_background 2s linear infinite;
}
#keyframes scroll_background {
to { background-position: -200% 0 }
}
https://jsfiddle.net/tpm1gf5v/
It looks like this is because without filter: blur(0px), the rainbow is no longer a relative container (according to this answer), and also does not have a stacking context to place ::after properly.
This may have caused ::after to be placed relative to body which resulted in the error.
It seems to be fixed by giving rainbow a relative positioning, and specify a new stacking context:
.rainbow {
display: inline-block;
color: white;
/* 👇 Add this */
position: relative;
/* 👇 Add one of these two for a new stacking context */
isolation: isolate;
/* z-index: 0; */
}
Example: (modified from the posted jsfiddle)
html,
body {
background: #d6daf0;
font-family: arial, helvetica, sans-serif;
font-size: 100px;
}
.rainbow {
display: inline-block;
color: white;
/* 👇 Add this */
position: relative;
/* 👇 Add one of these two for a new stacking context */
isolation: isolate;
/* z-index: 0; */
}
.rainbow::after {
content: attr(data-text);
z-index: -1;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: linear-gradient(90deg,
hsl(0, 100%, 50%),
hsl(30, 100%, 50%),
hsl(60, 100%, 50%),
hsl(90, 100%, 50%),
hsl(120, 100%, 50%),
hsl(150, 100%, 50%),
hsl(180, 100%, 50%),
hsl(210, 100%, 50%),
hsl(240, 100%, 50%),
hsl(270, 100%, 50%),
hsl(300, 100%, 50%),
hsl(330, 100%, 50%),
hsl(360, 100%, 50%)) 0 0 / 200% 100%;
-webkit-background-clip: text;
-moz-background-clip: text;
-webkit-text-fill-color: transparent;
-moz-text-fill-color: transparent;
filter: blur(10px);
animation: scroll_background 2s linear infinite;
}
#keyframes scroll_background {
to {
background-position: -200% 0
}
}
<span class="rainbow" data-text="Hello, World!">Hello, World!</span>
Hope this will help.
so, i'm trying to achieve this kind of animated border with css
sample of the border
the sample animated css is:
#keyframes bg {
0% {
background-size: 0 3px,
3px 0,
0 3px,
3px 0;
}
25% {
background-size: 100% 3px,
3px 0,
0 3px,
3px 0;
}
50% {
background-size: 100% 3px,
3px 100%,
0 3px,
3px 0;
}
75% {
background-size: 100% 3px,
3px 100%,
100% 3px,
3px 0;
}
100% {
background-size: 100% 3px,
3px 100%,
100% 3px,
3px 100%;
}
}
div {
width: 25%;
margin: 2rem auto;
padding: 2em;
background-repeat: no-repeat;
background-image: linear-gradient(to right, #f5ca00 100%, #f5ca00 100%),
linear-gradient(to bottom, #f5ca00 100%, #f5ca00 100%),
linear-gradient(to right, #f5ca00 100%, #f5ca00 100%),
linear-gradient(to bottom, #f5ca00 100%, #f5ca00 100%);
background-size: 100% 3px,
3px 100%,
100% 3px,
3px 100%;
background-position: 0 0,
100% 0,
100% 100%,
0 100%;
animation: bg 1.25s cubic-bezier(0.19, 1, 0.22, 1) 1;
animation-play-state: paused;
}
div:hover {
animation-play-state: running;
}
<div>
<img src="https://moro.fund/wp-content/uploads/2020/08/scale-photo.png" alt="">
</div>
i just want the last animated line to be half and inside the image just like the sample at the start :)
please note that is gonna be used inside wordpress.
any kind of help or guidance is appreciated.
Try to add to div styles with :after pseudo class and animate it on hover or on initail animations.
#keyframes bg {
0% {
background-size: 0 3px,
3px 0,
0 3px,
3px 0;
}
25% {
background-size: 100% 3px,
3px 0,
0 3px,
3px 0;
}
50% {
background-size: 100% 3px,
3px 100%,
0 3px,
3px 0;
}
75% {
background-size: 100% 3px,
3px 100%,
100% 3px,
3px 0;
}
100% {
background-size: 100% 3px,
3px 100%,
100% 3px,
3px 100%;
}
}
div {
width: 25%;
margin: 2rem auto;
padding: 2em;
background-repeat: no-repeat;
background-image: linear-gradient(to right, #f5ca00 100%, #f5ca00 100%),
linear-gradient(to bottom, #f5ca00 100%, #f5ca00 100%),
linear-gradient(to right, #f5ca00 100%, #f5ca00 100%),
linear-gradient(to bottom, #f5ca00 100%, #f5ca00 100%);
background-size: 100% 3px,
3px 100%,
100% 3px,
3px 100%;
background-position: 0 0,
100% 0,
100% 100%,
0 100%;
animation: bg 1.25s cubic-bezier(0.19, 1, 0.22, 1) 1;
animation-play-state: paused;
position: relative;
}
div:hover {
animation-play-state: running;
}
div:after{
content: '';
width: 2px;
height: 0;
background: #f5ca00;
position: absolute;
right: 0;
top: 0;
transition: height .3s ease;
}
div:hover:after {
height: 100px;
}
<div>
<img src="https://moro.fund/wp-content/uploads/2020/08/scale-photo.png" alt="">
</div>
I have tried so far.
body {
margin:0;
padding:20px;
background-color: #000;
}
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(to bottom, #fff 0%, #fff 20%, transparent 20%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 40%, #fff 40%, #fff 60%, transparent 60%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 80%, #fff 80%, #fff 100%);
}
<div class="mobil-menu__icon"></div>
Use only solid color in gradient and rely on background-size:
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
/* position / width height */
linear-gradient(#fff,#fff) top left / 100% 20%,
linear-gradient(#fff,#fff) center left / 80% 20%,
linear-gradient(#fff,#fff) bottom left / 60% 20%,
red;
border:10px solid red;
background-repeat:no-repeat; /* Never forget this! */
}
<div class="mobil-menu__icon"></div>
With hover animation:
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(#fff,#fff) top left,
linear-gradient(#fff,#fff) center left,
linear-gradient(#fff,#fff) bottom left,
red;
background-size:
100% 20%,
80% 20%,
60% 20%;
border:10px solid red;
background-repeat:no-repeat;
transition:0.3s all;
}
.mobil-menu__icon:hover {
background-size:100% 20%;
}
<div class="mobil-menu__icon"></div>
And if you want with transparency:
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(red,red) 0 calc(1*100%/4) / 100% 20%,
linear-gradient(red,red) 0 calc(3*100%/4) / 100% 20%,
linear-gradient(red,red) 100% calc(2*100%/4) / 20% 20%,
linear-gradient(red,red) 100% calc(4*100%/4) / 40% 20%;
border:10px solid red;
background-repeat:no-repeat;
}
body {
background:repeating-linear-gradient(to right,white 0 5px,grey 10px);
}
<div class="mobil-menu__icon"></div>
You were also almost good with your code but you were missing the size and the repeat:
body {
margin: 0;
padding: 20px;
background-color: #000;
}
.mobil-menu__icon {
height: 50px;
width: 50px;
background:
linear-gradient(to bottom, #fff 0%, #fff 20%, transparent 20%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 40%, #fff 40%, #fff 60%, transparent 60%, transparent 100%),
linear-gradient(to bottom, transparent 0%, transparent 80%, #fff 80%, #fff 100%);
background-size:100% 100%,80% 100%, 60% 100%;
background-repeat:no-repeat;
}
<div class="mobil-menu__icon"></div>
Related question to get more details about the different values:
Using percentage values with background-position on a linear gradient
button {
background: none;
border: 0;
box-sizing: border-box;
margin: 1em;
padding: 1em 2em;
box-shadow: inset 0 0 0 2px #f45e61;
color: #f45e61;
font-size: inherit;
font-weight: 700;
position: relative;
vertical-align: middle;
}
button::before, button::after {
box-sizing: inherit;
content: " ";
position: absolute;
width: 100%;
height: 100%;
}
.draw {
transition: color 0.25s;
}
.draw::before, .draw::after {
border: 2px solid transparent;
width: 0;
height: 0;
transition: width 1.25s ease-out 1.25s, height 1.25s ease-out 1.25s;
}
.draw::before {
top: 0;
left: 0;
}
.draw::after {
bottom: 0;
right: 0;
}
.draw:hover {
color: #60daaa;
}
.draw:hover::before, .draw:hover::after {
width: 100%;
height: 100%;
}
.draw:hover::before {
border-top-color: #60daaa;
border-right-color: #60daaa;
transition: width 0.25s ease-out, height 0.25s ease-out 0.25s;
}
.draw:hover::after {
border-bottom-color: #60daaa;
border-left-color: #60daaa;
transition: border-color 0s ease-out 0.5s, width 0.25s ease-out 0.5s, height 0.25s ease-out 0.75s;
}
<section class="buttons">
<button class="draw">Draw</button>
</section>
I have a working pen ( https://codepen.io/anon/pen/vdgdxO ) that changes the border color of an element while hovering ( top right bottom left ) with some transition to smoothen it up.
I would like to be able to "reverse" the border color change after a few seconds. Basically, I'd like to change border color when the opposite one is changing color :
border-top change color
border-right change color
border-bottom change color & border-top goes back to its original color
border-left change color & border-right goes back to its original color
border-top change color & border-bottom goes back to its original color
border-right change color & border-left goes back to its original color
etc.
Right now I only have the color change worked out, but I don't know how to "reverse" it. I'd also like this transition to loop forever, but I'm clueless on where to start. Any suggestions?
I would use multiple linear-gradient and a complex animation (by animating size/position of each one) to obtain the final result. If you get the trick you can easily adjust the different values to obtain any animation you want.
.draw {
padding: 20px 50px;
outline:none;
border: none;
box-shadow: none;
background-image:
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa);
background-position: 0 0, 0 0, 0 100%, 0 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 0% 3px, 0% 3px, 3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
background-color:transparent;
background-repeat:no-repeat;
transition:0.2s linear;
}
.draw:hover {
background-position: 0 100%, 0 0, 0 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
animation: animate 1.4s linear infinite 0.2s;
}
#keyframes animate {
0% {
background-position: 0 100%, 0 0, 0 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
40% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 100%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
60% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 0% 3px, 100% 3px,3px 100%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
70% {
background-position: 0 100%, 100% 0, 0% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 100%, 0% 3px, 100% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
80% {
background-position: 0% 0%, 0% 0, 0% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 100%, 0% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
100% {
background-position: 0% 0%, 0 0, 0 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
}
<button class="draw">Draw</button>
How does it work?
The structure: We have 8 linear-gradient. 4 will simply create the initial border and won't move (they are placed at the bottom layer) and 4 will be used to draw the line that will create our animation above the initial border (they are placed at the top layer).
The order is important as within background properties we will have 8 values each one for each gradient. You will notice the 3px value that will simply specify the width or height of each gradient (similar to the border-width) and it won't change during the animation.
The animation: I will adjust position/size of each gradient to create the animation. it's divided into 2 parts: a small transition and a big animation. The transition is simply used to create the initial state of the animation that's why the duration used for the transition is the same as the delay of the animation.
The first step is to animate the top border from left to right. To do this the gradient should be positioned at (0,0) [top,left] with a size of 0% 3px [width height]. Then I simply change the size to 100% 3px and I will get the needed animation (the 3px as described before won't change).
Now to animate the second border we do the same. We need a gradient positioned at (100%,0) [top,right] with a size of 3px 0% [width height] that we animate to 3px 100%:
Now since we have two borders we need to animate the third one AND hide the first one. I won't detail the third border as it's similar to the above ones so let's see how to hide the top one. The first intuitive idea is to simply set its size back to 0% 3px but this will simply create the inverse animation and thus we will have a right to left animation which is bad. The trick here is to adjust the position of the gradient to make it (100%,0) [top,right] instead of (0,0) as both positions are equivalent when the gradient is 100% size (so we do this at the previous step when animating the second one). Now, we can put back the size to 0% 3px and we will have a left to right animation:
We continue the same logic until we get back to the initial state and by specifying infinite in the animation property we will have the needed effect.
So the main Idea is to have a gradient with the size equal to 0% that we animate to full size (100%) in a given direction then we change its position (this won't have any effect on full size) and then animate back its size to 0. We mix this with the 4 gradients we have.
UPDATE
To avoid the confusing with all these gradient here is an update where I used a pseudo element for the static border thus we keep only 4 gradients for the animation:
.draw {
position:relative;
padding: 20px 50px;
outline:none;
border: none;
box-shadow: none;
background-image:
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61);
background-position: 0 0, 0 0, 0 100%, 0 100%;
background-size: 3px 0%, 0% 3px, 0% 3px, 3px 0%;
background-color:transparent;
background-repeat:no-repeat;
transition:0.2s linear;
}
.draw:before {
content:"";
position:absolute;
z-index:-1;
top:0;
right:0;
left:0;
bottom:0;
border:3px solid #60daaa;
}
.draw:hover {
background-position: 0 100%, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%;
animation: animate 1.4s linear infinite 0.2s;
}
#keyframes animate {
0% {
background-position: 0 100%, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%;
}
40% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 100%;
}
60% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 100%;
background-size: 3px 0%, 0% 3px, 100% 3px,3px 100%
}
70% {
background-position: 0 100%, 100% 0, 0% 100%, 100% 100%;
background-size: 3px 100%, 0% 3px, 100% 3px,3px 0%;
}
80% {
background-position: 0% 0%, 0% 0, 0% 100%, 100% 100%;
background-size: 3px 100%, 0% 3px, 0% 3px,3px 0%;
}
100% {
background-position: 0% 0%, 0 0, 0 100%, 100% 100%;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%
}
}
<button class="draw">Draw</button>
When I use this snippet on Chrome, IE, and Firefox and it works fine! But on Safari it doesn't work.
This issue happens:
.circle-red {
border: 2px solid;
border-radius: 51%;
width: 40px;
height: 40px;
background: radial-gradient(ellipse at 80px 40px, rgba(255, 255, 255, 0.75) 10%, rgba(255,255,255,0.5) 32%, rgba(255,255,255,0) 70% ), linear-gradient(160deg, transparent 10%, red 30%);
background-size: 87.5% 55%, 100% 100%;
background-repeat: no-repeat;
}
<div class="circle-red"></div>
Try This adding a webkit prefix on your background-size property and on your background gradient value. Here is an example:
.circle-red {
border: 2px solid;
border-radius: 51%;
width: 40px;
height: 40px;
background: radial-gradient(ellipse at 80px 40px, rgba(255, 255, 255, 0.75) 10%, rgba(255,255,255,0.5) 32%, rgba(255,255,255,0) 70% ), linear-gradient(160deg, transparent 10%, red 30%);
background: -webkit-radial-gradient(ellipse at 80px 40px, rgba(255, 255, 255, 0.75) 10%, rgba(255,255,255,0.5) 32%, rgba(255,255,255,0) 70% ), linear-gradient(160deg, transparent 10%, red 30%);
background-size: 87.5% 55%, 100% 100%;
-webkit-background-size: 87.5% 55%, 100% 100%;
background-repeat: no-repeat;
}