I want to create a circular progress bar around an image that should look like this :
I have tried making the circle fill but it just transforms into a spinner with the following code
.wrapper {
width: 152px;
height: 152px;
}
.loader {
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #21ac62;
width: 120px;
height: 120px;
animation: fill ease-in-out 3s;
transform: rotate(360deg);
}
.wrapper {
background: url('https://i.ibb.co/5T3p5sY/icon-3151974-1280.png') center no-repeat;
background-size:50%;
}
#keyframes fill{
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="jQuery-plugin-progressbar.css">
</head>
<body>
<div class="wrapper">
<div class="loader"></div>
</div>
</body>
</html>
I achieved the goal without changing the HTML layout using clip-path animation.
https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
.wrapper {
width: 152px;
height: 152px;
background-image: url('https://i.ibb.co/5T3p5sY/icon-3151974-1280.png');
background-position: center;
background-repeat: no-repeat;
background-size: 50%;
}
.loader {
border: 16px solid #21ac62;
border-radius: 50%;
width: 120px;
height: 120px;
animation: fill linear 3s;
}
#keyframes fill {
0% {
clip-path: polygon(50% 0%, 50% 50%, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%);
}
12.5% {
clip-path: polygon(50% 0%, 50% 50%, 100% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%);
}
37.5% {
clip-path: polygon(50% 0%, 50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 0%);
}
62.5% {
clip-path: polygon(50% 0%, 50% 50%, 0% 100%, 0% 100%, 0% 100%, 100% 100%, 100% 0%);
}
87.5% {
clip-path: polygon(50% 0%, 50% 50%, 0% 0%, 0% 0%, 0% 100%, 100% 100%, 100% 0%);
}
100% {
clip-path: polygon(50% 0%, 50% 50%, 50% 0%, 0% 0%, 0% 100%, 100% 100%, 100% 0%);
}
}
<div class="wrapper">
<div class="loader"></div>
</div>
Edit: This should be smoother:
.wrapper {
width: 152px;
height: 152px;
background-image: url('https://i.ibb.co/5T3p5sY/icon-3151974-1280.png');
background-position: center;
background-repeat: no-repeat;
background-size: 50%;
}
.loader {
border: 16px solid #21ac62;
border-radius: 50%;
width: 120px;
height: 120px;
animation: fill linear 3s;
}
#keyframes fill {
0% {
clip-path: polygon(50% -20.71%, 50% 50%, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%);
}
12.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 100% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%);
}
25% {
clip-path: polygon(50% -20.71%, 50% 50%, 120.71% 50%, 120.71% 50%, 120.71% 50%, 120.71% 50%, 100% 0%);
}
37.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 0%);
}
50% {
clip-path: polygon(50% -20.71%, 50% 50%, 50% 120.71%, 50% 120.71%, 50% 120.71%, 100% 100%, 100% 0%);
}
62.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 0% 100%, 0% 100%, 0% 100%, 100% 100%, 100% 0%);
}
75% {
clip-path: polygon(50% -20.71%, 50% 50%, -20.71% 50%, -20.71% 50%, 0% 100%, 100% 100%, 100% 0%);
}
87.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 0% 0%, 0% 0%, 0% 100%, 100% 100%, 100% 0%);
}
100% {
clip-path: polygon(50% -20.71%, 50% 50%, 50% -20.71%, 0% 0%, 0% 100%, 100% 100%, 100% 0%);
}
}
<div class="wrapper">
<div class="loader"></div>
</div>
For more Information and Full Explaination, Reach to https://dev.to/shantanu_jana/circular-progress-bar-using-html-and-css-1oda
body {
background:#d2eaf1;
}
.circle-wrap {
margin: 150px auto;
width: 150px;
height: 150px;
background: #fefcff;
border-radius: 50%;
border: 1px solid #cdcbd0;
}
.circle-wrap .circle .mask,
.circle-wrap .circle .fill {
width: 150px;
height: 150px;
position: absolute;
border-radius: 50%;
}
.circle-wrap .circle .mask {
clip: rect(0px, 150px, 150px, 75px);
}
.circle-wrap .inside-circle {
width: 122px;
height: 122px;
border-radius: 50%;
background: #d2eaf1;
line-height: 120px;
text-align: center;
margin-top: 14px;
margin-left: 14px;
color: #1e51dc;
position: absolute;
z-index: 100;
font-weight: 700;
font-size: 2em;
display:flex;
align-items:center;
justify-content:center;
}
/* color animation */
/* 3rd progress bar */
.mask .fill {
clip: rect(0px, 75px, 150px, 0px);
background-color: #227ded;
}
.mask.full,
.circle .fill {
animation: fill ease-in-out 3s;
transform: rotate(135deg);
}
#keyframes fill{
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(135deg);
}
}
<body>
<div class="circle-wrap">
<div class="circle">
<div class="mask full">
<div class="fill"></div>
</div>
<div class="mask half">
<div class="fill"></div>
</div>
<div class="inside-circle">
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="currentColor" class="bi bi-apple" viewBox="0 0 16 16">
<path d="M11.182.008C11.148-.03 9.923.023 8.857 1.18c-1.066 1.156-.902 2.482-.878 2.516.024.034 1.52.087 2.475-1.258.955-1.345.762-2.391.728-2.43zm3.314 11.733c-.048-.096-2.325-1.234-2.113-3.422.212-2.189 1.675-2.789 1.698-2.854.023-.065-.597-.79-1.254-1.157a3.692 3.692 0 0 0-1.563-.434c-.108-.003-.483-.095-1.254.116-.508.139-1.653.589-1.968.607-.316.018-1.256-.522-2.267-.665-.647-.125-1.333.131-1.824.328-.49.196-1.422.754-2.074 2.237-.652 1.482-.311 3.83-.067 4.56.244.729.625 1.924 1.273 2.796.576.984 1.34 1.667 1.659 1.899.319.232 1.219.386 1.843.067.502-.308 1.408-.485 1.766-.472.357.013 1.061.154 1.782.539.571.197 1.111.115 1.652-.105.541-.221 1.324-1.059 2.238-2.758.347-.79.505-1.217.473-1.282z"/>
<path d="M11.182.008C11.148-.03 9.923.023 8.857 1.18c-1.066 1.156-.902 2.482-.878 2.516.024.034 1.52.087 2.475-1.258.955-1.345.762-2.391.728-2.43zm3.314 11.733c-.048-.096-2.325-1.234-2.113-3.422.212-2.189 1.675-2.789 1.698-2.854.023-.065-.597-.79-1.254-1.157a3.692 3.692 0 0 0-1.563-.434c-.108-.003-.483-.095-1.254.116-.508.139-1.653.589-1.968.607-.316.018-1.256-.522-2.267-.665-.647-.125-1.333.131-1.824.328-.49.196-1.422.754-2.074 2.237-.652 1.482-.311 3.83-.067 4.56.244.729.625 1.924 1.273 2.796.576.984 1.34 1.667 1.659 1.899.319.232 1.219.386 1.843.067.502-.308 1.408-.485 1.766-.472.357.013 1.061.154 1.782.539.571.197 1.111.115 1.652-.105.541-.221 1.324-1.059 2.238-2.758.347-.79.505-1.217.473-1.282z"/>
</svg> </div>
</div>
</div>
</body>
Related
var timerSeconds = 10; // This will be set from a DB value
function StartCountDownTimer() {
var timerStart = new Date();
var css_seconds = `${timerSeconds}s`;
css_root = document.querySelector(':root');
cssVarBefore = '--timer-seconds BEFORE being set by JS: ' + getComputedStyle(css_root).getPropertyValue('--timer-seconds');
css_root.style.setProperty('--timer-seconds', css_seconds);
cssVarAfter = '--timer-seconds AFTER being set by JS: ' + getComputedStyle(css_root).getPropertyValue('--timer-seconds');
document.querySelector('.progress-border').classList.add('progress-border-animation');
timerStart.setSeconds(timerStart.getSeconds() + timerSeconds);
timerStart = timerStart.getTime();
// Update the count down every 1 second
var x = setInterval(function() {
var now = new Date().getTime();
var distance = timerStart - now;
var seconds = Math.round(distance / 1000, 1000);
document.getElementById("seconds-remaining").innerHTML = seconds;
if (seconds < 1) {
clearInterval(x);
document.getElementById("seconds-remaining").innerHTML = "";
document.querySelector('.progress-border').classList.remove('progress-border-animation');
alert("This demonstrates that the CSS variable is actually being changed it just isn't affecting the animation duration\n\n" + cssVarBefore + '\n' + cssVarAfter);
}
}, 1000);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
/* this is the variable I'm trying to set from JavaScript */
--timer-seconds: 5s;
--box-size: 150px;
--border-width: 8px;
}
body {
margin: 3em;
}
container {
display: flex;
flex-direction: columns;
gap: 1em;
}
.secs {
color: #365a2a;
font-size: 72px;
font-weight: bold;
text-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);
}
.count-down-timer{
position: relative;
display: flex;
flex-wrap: wrap;
align-content: center;
justify-content: center;
width: var(--box-size);
height: var(--box-size);
border: var(--border-width) solid #c05b20;
border-radius: calc(var(--border-width)*2);
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);
background: linear-gradient(#599646, #bfe2c3);
cursor: pointer;
}
.progress-border {
position: absolute;
top: calc(var(--border-width)*-1);
left: calc(var(--border-width)*-1);
width: var(--box-size);
height: var(--box-size);
border-radius: calc(var(--border-width)*2);
}
.progress-border-animation {
border: var(--border-width) solid #365a2a;
animation: fill forwards linear;
animation-duration: var(--timer-seconds); /* this line doesn't work */
/* animation-duration: 10s; */ /* this line works */
}
#keyframes fill {
0% {
clip-path: polygon(50% -20.71%, 50% 50%, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%);
}
12.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 100% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%);
}
25% {
clip-path: polygon(50% -20.71%, 50% 50%, 120.71% 50%, 120.71% 50%, 120.71% 50%, 120.71% 50%, 100% 0%);
}
37.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 0%);
}
50% {
clip-path: polygon(50% -20.71%, 50% 50%, 50% 120.71%, 50% 120.71%, 50% 120.71%, 100% 100%, 100% 0%);
}
62.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 0% 100%, 0% 100%, 0% 100%, 100% 100%, 100% 0%);
}
75% {
clip-path: polygon(50% -20.71%, 50% 50%, -20.71% 50%, -20.71% 50%, 0% 100%, 100% 100%, 100% 0%);
}
87.5% {
clip-path: polygon(50% -20.71%, 50% 50%, 0% 0%, 0% 0%, 0% 100%, 100% 100%, 100% 0%);
}
100% {
clip-path: polygon(50% -20.71%, 50% 50%, 50% -20.71%, 0% 0%, 0% 100%, 100% 100%, 100% 0%);
visibility: hidden;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Progress Bar</title>
</head>
<body>
<container>
<div>
<p><b>Click on the box to start the timer</b></p><br>
<div onclick="StartCountDownTimer()" class="count-down-timer">
<p class="secs" id="seconds-remaining"></p>
<div class="progress-border"></div>
</div>
</div>
<div>
<p><b>This is where I need help:</b></p>
<p>The CSS variable used for animation duration of the border is being set to 10 seconds to match the count down timer but the border is still using the original value of 5 seconds for its animation. <b>WHY?</b>
</p>
</div>
</container>
</body>
</html>
Trying to figure out how to dynamically change the seconds value for a CSS animation duration. I statically set the value in the class to 20s. From JavaScript I want to be able to change the 20s to some dynamic value, e.g. 60s. I'm using the value in JS to do other iterations so I need it to be an integer in JS. I think the issue I'm having is using different data types integer vs seconds but I'm not sure.
I've tried a few different approaches but none have worked:
changing CSS integer variable --sec: 20, from JS, then using calc(0s + var(--sec)) for the animation duration.
changing CSS seconds variable --sec: 20s, from JS by concatenating (60 + 's') and using var(--sec) for the animation duration.
modifying the document.getElementsByClassName('class')[0].style.animationDuration value from JS by concatenating (60 + 's')
Any suggestions would be much appreciated...
UPDATE regarding the latest posted code
It seems that the CSS variables are not defined in :root {}, instead are in * {}, therefore the setProperty() did not work.
If you move them to :root {} it should work properly:
:root {
--timer-seconds: 5s;
--box-size: 150px;
--border-width: 8px;
}
Update regarding custom duration input
You can also set ms as value of animation-duration in CSS.
More about animation-duration
Here is an over simplified example, it sets a value in ms to animation-duration by changing a variable --duration on the animated element.
There are many other ways, but this seems to be straight forward.
Hope this will help.
const figure = document.querySelector("figure");
const btns = document.querySelectorAll("button:not(#custom)");
const btnCustom = document.querySelector("button#custom");
const input = document.querySelector("input");
btnCustom.addEventListener("click",()=>{
const {value} = input
if (!value || isNaN(value) || value < 100 || value > 2000) {
input.value = ""
return}
const duration = `${Math.floor(value)}ms`
figure.style.setProperty("--duration", duration)
})
btns.forEach((btn) =>
btn.addEventListener("click", (e) =>
figure.style.setProperty("--duration", e.target.dataset.duration)
)
)
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
section {
display: flex;
flex-direction: column;
flex-wrap: wrap;
gap: 6px;
justify-content: center;
align-items: center;
width: 500px;
padding: 6px;
}
.control {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
gap: 3px;
}
button {
flex: 1;
padding: 3px;
}
input {
flex: 1;
padding: 3px;
}
.animation {
display: flex;
align-items: center;
width: 500px;
height: 150px;
background-color: #fdf5e6;
}
figure {
width: 100px;
height: 100px;
background-color: #1e90ff;
border-radius: 50%;
animation: move alternate infinite linear;
animation-duration: var(--duration, 1200ms);
}
#keyframes move {
from {
transform: translateX(0);
}
to {
transform: translateX(400px);
}
}
<section>
<div class="control">
<input
type="number"
min="100"
max="2000"
step="100"
placeholder="Enter num between 100 and 2000"
/>
<button id="custom">Set custom duration in ms</button>
</div>
<div class="control">
<button data-duration="1200ms">Defalut</button>
<button data-duration="700ms">Fast</button>
<button data-duration="300ms">Faster</button>
</div>
<div class="animation">
<figure></figure>
</div>
</section>
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I would want to add to my website a progress bar with this design:
The progress pie
How do I make a progress pie with an image inside it, and when it moves it display the image inside it with colors?
This is non-trivial but could be achieved by using two images, clip-path and a script, a greyscale image and a coloured image.
Position the greyscale image under the coloured one.
Use clip-path to only show a portion of the coloured image.
Adjust the clip-path values using a JavaScript loop OR using a css key-frames animation
Here's a simplified keyframes example:
.greyscale {
filter: grayscale(1);
}
.color {
overflow: hidden;
animation: clippy 2s infinite;
}
#keyframes clippy {
0% { clip-path: polygon(50% 50%, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0); }
12.5% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 0, 100% 0, 100% 0, 100% 0); }
25% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 100% 50%, 100% 50%, 100% 50%); }
37.5% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 100% 100%, 100% 100%, 100% 100%); }
50% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 50% 100%, 50% 100%, 50% 100%); }
62.5% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 0 100%, 0 100%, 0 100%); }
75% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 0 100%, 0 50%, 0 50%); }
87.5% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 0 100%, 0 0, 0 0); }
100% { clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 0 100%, 0 0, 50% 0); }
}
div {
border-radius: 50%;
height: 200px;
overflow: hidden;
position: relative;
width: 200px;
}
img {
height: 100%;
width: 100%;
object-fit: cover;
position: absolute;
}
<div>
<img class="greyscale" src="https://interactive-examples.mdn.mozilla.net/media/examples/balloon-small.jpg">
<img class="color" src="https://interactive-examples.mdn.mozilla.net/media/examples/balloon-small.jpg">
</div>
I have a CSS keyframe animation that outlines the border of the button. However, when I try to reverse the animation on mouse off, it removes the inset box shadow instead of the gradient border.
As you can see below, I've tried to set the border and background again in mouseLeaveAnimationClass. That does not solve the problem either. Is there an elegant solution to this problem?
var els = document.querySelectorAll('.get-started');
for (var i = 0; i < els.length; i++) {
els[i].addEventListener('mouseleave', function(e) {
e.target.classList.add('mouseleaveAnimationClass');
});
els[i].addEventListener('mouseenter', function(e) {
e.target.classList.remove('mouseleaveAnimationClass');
});
}
body {
background-color: black;
}
#button {
display: flex;
font-size: 2.5rem;
color: white;
align-items: center;
justify-content: center;
width: 250px;
height: 75px;
position: relative;
top: -30%;
left: calc(50% - 125px);
}
.get-started {
--borderWidth: 5px;
position: relative;
border-radius: var(--borderWidth);
background-color: #8551FF;
box-shadow: inset 0 0 0 5px white;
z-index: 1;
}
.get-started:after {
content: '';
position: absolute;
}
.get-started:hover:after {
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
animation: frame-enter 1s forwards ease-in-out reverse, gradient-animation 4s ease-in-out infinite;
}
.get-started.mouseleaveAnimationClass {
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
animation: frame-enter 1s forwards ease-in-out;
}
/* motion */
#keyframes gradient-animation {
0% {
background-position: 15% 0%;
}
50% {
background-position: 85% 100%;
}
100% {
background-position: 15% 0%;
}
}
#keyframes frame-enter {
0% {
clip-path: polygon(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%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
-webkit-clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
-webkit-clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
<div class="get-started" id="button">Get Started</div>
Runnable Example
In your original problem, the .get-started.mouseleaveAnimationClass { rule is applied to the element itself, and not to the ::after pseudo-element, and that's why the element is clipped. However, this won't solve your main problem - the reverse animation.
I've updated your code with a solution that is not super DRY, and you can probably improve it.
On the 1st hover only, the .ready class is added to the button. This enables the frame-leave animation, without running it. Whenever you :hover the element the frame-enter animation is applied, and as soon as you leave the element, the frame-leave is called again.
Notes:
frame-enter and frame-leave are the same animation. Using a different name allows us to replace them.
When you enter and then leave in the middle of the animation it will jump from the enter to the leave animation.
var els = document.querySelectorAll('.get-started');
for (var i = 0; i < els.length; i++) {
els[i].addEventListener('mouseenter', function(e) {
e.target.classList.add('ready');
}, { once: true });
}
#button {
display: flex;
font-size: 2.5rem;
color: white;
align-items: center;
justify-content: center;
width: 250px;
height: 75px;
position: relative;
top: -30%;
left: calc(50% - 125px);
}
.get-started {
--borderWidth: 5px;
position: relative;
border-radius: var(--borderWidth);
background-color: #8551FF;
box-shadow: inset 0 0 0 5px white;
z-index: 1;
}
.get-started::after {
content: '';
position: absolute;
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
.get-started.ready::after {
animation: frame-leave 1s forwards ease-in-out, gradient-animation 4s ease-in-out infinite;
}
.get-started.ready:hover::after {
animation: frame-enter 1s forwards ease-in-out reverse, gradient-animation 4s ease-in-out infinite;
}
/* motion */
#keyframes gradient-animation {
0% {
background-position: 15% 0%;
}
50% {
background-position: 85% 100%;
}
100% {
background-position: 15% 0%;
}
}
#keyframes frame-enter {
0% {
clip-path: polygon(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%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
#keyframes frame-leave {
0% {
clip-path: polygon(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%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
<div class="get-started" id="button">Get Started</div>
So I'm new to HTML & CSS and I'm currently doing some research.
I am using this Template and I'm trying to change the background image every 5 seconds.
I already found out, that the background image is defined in the CSS.
#bg:after {
-moz-transform: scale(1.125);
-webkit-transform: scale(1.125);
-ms-transform: scale(1.125);
transform: scale(1.125);
-moz-transition: -moz-transform 0.325s ease-in-out, -moz-filter 0.325s ease-in-out;
-webkit-transition: -webkit-transform 0.325s ease-in-out, -webkit-filter 0.325s ease-in-out;
-ms-transition: -ms-transform 0.325s ease-in-out, -ms-filter 0.325s ease-in-out;
transition: transform 0.325s ease-in-out, filter 0.325s ease-in-out;
background-image: url("../../images/bg1.jpg");
background-position: center;
background-size: cover;
background-repeat: no-repeat;
z-index: 1;
}
I would like to have multiple backgrounds that change every few seconds.
How is this possible?
Thanks.
Use this code to change the background color for every 5 seconds.
body {
-webkit-animation-name: bgcolor;
-webkit-animation-duration: 5s;
animation-name: bgcolor;
animation-duration: 5s;
animation-iteration-count: infinite;
}
#-webkit-keyframes bgcolor {
0% {
background: radial-gradient(at 50% -20%, #16113B, #16113B) fixed;
}
14.3% {
background: radial-gradient(at 50% -20%, #9b00a1, #16113B) fixed;
}
28.6% {
background: radial-gradient(at 50% -20%, #0062a1, #16113B) fixed;
}
42.9% {
background: radial-gradient(at 50% -20%, #00a18e, #16113B) fixed;
}
57% {
background: radial-gradient(at 50% -20%, #00a144, #16113B) fixed;
}
71% {
background: radial-gradient(at 50% -20%, #a18200, #16113B) fixed;
}
85.6% {
background: radial-gradient(at 50% -20%, #a10000, #16113B) fixed;
}
100% {
background: radial-gradient(at 50% -20%, #a10000bd, #16113B) fixed;
}
}
#keyframes bgcolor {
0% {
background: radial-gradient(at 50% -20%, #16113B, #16113B) fixed;
}
14.3% {
background: radial-gradient(at 50% -20%, #9b00a1, #16113B) fixed;
}
28.6% {
background: radial-gradient(at 50% -20%, #0062a1, #16113B) fixed;
}
42.9% {
background: radial-gradient(at 50% -20%, #00a18e, #16113B) fixed;
}
57% {
background: radial-gradient(at 50% -20%, #00a144, #16113B) fixed;
}
71% {
background: radial-gradient(at 50% -20%, #a18200, #16113B) fixed;
}
85.6% {
background: radial-gradient(at 50% -20%, #a10000, #16113B) fixed;
}
100% {
background: radial-gradient(at 50% -20%, #a10000bd, #16113B) fixed;
}
}
function run(interval, frames) {
var int = 1;
function func() {
document.body.id = "b"+int;
int++;
if(int === frames) { int = 1; }
}
var swap = window.setInterval(func, interval);
}
run(1000, 10); //milliseconds, frames
#b1 { background: hsl(0, 50%, 50%); }
#b2 { background: hsl(30, 50%, 50%); }
#b3 { background: hsl(60, 50%, 50%); }
#b4 { background: hsl(90, 50%, 50%); }
#b5 { background: hsl(120, 50%, 50%); }
#b6 { background: hsl(150, 50%, 50%); }
#b7 { background: hsl(180, 50%, 50%); }
#b8 { background: hsl(210, 50%, 50%); }
#b9 { background: hsl(240, 50%, 50%); }
#b10 { background: hsl(270, 50%, 50%); }
<script>
$("flexbox.center").scroll(changeClass);
function changeClass() {
if($("#coverphoto").hasClass('.coverphoto')){
$("#coverphoto").removeClass("coverphoto").addClass("newshape");
}
else{
$("#coverphoto").removeClass("newshape").addClass("coverphoto");
}
}
</script>
clip-path: polygon(0% 0%, 100% 0%, 100% 38.5%, 28.5% 65%, 0 65%);
transition: 0.5s ease-in-out;
-----
clip-path: polygon(0% 0%, 100% 0%, 100% 53%, 41% 53%, 0 53%);
transition: 0.5s ease-in-out;
Hello,
my goal is to smoothly change the shape of a clipped image on scroll.
My approach was to simply switch between the two css properties on scroll but this does not work. (By the way this works perfectly with :hover on the initial css property)
Any hints are highly appreciated and would mean a lot to me!
You have error in your code, the hasClass() function doesn't take a selector but only the class name :
function changeClass() {
if ($("#cover").hasClass('coverphoto')) {
$("#cover").removeClass("coverphoto").addClass("newshape");
} else {
$("#cover").removeClass("newshape").addClass("coverphoto");
}
}
.coverphoto {
clip-path: polygon(0% 0%, 100% 0%, 100% 38.5%, 28.5% 65%, 0 65%);
transition: 0.5s ease-in-out;
}
.newshape {
clip-path: polygon(0% 0%, 100% 0%, 100% 53%, 41% 53%, 0 53%);
transition: 0.5s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cover" class="coverphoto">
<img src="https://lorempixel.com/400/150/">
</div>
<button onClick="changeClass()">change</button>
By the way you can optimize your logic by simply using toggleClass() :
function changeClass() {
$("#cover").toggleClass("newshape");
}
.coverphoto {
clip-path: polygon(0% 0%, 100% 0%, 100% 38.5%, 28.5% 65%, 0 65%);
transition: 0.5s ease-in-out;
}
.newshape {
clip-path: polygon(0% 0%, 100% 0%, 100% 53%, 41% 53%, 0 53%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cover" class="coverphoto">
<img src="https://lorempixel.com/400/150/">
</div>
<button onClick="changeClass()">change</button>
Here is a trigger on scroll event:
$(document).scroll(function() {
if ($(window).scrollTop() <= 150) {
$("#cover").removeClass("newshape");
} else {
$("#cover").addClass("newshape");
}
});
body {
height: 150vh;
}
.coverphoto {
position: fixed;
clip-path: polygon(0% 0%, 100% 0%, 100% 38.5%, 28.5% 65%, 0 65%);
transition: 0.5s ease-in-out;
}
.newshape {
clip-path: polygon(0% 0%, 100% 0%, 100% 53%, 41% 53%, 0 53%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cover" class="coverphoto">
<img src="https://lorempixel.com/400/150/">
</div>