I'm trying to make a strikethrough animation like the effect here:
The strike line appears from left to right and disappears from left to right.
#keyframes strike {
0% {
width: 0;
}
50% {
width: 100%;
}
100% {
width: 0;
}
}
.strike {
position: relative;
}
.strike:hover:after {
content: ' ';
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 1px;
background: black;
animation-name: strike;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: 1;
animation-fill-mode: fill;
animation-direction: normal;
}
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
Is there a way to achieve that only with CSS ?
You can use transforms and transform-origin in the keyframe animation to make strike-through apear from left to right and disapear from left to right.
The point is to scale the pseudo element on the X axis for 0 to 1 with a transform origin on the left then back to 0 with a transform origin on the right (similar to this hover effect see last example of the answer).
And here is an example with your markup :
#keyframes strike{
0% { transform-origin: 0% 50%;transform:scaleX(0); }
50% { transform-origin: 0% 50%;transform:scaleX(1); }
50.01% { transform-origin:100% 50%;transform:scaleX(1); }
100% { transform-origin:100% 50%;transform:scaleX(0); }
}
.strike {
position: relative;
}
.strike:hover:after {
content: ' ';
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 1px;
background: black;
animation: strike .75s ease-in-out forwards;
}
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
Here is a sample using transition, where it on hover toggle left/right position.
.strike {
position: relative;
}
.strike::after {
content: ' ';
position: absolute;
top: 50%;
left: 0;
right: 100%;
height: 1px;
background: black;
}
.strike:hover::after {
right: 0;
left: 100%;
transition: right .5s .0s, left .5s .5s;
}
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
Related
I'm trying to make an animation for drawing a square border on hover.
It's working fine but when drawing the left side of the border the bottom of the border is jittering
Here's a link to the codepen https://codepen.io/Taggagii/pen/GRxYpXY to see the code and the jittering that's happening.
My approach is to just animate the ::before element to render the top and right sides and the ::after element to render the bottom and left sides. To animate both of them I'm just modifying their width and height attributes so it doesn't really make sense to me that only the bottom is jittery and not all the sides.
Note: This issue is present on Chrome but not on Firefox
html {
background: #f58442;
}
.center {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.border-renderer {
--border-size: 1px;
--animation-duration: 4s;
--border-z-index: -1;
--border-color: black;
--second-border-final-extent: calc(100% + 2 * var(--border-size));
--first-border-final-extent: calc(100% + var(--border-size));
--size: 200px;
position: relative;
display: inline-block;
background: #ccba87;
padding: 10px;
font-size: 5em;
margin-left: 35vw;
margin-top: 40vh;
}
.border-renderer::before,
.border-renderer::after {
content: '';
background: var(--border-color);
position: absolute;
z-index: var(--border-z-index);
}
.border-renderer::before {
top: calc(-1 * var(--border-size));
left: 0;
}
.border-renderer::after {
top: var(--first-border-final-extent);
right: calc(-1 * var(--border-size));
transform: translateY(-100%);
}
.border-renderer:hover::before {
animation-name: draw-box-top-right;
animation-duration: calc(var(--animation-duration) / 2);
animation-timing-function: ease;
animation-fill-mode: forwards;
}
.border-renderer:hover::after {
animation-name: draw-box-bottom-left;
animation-duration: calc(var(--animation-duration) / 2);
animation-delay: calc(var(--animation-duration) / 2);
animation-timing-function: ease;
animation-fill-mode: forwards;
}
#keyframes draw-box-top-right {
0% {
width: 0%;
height: var(--border-size);
}
50% {
width: var(--first-border-final-extent);
height: var(--border-size);
}
100% {
width: var(--first-border-final-extent);
height: var(--first-border-final-extent);
}
}
#keyframes draw-box-bottom-left {
0% {
width: var(--border-size);
height: var(--border-size);
}
50% {
width: var(--second-border-final-extent);
height: var(--border-size);
}
100% {
width: var(--second-border-final-extent);
height: var(--second-border-final-extent);
}
}
<div class="holder">
<div class="border-renderer">
<div class="center">Mouse over me</div>
</div>
</div>
We are trying to animate a div as follows:
1- Stretch from 0 to 100% (from left to right)
2- Then shrink from 100% to 0 (also from left to right)
3- then repeat.
We have the following div:
div {
position: absolute;
height: 2px;
background: #c60000;
left: 0;
top: 0;
color: #789;
width: 0;
animation-duration: 5s;
animation-name: progress;
animation-iteration-count: infinite;
}
#keyframes progress {
50% {
// transform-origin: right top;
width: 100%;
}
}
<div></div>
But no matter what we do using transform-origin and floats, positioning etc, the second part shrinks from right to left. i.e. the left side is always the anchor, whereas we want the right side to be the anchor when shrinking is taking place.
Would appreciate any help.
div {
position: absolute;
height: 2px;
background: #c60000;
top: 0;
color: #789;
animation-duration: 5s;
animation-name: progress;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
#keyframes progress {
0% {
left: 0;
width: 0;
}
50% {
right: 0;
width: 100%;
}
100% {
right: 0;
width: 0;
}
}
<div></div>
I have a problem with CSS currently.
https://jsfiddle.net/k9cfdofv/1/
There you can see that the
stripe (parallelogram) comes from the bottom, but it goes a little bit to right before it goes in that state I want it.
So I want it come from the bottom and go to the top without this shift at the end.
CSS-Code:
.stripe {
width: 100px;
height: 100px;
margin-left: 100px;
background: red;
transform: skew(-10deg);
animation: ani 1s linear 1 forwards;
position: absolute;
bottom: 10px;
}
#keyframes ani {
0% {
height: 0px;
}
100% {
height: 700px;
}
}
It can be done by setting a transform-origin for element to be skewed to left bottom.
div {
width: 100px;
height: 100px;
margin-left: 100px;
background: red;
transform: skew(-10deg);
transform-origin: left bottom;
animation: ani 1s linear 10 forwards;
position: absolute;
bottom: 10px;
}
#keyframes ani {
0% {
height: 0px;
}
100% {
height: 700px;
}
}
<div>
</div>
Here's the CodePen.
The square changes to a circle as expected when it slides to the right, but when it returns back to the left, it stays a circle instead of changing to a square.
Also, I can only click the <a> once. If I try to click multiple times, it doesn't work.
Trying to do this with only CSS (if possible).
body {
margin-top: 30px;
background: gainsboro;
}
.container {
margin: auto;
width: 100%;
}
.path {
position: relative;
overflow: hidden;
width: 100%;
height: 80px;
x-background: white;
}
#keyframes ani {
0% {
left: 0;
}
50% {
left: 95%;
}
100% {
left: 0;
}
}
.shape:target {
border-radius: 50%;
transition: all .7s ease-in-out;
animation-name: ani;
animation-duration: 2s;
animation-direction: alternate;
animation-fill-mode: none;
}
.shape {
position: absolute;
left: 0;
background-color: slateblue;
width: 80px;
height: 80px;
display: block;
border-radius: none;
transition: border-radius .4s ease-out;
}
<div class="container">
<div class="path">
<span id="elem" class="shape"></span>
</div>
</div>
The closest you can get with just CSS is this, as far as I know:
body {
margin-top: 30px;
background: gainsboro;
}
.container {
margin: auto;
width: 100%;
}
.path {
position: relative;
overflow: hidden;
width: 100%;
height: 80px;
x-background: white;
}
#keyframes ani {
0% {
left: 0;
}
50% {
left: 95%;
}
100% {
left: 0;
}
}
.path a:focus .shape {
border-radius: 50%;
transition: all .7s ease-in-out;
animation-name: ani;
animation-duration: 2s;
animation-direction: alternate;
animation-fill-mode: none;
}
.shape {
position: absolute;
left: 0;
background-color: slateblue;
width: 80px;
height: 80px;
display: block;
border-radius: none;
transition: border-radius .4s ease-out;
}
<div class="container">
<div class="path">
<span id="elem" class="shape"></span>
</div>
</div>
The problem before was triggering the state with :target:. This is tough to debug with sites like Codepen or other embedded editors, since you can't see the hash change. Basically, clicking the link would append #elem to the URL, apply the :target styles to .shape, and stay like that until the hash changes.
This solution uses :focus, which gets you closer to your goal, but not all the way. To repeat the animation, you need to defocus/blur the circle, then click it again.
I'm usually all for CSS-only effects, but I'm pretty sure you'll need Javascript for this. Something as simple as applying a class on click, waiting 2 seconds, then removing the class would accomplish the same effect more reliably.
I have a pretty simple animation that has borders that I created animate in width, in height, and then the center fades in.
The issue I'm having is I can't figure out how to animate from the center, rather than left to right (for the top and bottom borders) and top to bottom (for the side borders).
Is there any simple way to get the animation to happen from the middle?
Example of the code for the top and bottom animation:
#keyframes tb {
0% {width: 0;}
100% {width: 800px}
}
JSFiddle of the code.
You need to animate the left and top, too. For the horizontal bars, set the property left to 400px (50%) on the first keyframe, and to 0px on the last keyframe. Same goes for the vertical bars. Here is your fixed example:
#import url(https://fonts.googleapis.com/css?family=Montserrat:700);
html{
background: black;
}
#holder{
width: 800px;
display: block;
position: relative;
}
#follower {
display: block;
text-align: center;
padding: 20px;
font-family: 'Montserrat', sans-serif;
font-size: 30px;
line-height: 70px;
color: #fff;
background: rgba(255,255,255,.1);
animation: main 2s ease-out;
-webkit-animation: main 2s ease-out;
}
#keyframes main {
0% {opacity: 0}
50% {opacity: 0}
100%{opacity: 1}
}
#-webkit-keyframes main {
0% {opacity: 0}
50% {opacity: 0}
100%{opacity: 1}
}
#t, #b {
width: 800px;
height: 2px;
background: #fff;
position: absolute;
display: block;
animation: tb .5s 1 ease-out;
-webkit-animation: tb .5s 1 ease-out;
}
#t {
top: 0;
left: 0;
}
#b{
bottom: 0;
left: 0;
}
#r, #l {
width: 2px;
height: 110px;
background: #fff;
position: absolute;
display: block;
animation: rl 1s 1 ease-out;
-webkit-animation: rl 1s 1 ease-out;
}
#r{
left: 0;
top: 0;
}
#l {
right: 0;
top: 0;
}
#keyframes tb {
0% {
width: 0;
left: 400px;
}
100% {
width: 800px
left: 0;
}
}
#keyframes rl {
0% {height: 0}
50% {
height: 0;
top: 55px;
}
100% {
height: 110px;
top: 0;
}
}
<div id="holder">
<div id="t"></div>
<div id="b"></div>
<div id="r"></div>
<div id="l"></div>
<div id="follower">
Super Long Text Goest Here!
</div>
</div>
You can play around with your timing, and make it start at right point in your animation... using an animation-delay.
E.g.
#keyframes makeFatter {
0% {width: 0;}
100% {width: 800px}
}
#makeMeFat {
animation-name: makeFatter;
animation-duration: 5s;
animation-delay: -2.5s; /* Makes it start at 50% of your animation, i.e. width: 400px */
/* blah blah... rest of the CSS code */
}