Is there a way to make the bar on the conic gradient rotate infinitely in a circle? This is how the gradient looks, I just want it to rotate around the center but everything I have tried hasn't worked.
If I understand what you want, just make sure you have (at least) 3 colours, and the final colour is the same as the first
P.S. I added rotation because wasn't sure what you meant by infinite rotation
div {
position:relative;
height:200px;
overflow:hidden;
aspect-ratio: 1 / 1;
border: solid black 1px;
clip-path: border-box;
}
div::before {
z-index:-1;
content:'';
position:absolute;
inset: -25%;
background-image: conic-gradient(
hsl(297.3, 84.6%, 20.4%),
hsl(192.6, 51.4%, 58.0%),
hsl(297.3, 84.6%, 20.4%)
);
animation: 3s linear infinite rot;
}
#keyframes rot {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<div>Hello World</div>
I have the picture below to which I would like to animate a diagonal split from the line cut through the logo from the top left to bottom right as shown below. The animation would split the picture on the X axis a few pixels apart.
https://i.ibb.co/fDzZ6Sc/Logo.png
I have made some progress so far, I used the same picture twice and laid them over each other and skewed on the X axis. However this split the picture apart from the top right to bottom left. I like it the other way around and can't figure it out.
I also could not figure out how to hover over the whole picture for the animation to execute for both of the sides.
body { background: gainsboro; }
.pageOption {
overflow: hidden;
position: relative;
margin: 0 auto;
width: 40em; height: 27em;
}
.option, .option img { width: 100%; height: 100%; }
.option {
overflow: hidden;
position: absolute;
/* arctan(27 / 40) = 34.01935deg
* need to skew by 90deg - 34.01935deg = 55.98065deg
*/
transform: skewX(-55.98deg);
}
.option:first-child {
left: -.25em;
transform-origin: 100% 0;
}
.option:last-child {
right: -.25em;
transform-origin: 0 100%;
}
.option img, .option:after {
transform: skewX(55.98deg);
transform-origin: inherit;
}
.option:hover {
left: -.8em;
transition: 1s;
}
<div class='pageOption'>
<a href='#' class='option'>
<img src='https://i.ibb.co/fDzZ6Sc/Logo.png'>
</a>
<a href='#' class='option'>
<img src='https://i.ibb.co/fDzZ6Sc/Logo.png'>
</a>
</div>
Essentially what I would like to happen is upon hovering on the whole picture, the two sides would split from the middle (cut from the line going from top left to bottom right), and when you move your mouse off, for the image to go back together.
You can consider clip-path and easily do this like below. The trick is to use two opposite polygon where the combination will make the full image.
.image {
width:340px;
height:230px;
background-image:url(https://i.ibb.co/fDzZ6Sc/Logo.png);
background-size:0;
position:relative;
}
.image:before,
.image:after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background-image:inherit;
background-size:cover;
transition:1s;
}
.image:before {
clip-path:polygon(0 0, 15% 0, 97% 100%, 0 100%);
}
.image:after {
clip-path:polygon(100% 0, 15% 0, 97% 100%);
}
.image:hover::before{
transform:translate(-20px,-10px);
}
.image:hover::after{
transform:translate(20px,10px);
}
body {
background:pink;
}
<div class="image">
</div>
If you don't want to cut the The adjust the clip-path
.image {
width:340px;
height:230px;
background-image:url(https://i.ibb.co/fDzZ6Sc/Logo.png);
background-size:0;
position:relative;
}
.image:before,
.image:after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background-image:inherit;
background-size:cover;
transition:1s;
}
.image:before {
clip-path:polygon(0 0, 32% 0 ,32% 19%, 97% 100%, 0 100%);
}
.image:after {
clip-path:polygon(100% 0,32% 0,32% 19%,97% 100%);
}
.image:hover::before{
transform:translate(-20px,-10px);
}
.image:hover::after{
transform:translate(20px,10px);
}
body {
background:pink;
}
<div class="image">
</div>
I have been able to animate a div with a background image as well as resize it along the path. However, I am trying to get this CSS-based animation to stop at a certain percentage of the progress.
The premise is to visually show a student her/his progress of completing a varying number of tasks (8 of 12 complete. 68%). That is not a problem with a straight progress bar, but I am looking to use an image of a mountain with a hiker moving along a path. I can get the hiker image from start to end with the following code, but I need it to stop based on the progress of the student.
I am trying to keep this as simple as I can, but do not have to use CSS.
.mtnBg
{
height:306px;
width:450px;
border:1px silver solid;
background-image: url(https://comps.canstockphoto.com/mountain-with-trail-and-sun-retro-style-eps-vector_csp43572145.jpg);
background-repeat: no-repeat;
background-size: 100%;
display:block;
opacity:.18;
z-index:-1;
}
.animSurround {
margin:0;
padding:0;
height:32px;
width:32px;
display:block;
position:relative;
left:140px;
bottom:50px;
border:1px none black;
animation: yAxis 2.8s 1 ease;
}
.anim {
background-image: url(https://www.tenstickers.co.uk/wall-stickers/img/preview/hiker-icon-sticker-8451.png);
background-repeat: no-repeat;
min-height:32px;
min-width:32px;
background-size: 100%;
animation-iteration-count:1;
animation: zoom-move 2.8s ease 1;
animation-fill-mode: forwards;
}
.anim::after {
/* Render dot, and animate along Y-axis */
min-height:96px;
min-width:96px;
}
#keyframes zoom-move {
0% {
transform: scale(3) translateX(calc(0px)) translateY(0px);
opacity: 0.50;
border-radius:32px;
background-color: rgba(256 , 256, 256, 1);
}
25% {
transform: scale(2.6) translateX(60px) translateY(-19px);
opacity: 1;
border-radius:32px;
background-color: rgba(256 , 256, 256, 1);
}
50% {
transform: scale(1.7) translateX(68px) translateY(-50px);
opacity: 1;
border-radius:32px;
background-color: rgba(256 , 256, 256, 1);
animation-play-state: paused;
}
93% {
background-color: rgba(256 , 256, 256, 1);
}
99% {
transform: scale(1.1) translateX(161px) translateY(-122px);
opacity: 1;
border-radius:32px;
background-color: rgba(76, 175, 80, 1);
}
100% {
transform: scale(1.1) translateX(161px) translateY(-122px);
opacity: 1;
border-radius:32px;
background-color: rgba(76, 175, 80, 1);
}
}
<div class="mtnBg"></div>
<div class="animSurround">
<div class="anim"></div>
</div>
Any help would be appreciated.
You can rely on the animation-play-state property. The is idea to convert the % value to the time when the animation should be paused. So you using JS/jQuery you run the animation and after this amount of time you set the property animation-play-state:
Here is an example with a simplied animation:
/* if we want the animation to run until 10%
we consider a duratioon of Xs and we should run until 0.1 * Xs
The duration will only affect the speed
so use a small value to simulate an instant change.
*/
var duration = 3;
function stop_animation(element, percent) {
var stop = (percent / 100) * duration; /* we get the value un second*/
stop *= 1000 /* we transform to milliseconds */
element.css('animation', 'anim ' + duration + 's linear');
setTimeout(function() {
element.css('animation-play-state', 'paused');
}, stop);
}
stop_animation($('.element').eq(0),50);
stop_animation($('.element').eq(1),20);
.container {
width: 200px;
height: 50px;
border: 1px solid;
border-left: 0;
background: linear-gradient(to right, #000 10%, transparent 11%) 0 0/20px 100%;
}
.element {
height: 100%;
width: 20px;
margin-left: 0;
background: red;
}
#keyframes anim {
from {
margin-left: 0;
}
to {
margin-left: calc(100% - 20px);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="element"></div>
</div>
<div class="container">
<div class="element"></div>
</div>
I found some CSS that moves a needle like a VU meter. This mimics what I want to do. However it does a full animation from start to finish. Whereas I would like to make the change happen through a series of clicks. I'm trying to figure out how to do that and I am unsuccessful. I would like to know how I can make the needle move in the same way only through clicks
CSS
.gauge {
position:relative;
width:120px;
height:120px;
margin:10px;
display:inline-block;
}
.needle-assembly {
position:absolute;
top: 0%;
left:46%;
height:100%;
width:10%;
-webkit-transform: rotate(-45deg);
}
.needle-holder {
position:relative;
top:0;
left:0;
height:60%;
width:100%;
}
.needle {
position:absolute;
background-color:#A00;
height:100%;
width:20%;
left:40%;
}
#-webkit-keyframes moveNeedle
{
0% {-webkit-transform: rotate(-45deg);}
60% {-webkit-transform: rotate(55deg);}
65% {-webkit-transform: rotate(50deg);}
100% {-webkit-transform: rotate(65deg);}
}
#gauge {
-webkit-transform-origin:50% 50%;
-webkit-animation: moveNeedle 5s;
-webkit-animation-fill-mode: forwards;
}
HTML
<div class="gauge" style="height:140px; width:140px;">
<div class="needle-assembly" id="gauge">
<div class="needle-holder">
<div class="needle"></div>
</div>
</div>
</div>
jQuery
$('#gauge').click(function(){
$('#gauge').css({transform: 'rotate(45deg)'})
});
fiddle
It doesn't move when you click it because you are setting it to a static value.
You need to change the value somehow.
var deg=45;
$('#gauge').click(function(){
var t = 'rotate(' + deg +'deg)';
$('#gauge').css({transform: t})
deg = deg+5;
});
http://jsfiddle.net/4xc3wnux/6/
I am attempting to build a Phonegap app that will allow the user to change the size of a two column layout by moving the middle divider.
I was able to get this working, but there is a huge UX problem: it's laggy. It's not terrible, but on the latest iPad it's even noticeable, which has me worrying.
Here's my JS that does the resizing:
$("div").on("touchmove", "#columnResizeIcon", function(e) {
e.preventDefault();
var left = e.originalEvent.touches[0].pageX;
var right = $("#columnContainer").width() - left;
$("#leftColumn").css({
"width":left - 1 + "px",
"right":"auto",
});
$("#rightColumn").css({
"width":right - 1 + "px",
"left":"auto",
});
$("#columnResize").css({
"-webkit-transform":"translate3d(" + left + "px" + ", 0, 0)",
"left":"auto",
});
$("#columnResizeIcon").css({
"-webkit-transform":"translate3d(" + left + "px" + ", 0, 0)",
"left":"auto",
});
});
You'll notice that I take advantage of translate3d() to change the "left" value of the elements, as that is hardware accelerated. I believe the lag is being produced from changing the widths of the left and right column, which is what I need to be hardware accelerated.
A possible solution that I thought might work would be to use -webkit-transform:translate3d(50%, 0, 0) to push the right column over half the page, and then just changing that value, hoping that it would only stretch until it reached the parent. It continues, however, and goes 50% of the page, not 50% of the parent.
My HTML markup looks like this:
<div id="columnContainer">
<div id="columnResize"></div>
<div id="columnResizeIcon"></div>
<div id="leftColumn">
<div class="header">Left Header</div>
<div class="content"></div>
</div>
<div id="rightColumn">
<div class="header">Right Header</div>
<div class="content"></div>
</div>
</div>
And my CSS:
body{
background-color:#000;
}
#columnContainer{
position: absolute;
bottom:0;
top:0;
right:0;
left:0;
background-color:#000;
}
#leftColumn{
position: absolute;
top:0;
left:0;
right:50%;
bottom:0;
-webkit-overflow-scrolling: touch;
z-index: 1;
margin-right: 1px;
}
#rightColumn{
position: absolute;
top:0;
left:50%;
right:0;
bottom:0;
-webkit-overflow-scrolling: touch;
z-index: 1;
margin-left: 1px;
}
.header{
position: absolute;
left:0;
right:0;
height:33px;
z-index: 5;
background: -webkit-linear-gradient(top, #f4f5f7 0%,#a7abb7 100%);
box-shadow: inset 0 1px 0 #fff, inset 0 -1px 0 #7A8090, 3px 0 2px rgba(0,0,0,.3);
border-top-left-radius: 5px;
border-top-right-radius: 5px;
font-size: 17px;
font-family: Helvetica;
font-weight: bold;
letter-spacing: .2px;
text-align: center;
padding-top:9px;
color:#71787F;
text-shadow: 0 1px 0 #E3E5E9;
}
.content{
position: absolute;
left:0;
right: 0;
top:42px;
bottom: 0;
}
#leftColumn .content{
background-color:#F5F5F5;
}
#rightColumn .content{
background-color:#fff;
}
#columnResize{
position: absolute;
width:2px;
top:0;
bottom: 0;
left:50%;
margin-left:-1px;
background-color:#000;
z-index: 2;
}
#columnResizeIcon{
position: absolute;
z-index: 3;
width:10px;
height:30px;
top:50%;
bottom:50%;
margin-top:-15px;
left:50%;
margin-left:-7px;
border-left:2px solid #000;
border-right:2px solid #000;
}
I finally figured out a solution that works a lot better than what I had. Basically, I animate the container, and I hide the content when I'm resizing. Then, when the resizing is done, I show the content again. I used an animations to make it look pretty when hiding/showing. The code will explain it better than I will:
The almighty fiddle
1 http://jsfiddle.net/charlescarver/hnQHH/134/
My explanation
When the slider is tapped, it pushes all the text elements off the page with a translate3d() transform, then hides the div. This is because the lag returns if I try to update the width while the elements are shown. So, once the divs are hidden, I then just move the columns left or right with the translate3d() transform once again. I can do this without having the width of each element stop short because I set the left or right values to a value that can never be reached so it's extended far enough beyond the page. That way, I can simply shift it without worrying that it will cut off prematurely.
Weirdness
There are parts of this that are probably redundant, but I'll clean those up soon. You'll also probably notice some weird things going on, such as (1) cornerLeft, (2) dummy, (3) shadow, and in the JS, (4) minimum:
When I resize the page, the dummy nav bar extends the entire width of the left and right columns, which means it goes 1000% of the width. That means that I can't set a border-radius on the nav for the left and right sides of each column, as it would be so far off the screen that it wouldn't be visible. So, I made a simple corner to mask each side of the window, making it look pretty.
I hide .contentLeft and .contentRight when I resize as it causes lag when it's shown. I don't want to get rid of the nav bar though, so I make a dummy one that is always there on the page, and is simply revealed when the resize is about to happen. I think this reduces the lag as I don't have to add the element in, since it's always there.
One problem with that, however, is that when the normal nav overlays the dummy nav, the box-shadow's overlap, causing it to become darker for 200ms. I don't like this. So, I put in a shadow that is always on top of the nav, regardless of what nav is showing.
I can now easily set a bound that the draggable columns can reach before stopping. Convenient, right?
Code
HTML:
<div id="container">
<div class="cornerLeft"></div>
<div class="cornerRight"></div>
<div class="shadow"></div>
<div class="left">
<div class="contentLeft">
<div class="header"></div>
<div class="headerbehind"></div>
<div class="text textLeft">Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus.</div>
</div>
<div class="dummy"></div>
<div class="dummybg"></div>
</div>
<div class="divider"></div>
<div class="right">
<div class="contentRight">
<div class="header"></div>
<div class="headerbehind"></div>
<div class="text textRight">Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus.</div>
</div>
<div class="dummy"></div>
<div class="dummybg"></div>
</div>
</div>
CSS:
* {
-webkit-text-size-adjust:none;
}
#container {
position:fixed;
left:0;
right:0;
bottom:0;
top:0;
background-color:#000;
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
}
.left {
-webkit-transform:translate3d(0, 0, 0);
position:absolute;
left:-3000px;
right:50%;
top:0;
bottom:0;
border-right:1px solid #000;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.right {
-webkit-transform:translate3d(0, 0, 0);
position:absolute;
left:50%;
right:-3000px;
top:0;
bottom:0;
border-left:1px solid #000;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.divider {
width:24px;
height:40px;
border-left:2px solid #000;
border-right:2px solid #000;
position:absolute;
left:50%;
z-index:3;
margin-left:-14px;
margin-top:-20px;
top:50%;
-webkit-transform:translate3d(0, 0, 0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
-webkit-touch-callout: none;
-webkit-user-select: none;
}
.contentLeft {
position:absolute;
right:0;
bottom:0;
top:0;
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.contentRight {
position:absolute;
left:0;
bottom:0;
top:0;
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.cornerLeft:after {
content:"";
height:5px;
position:absolute;
left:0;
width:5px;
background: -webkit-linear-gradient(top, #F0F2F4 0%, #EAEBEE 100%);
z-index:700;
border-top-left-radius:5px;
box-shadow:inset 0 1px 0 #fff;
}
.cornerLeft {
position:absolute;
z-index:700;
left:0;
width:5px;
height:5px;
background-color:#000;
}
.cornerRight:after {
content:"";
height:5px;
position:absolute;
right:0;
width:5px;
background: -webkit-linear-gradient(top, #F0F2F4 0%, #EAEBEE 100%);
z-index:700;
border-top-right-radius:5px;
box-shadow:inset 0 1px 0 #fff;
}
.cornerRight {
position:absolute;
z-index:700;
right:0;
width:5px;
height:5px;
background-color:#000;
}
.header, .dummy {
position: absolute;
left:0;
right:0;
height:35px;
background: -webkit-linear-gradient(top, #f4f5f7 0%, #a7abb7 100%);
border-top-left-radius: 5px;
border-top-right-radius: 5px;
font-size: 17px;
font-family: Helvetica;
font-weight: bold;
letter-spacing: .2px;
text-align: center;
padding-top:9px;
color:#71787F;
text-shadow: 0 1px 0 #E3E5E9;
word-break: break-all;
box-shadow:inset 0 1px 0 #fff, inset 0 -1px 0 #7A8090;
}
.shadow {
height:44px;
position:absolute;
left:0;
right:0;
box-shadow:0 1px 2px rgba(0, 0, 0, .2);
z-index:600;
}
.header {
z-index:500;
}
.dummy {
z-index:100;
}
.headerbehind {
position:absolute;
background-color:#000;
left:0;
right:0;
height:44px;
z-index:499;
}
.text, .dummybg {
margin-top:44px;
background-color:#fff;
position:absolute;
top:0;
right:0;
left:0;
bottom:0;
}
.text {
z-index:2;
padding:20px 40px;
-webkit-animation-duration:200ms;
-webkit-animation-timing-function:ease;
}
.contentLeft, .contentRight {
z-index:300;
}
.leftOut {
-webkit-transform:translate3d(-100%, 0, 0);
-webkit-animation-name:leftOut;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.leftIn {
-webkit-transform:translate3d(0, 0, 0);
-webkit-animation-name:leftIn;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
#-webkit-keyframes leftOut {
0% {
-webkit-transform:translate3d(0, 0, 0);
}
100% {
-webkit-transform:translate3d(-100%, 0, 0);
}
}
#-webkit-keyframes leftIn {
0% {
-webkit-transform:translate3d(-100%, 0, 0);
}
100% {
-webkit-transform:translate3d(0, 0, 0);
}
}
.rightOut {
-webkit-transform:translate3d(100%, 0, 0);
-webkit-animation-name:rightOut;
}
.rightIn {
-webkit-transform:translate3d(0, 0, 0);
-webkit-animation-name:rightIn;
}
#-webkit-keyframes rightOut {
0% {
-webkit-transform:translate3d(0, 0, 0);
}
100% {
-webkit-transform:translate3d(100%, 0, 0);
}
}
#-webkit-keyframes rightIn {
0% {
-webkit-transform:translate3d(100%, 0, 0);
}
100% {
-webkit-transform:translate3d(0, 0, 0);
}
}
JS:
minimum = 100;
$(".contentLeft").css("width", ($("#container").width() / 2) - 1);
$(".contentRight").css("width", ($("#container").width() / 2) - 1);
$("div").on("touchstart", ".divider", function (e) {
$(".textLeft").removeClass("leftIn");
$(".textLeft").addClass("leftOut");
$(".textRight").removeClass("rightIn");
$(".textRight").addClass("rightOut");
setTimeout(function () {
$(".contentLeft, .contentRight").hide();
}, 200);
});
$("div").on("touchmove", ".divider", function (e) {
e.preventDefault();
if ($(".contentLeft").css("display", "none")) {
var page = $("#container").width();
var left = e.originalEvent.touches[0].pageX;
var right = page - left;
updateWidth(page, left, right);
}
});
//$(".contentLeft, .contentRight").hide();
$("div").on("touchend", ".divider", function (e) {
setTimeout(function () {
$(".textLeft").removeClass("leftOut");
$(".textLeft").addClass("leftIn");
$(".textRight").removeClass("rightOut");
$(".textRight").addClass("rightIn");
$(".contentLeft, .contentRight").show();
}, 200);
});
$(window).on('orientationchange', function (e) {
var page = $("#container").width();
var leftWidth = $(".contentLeft").width();
var rightWidth = $(".contentRight").width();
var previousWidth = (leftWidth + rightWidth);
if (leftWidth + rightWidth + 2 < page) {
var left = (page / 2) - (previousWidth / 2) + leftWidth;
} else if (leftWidth + rightWidth + 2 > page) {
var left = leftWidth - ((previousWidth / 2) - (page / 2));
}
var right = page - left;
updateWidth(page, left, right);
});
function updateWidth(page, left, right) {
if (left < minimum) {
var finalLeft = minimum;
var finalRight = (-1 * (page - minimum));
var finalRightWidth = (page - minimum);
} else if (right < minimum) {
var finalLeft = (page - minimum);
var finalRight = (-1 * minimum);
var finalRightWidth = minimum;
} else {
var finalLeft = (left);
var finalRight = (0 - right);
var finalRightWidth = (right);
}
$(".divider").css({
"-webkit-transform": "translate3d(" + finalLeft + "px, 0, 0)",
"left": "auto",
});
$(".left").css({
"-webkit-transform": "translate3d(" + finalLeft + "px, 0, 0)",
"right": "100%",
});
$(".right").css({
"-webkit-transform": "translate3d(" + finalRight + "px, 0, 0)",
"left": "100%",
});
$(".contentLeft").css("width", finalLeft);
$(".contentRight").css("width", finalRightWidth);
}
1 Yes, it took me 134 tries.
I had some success by pushing the two elements into question in the hardware-accelerated stack:
#leftColumn,
#rightColumn {
-webkit-transform: translate3d(0,0,0);
}
Seems to be resizing much more smoothly. It's not that changing width itself is optimized, rather the elements themselves are re-rendered much more quickly.
I set up a plunk here: http://plnkr.co/edit/5RMtCl1Sql8f3CmQLHFz