I'm new to animation. I pick some code up that had a demo that worked in the 5 browsers I'm testing in. I'm on Windows 10 and have the latest versions of the 5 browsers I test in (Chrome, FF, edge IE, and Opera. The CSS follows.
.progress-bar {
margin-bottom: 1rem;
background-color: tomato;
border-radius: 1.25em;
width: 300px;
height: 16px;
display: inline-block;
}
.progress-value {
background-color: MEDIUMBLUE;
transition: 0.3s all linear;
border-radius: 1.25em;
height: 16px;
display: inline-block;
animation: progress 3s ease-in-out forwards;
-webkit-animation: progress 3s ease-in-out forwards;
}
.progress-value.green {
background-color: MEDIUMSEAGREEN;
animation: progress-3 3s ease-in-out forwards;
-webkit-animation: progress-3 3s ease-in-out forwards;
}
.progress-value.red {
background-color: TOMATO;
animation: progress-2 3s ease-in-out forwards;
-webkit-animation: progress-2 3s ease-in-out forwards;
}
/* animation */
#keyframes progress {
from {
width: 0;
}
to {
width: 55%;
}
}
#-webkit-keyframes progress {
from {
width: 0;
}
to {
width: 55%;
}
}
#keyframes progress-2 {
from {
width: 0;
}
to {
width: 70%;
}
}
#-webkit-keyframes progress-2 {
from {
width: 0;
}
to {
width: 70%;
}
}
#keyframes progress-3 {
from {
width: 0;
}
to {
width: 90%;
}
}
#-webkit-keyframes progress-3 {
from {
width: 0;
}
to {
width: 90%;
}
}
<DIV ID='dvLoading' STYLE='POSITION:relative;TOP:-300px;LEFT:30%;'>
<DIV class='progress-bar'>
<DIV class='progress-value' style='WIDTH:70%;'></DIV>
</DIV>
</DIV>
The bar looks like I hoped. But there is no animation in any of the 5 browsers.
Here's working and better code for you. Instead of creating animation for each progress value, change width of child and show indicator inside the child and animate it once (from width: 0% to width: 100% width). I created a simple animating progress bar with 4 color variants.
.progress {
width: 500px;
height: 30px;
border-radius: 15px;
overflow: hidden;
background: #eee;
position: relative;
}
.progress>.progress-value {
position: relative;
height: 100%;
left: 0;
top: 0;
}
.progress>.progress-value::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
animation: progress-value 3s ease-in-out forwards;
-webkit-animation: progress-value 3s ease-in-out forwards;
background: #666;
}
.progress>.progress-value.red::before {
background: #f44;
}
.progress>.progress-value.green::before {
background: #3f4;
}
.progress>.progress-value.blue::before {
background: #54f;
}
#keyframes progress-value {
from {
width: 0%;
}
to {
width: 100%;
}
}
#-webkit-keyframes progress-value {
from {
width: 0%;
}
to {
width: 100%;
}
}
<div class="progress">
<div class="progress-value" style="width: 65%"></div>
</div>
<div style="height: 15px"></div>
<div class="progress">
<div class="progress-value red" style="width: 95%"></div>
</div>
<div style="height: 15px"></div>
<div class="progress">
<div class="progress-value green" style="width: 41%"></div>
</div>
<div style="height: 15px"></div>
<div class="progress">
<div class="progress-value blue" style="width: 14%"></div>
</div>
What I did that works as I hoped is that I load the indicator as an HTML file into an object in the CGI process and position that object at the V/H center of the iframe. I put a 1 second lag in the JavaScript that's executed when the IFRAME content is loaded (ONLOAD) to turn the indicator off, to ensure that at least a little of the indicator is seen on a real fast load. Thanks all. ct
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>
I'm trying to load the progress bar up to a certain percentage. Whatever that percentage is, the progress bar will stop at that specific color animation specified in the keyframes.
How can i get it to work.
HTML
<div class="container">
<div class="progress-bar">
<span style="width:50%">
<span class="progress-value"></span>
</span>
</div>
<span><strong>CSS</strong></span>
<br/>
</div>
CSS
.container {
display: flex;
justify-content: center;
}
.progress-bar {
background-color: lightgray;
border-radius: 1.25em;
width: 300px;
height: 16px;
width: 50vw;
}
.progress-bar > span {
display: flex;
}
.progress-value {
background-color: #673ab7;
transition: 0.3s all linear;
border-radius: 1.25em;
height: 16px;
width: 50vw;
animation: progress-color 3s linear forwards;
-webkit-animation: progress-color 3s linear forwards;
}
/* animation */
#keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background: purple;
}
100% {
background: green;
width: 100%;
}
}
#-webkit-keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background:red;
}
100% {
background: green;
width: 100%;
}
}
Here's my codepen
https://codepen.io/mingsterism/pen/xJgePK
The problem is that where you have specified the animation is 100% completed under the #keyframes , there you must specify red as the color, which you have specified as the color you wish when the bar reaches 50%, while the rest of of the code is fine. Replace your piece of code with this one below and tell, is this what you want ?
#keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background: green;
}
100% {
background: red;
width: 100%;
}
}
#-webkit-keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background: green;
}
100% {
background: red;
width: 100%;
}
}
I have 2 images with transparent background and need to put one on top of each other with the same positioning:
1 spinning (underneath)
1 fixed (above)
I need to have the whole image composition to be centered and to have its size adjusted depending on the window size.
I used an ::after pseudo element for the fixed one but couldn’t get its position and size to follow the spinning one.
I suppose the background-size property should be involved but didn’t manage to use it properly.
Would appreciate any advice, even if it involves going with a totally different approach than the ::after pseudo class.
Many thanks.
body{
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container{
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
}
.engine-complete{
position: relative;
width: 100%;
height: auto;
margin: 0 auto;
}
.engine-complete::after{
content: "";
position: absolute;
width: 191px;
height: 192px;
top: 1px;
left: 0;
background-image: url(https://image.ibb.co/jOqNma/engine1_crpd.png);
}
.engine-rotating{
width: 50%;
height: auto;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function:linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform:rotate(360deg);
}
to {
transform:rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<div class="engine-complete">
<img src="https://image.ibb.co/nwOKXF/engine1.png" width=191 height=192 class="engine-rotating spin"/>
</div>
</div>
</div>
Something like this?
EDIT: Instead of setting the image as a background using the ::after pseudo-class, I added the fixed image into the html. I also eliminated one of your containers.
I centred the animated image using text-align:center and centred the fixed image using position: absolute
I set both images to 30% width relative their parent .engine-container
The fixed image has a higher z-index than the animated image so that it always appears over it. The images also change size accordingly, relative to window size.
body {
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container {
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container {
text-align: center;
position: relative;
}
.engine-rotating,
.engine-fixed {
width: 30%;
}
.engine-fixed {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
z-index: 5000;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<img src="https://image.ibb.co/nwOKXF/engine1.png" class="engine-rotating spin" />
<img src="https://image.ibb.co/jOqNma/engine1_crpd.png" class="engine-fixed" alt="">
</div>
</div>
UPDATE
Heres what I came up with:
A similar effect using ::after. I was able to achieve this by inserting the image url into the content: rule, rather than setting a background image.
body {
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container {
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
text-align: center;
position: relative;
}
.engine-rotating{
}
.engine-container::after{
content: url('https://image.ibb.co/jOqNma/engine1_crpd.png');
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
z-index: 5000;
}
.spin{
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
#keyframes spin{
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<img src="https://image.ibb.co/nwOKXF/engine1.png" class="engine-rotating spin" />
</div>
</div>
Set position for .engine-complete::after to relative
.engine-complete::after {position: relative}
body{
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container{
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
}
.engine-complete{
position: relative;
width: 100%;
height: auto;
margin: 0 auto;
}
.engine-complete::after{
content: "";
position: relative; /* this was changed */
width: 191px;
height: 192px;
top: 1px;
left: 0;
background-image: url(https://image.ibb.co/jOqNma/engine1_crpd.png);
}
.engine-rotating{
width: 50%;
height: auto;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function:linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform:rotate(360deg);
}
to {
transform:rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<div class="engine-complete">
<img src="https://image.ibb.co/nwOKXF/engine1.png" width=191 height=192 class="engine-rotating spin"/>
</div>
</div>
</div>
I can get everything work if I use solely transitions, or solely animations, but I can't seem to work out how to make things work with the mixture.
Basically I have one outer element which I want to fade in, then an inner element I want to slide in after the fade is complete.
My real example is complex so I created a fiddle which illustrates what I'm going after.
How can I get the bottom bar here to behave similarly to the top one? (obv differences of scaleX aside). The issue is that the bottom inner blue bar shows up as full straight away, instead of animating open like the top one.
https://jsfiddle.net/joshuaohana/sqsLc5sd/
For this example just hover over either colored box
<div class="outer">
<div class="inner">
</div>
</div>
<p></p>
<div class="outer2">
<div class="inner2">
</div>
</div>
.outer {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
}
.outer .inner {
height: 100px;
width: 0;
background-color: blue;
}
.outer:hover {
opacity: 1;
transition: opacity 1s;
}
.outer:hover .inner {
width: 100px;
transition: width 1s 0.5s;
}
.outer2 {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
}
.outer2 .inner2 {
height: 100px;
width: 0;
background-color: blue;
}
.outer2:hover {
opacity: 1;
transition: opacity 1s;
}
.outer2:hover .inner2 {
width: 100px;
animate: widen 1s 0.5s forwards;
}
#keyframes widen {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
You're using animate instead of animation. I would also use translateX instead of scaleX() but it probably doesn't matter. I would also set the initial state for the animation in the rule for .inner2, then simplify the animation and only specify the to or 100% step.
.outer {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
}
.outer .inner {
height: 100px;
width: 0;
background-color: blue;
}
.outer:hover {
opacity: 1;
transition: opacity 1s;
}
.outer:hover .inner {
width: 100px;
transition: width 1s 0.5s;
}
.outer2 {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
transition: opacity 1s;
overflow: hidden;
}
.inner2 {
height: 100px;
transform: translateX(-100%);
background-color: blue;
transform-origin: 0;
}
.outer2:hover {
opacity: 1;
}
.outer2:hover .inner2 {
width: 100px;
animation: widen 1s forwards;
animation-delay: .5s;
}
#keyframes widen {
to {
transform: translateX(0);
}
}
<div class="outer">
<div class="inner">
</div>
</div>
<p></p>
<div class="outer2">
<div class="inner2">
</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.