I have a div with a width of 800 and a height of 300 pixels.
I also have an .svg image that's set as the background-image of this div, and using css3 animations I make this image scroll left to right, indefinitely (it's a landscape) and wrapping.
I would like to put a circle in the middle of this div, and make the inside of this circle "zoom" the background. I'd love to have this pure CSS.
I've tried some masking and clipping, but nothing seemed to do the trick.
Is this possible with the current CSS specifications? A JavaScript solution would also be acceptable.
Here's an image showing what I mean:
If you look closely, you can see a circle in the middle, which should zoom the clouds behind it, as if looking through a magnifying glass.
Trying to get it reusing the same animation, without extra elements:
CSS
.test {
position: absolute;
width: 600px;
height: 400px;
left: 0px;
background-image: url(http://placekitten.com/1000/400);
background-size: 1000px;
-webkit-animation: base linear 20s infinite;
background-position-x: 0px;
background-position-y: 50%;
}
.test:after {
content: "";
position: absolute;
left: 200px;
width: 200px;
top: 100px;
height: 200px;
border-radius: 50%;
background: inherit;
-webkit-transform: scale(1.1);
-webkit-animation: inherit;
-webkit-animation-delay: -4s;
}
#-webkit-keyframes base {
0% { background-position-x: 0px; }
100% { background-position-x: -1000px; }
}
The trick is to set the animation in sync delaying it; just calculate the equivalence in time of the x offset.
fiddle
throw your zoom div into the pic div and give it a background image of a larger version of the same image.
Related
The text that should be on the picture and follow it
<h1>Enter</h1>
the picture itself
I was told to try "position relative" but nothing worked does anyone have any suggestions on how to do this?
Animations
Syncing to animated images
Quickly skimming through the spec I didn't find anything to whether animated images (e.g. animated GIFs) should be in sync with CSS. Therefore I presume that animated images may or may not be in sync, depending on the implementation.
Not only is this (presumably) not defined, images' actual presentation may be deferred. We can specify sync, async or auto (default) for attribute decoding, but that is just a hint which the browser may not honour.
This means while we can try to sync CSS with animated images, this may not actually work due to technical reasons.
Here is my approach to getting the CSS animation to sync with the animated image. Note that while it may look synchronous for the first 1 or 2 cycles, it quickly gets out of sync due to me being off by a tiny bit:
#keyframes gif-anim {
0% {top: 40%}
50% {top: 30%}
}
.wrapper {position: relative}
.wrapper img {width: 100%}
.wrapper h1 {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
animation: .715s normal .14s gif-anim infinite backwards steps(1);
}
<div class="wrapper">
<img src=https://i.stack.imgur.com/I62VF.gif>
<h1>Enter</h1>
</div>
Syncing with CSS Animations
If we had the individual images that make up the animated image, we could synchronize it with CSS #keyframes.
It is significantly easier to synchronize if the frames are evenly spaced across the animation cycle. Example:
#keyframes img-anim {
0% {background-image: url(https://picsum.photos/id/1/300/200)}
50% {background-image: url(https://picsum.photos/id/2/300/200)}
}
#keyframes text-anim {
0% {left: 0%}
50% {left: 50%}
}
.wrapper {
position: relative;
width: 300px;
overflow: hidden;
}
.wrapper::before {
content: "";
width: 300px;
height: 200px;
display: block;
background-image: url(https://picsum.photos/id/1/300/200);
animation: img-anim 1s infinite steps(1);
}
.wrapper>h1 {
position: relative;
left: 0%;
display: inline-block;
animation: text-anim 1s infinite steps(1);
}
<div class="wrapper">
<h1>Enter</h1>
</div>
I have a reproduction of the issue I'm facing below:
.rect {
transform: rotateZ(45deg);
background-color: #ddd;
position: absolute;
width: 300px;
height: 200px;
animation: 3s linear 0s infinite normal none running widen;
}
#keyframes widen {
from { width: 300px; }
to { width: 500px; }
}
<div class="rect"></div>
Notice how as the rectangle gets wider, its position also changes. It is true that the element's programmatic position isn't changing, but visually on the screen it appears it is.
I am only looking to widen it without having it visually appear to move. That is, the right side of the rectangle should simply extrude out an additional 200 pixels. Is this possible?
Looking around, it seems like setting the transform-origin from center to top left accomplishes this effect, but unfortunately my rectangle's origin of rotation is around its center. Perhaps the solution is to temporarily set it in some way while the effect is occurring..
An easy way to do this is to wrap the grey rectangle div in another div that does the rotating. That way the width and rotation can be controlled independently.
If other transformations need to be applied as well, this approach gives you control over the order the transformations will be applied.
.rect {
transform: rotateZ(45deg);
}
.widen {
background-color: #ddd;
width: 300px;
height: 200px;
animation: 3s linear 0s infinite normal none running widen;
}
#keyframes widen {
from {
width: 300px;
}
to {
width: 500px;
}
}
<div class="rect">
<div class="widen" />
</div>
That squish effect is expected, but for this scenario I'd suggest not animating the size properties anyway since it's going to push your natural DOM flow around with if there's other elements. Instead try scale transform, see below.
.rect {
transform: rotate(45deg);
background-color: #ddd;
position: absolute;
width: 300px;
height: 200px;
transform-origin: center left;
animation: 3s linear widen infinite;
}
/*
#keyframes widen {
from { width: 300px; }
to { width: 500px; }
}
*/
#keyframes widen {
to { transform: rotate(45deg) scaleX(2);
}
<div class="rect"></div>
It looks like it is moving because of the angle. If you want it to grow proportionally, add height to the animation.
Example 1:
.rect {
transform: rotateZ(45deg);
background-color: #ddd;
position: relative;
width: 300px;
height: 200px;
animation: 3s linear 0s infinite normal none running widen;
}
#keyframes widen {
from { width: 300px; height: 200px; }
to { width: 500px; height: 400px; }
}
<div class="rect"></div>
If we remove the rotation, it won't look like it is moving.
Example 2:
.rect {
background-color: #ddd;
position: relative;
width: 300px;
height: 200px;
animation: 3s linear 0s infinite normal none running widen;
}
#keyframes widen {
from { width: 300px; }
to { width: 500px; }
}
<div class="rect"></div>
Ok, my goal is to animate the background image with it sliding up from the bottom when the page loads and once the animation is over set its position to fixed. As far as I can tell the code I've written should work perfectly (I'm pretty new though), but when the animation ends and the javascript adds the position property to the background image, it disappears completely and everything below it moves up to take its place. Can anybody tell me what's wrong with my code?
HTML:
<div style="background-image: url(/resources/css/img/Logo\ Cropped.jpg);" class="background__img--hero"></div>` (set inside the header)
CSS:
#keyframes slideUp {
from {
margin-top: 700px;
}
to {
margin-top: 0px;
}
}
.background__img--hero {
background-size: cover;
background-position: center;
height: 100vh;
animation: slideUp 2s ease-out;
}
Javascript:
document.querySelector('.background__img--hero').addEventListener('animationend', posFix);
function posFix() { document.querySelector('.background__img--hero').style.position = 'fixed'; };
At your .background__img--hero, just add these:
.background__img--hero {
background-size: cover;
background-position: center;
height: 100vh;
width: 100%;
animation: slideUp 2s 1 ease-out forwards;
}
or any width you want your image to have
To animate the position of a position:fixed element, don't animate margins, but animate the position itself (in this cas top), like
#keyframes slideUp {
from {
top: 700px;
}
to {
top: 0px;
}
}
I would like to make a background animation. Previously I used the following simple CSS solution:
#splash {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
left: 0;
border-top: 2em solid #232323;
border-bottom: 2em solid #232323;
background-image: url("../img/splash.jpg");
background-size: cover;
background-position: 0 100%;
animation: moveSplash 15s ease-in-out infinite alternate;
-moz-animation: moveSplash 15s ease-in-out infinite alternate;
-webkit-animation: moveSplash 15s ease-in-out infinite alternate;
/* Safari 4.0 - 8.0 */
transition: opacity .5s;
z-index: 1;
}
#keyframes moveSplash {
from {
background-position-y: 100%;
background-position-x: 0%;
}
to {
background-position-y: 0%;
background-position-x: 100%;
}
}
Which worked perfectly:
whenever the screen was wider than taller, the background picture started to move from the bottom to the top, and it had the same width as the window's
whenever the screen was taller than wider, the background picture started to move from the left to the right, and it had the same height as the window's
HOWEVER, there was one major problem with this method: the animation was very jumpy, that's why I started playing with transition and transform: translate(), but then I could not make the image perfectly fitting.
Is there any workaround out there to achieve a smooth background-image animation keeping it cover-sized?
ANOTHER SOLUTION COULD BE to set image's width and height to 100%, and object-fit to cover. After this I would need to get the computed new dimensions of the image by Javascript or jQuery, however, I have tried .width, .naturalWidth, .offsetWidth, .clientWidth, and they returns 0. When I try this:
var oImg = document.getElementById('splash');
window.getComputedStyle(oImg).transformOrigin.split(' ')[0].replace('px', '')
window.getComputedStyle(oImg).transformOrigin.split(' ')[1].replace('px', '')
I get the window's dimensions (since the object's width and height are set to 100%), not the resized image's new size. If I could get the new size of the image, I could make a calculation where I find the max X and Y values.
Any idea how could I make this animation work smoothly?
Instead of performing the animation on the background-image itself, which is slow, I would suggest animating the entire element.
From what I can see you're trying to animate the background diagonally? Not horizontally and not vertically?
#keyframes moveSplash {
from {
transform: translateY(100%);
transform: translateX(0%);
}
to {
transform: translateY(0%);
transform: translateX(100%);
}
}
If you can't make the image fit the div perfectly when using translate, then that is perhaps what your question really should've been about, because it's kind of "unconventional" to perform the transition on the background-image (because it's slow) and not the entire element (which makes better use of the available memory, and therefor, again – is faster).
I have a div with a background image on it. When it has simple transform scale animation, it starts to flicker in Google Chrome and Opera.
Here is a simple exmple:
http://codepen.io/anon/pen/bWpNYq
CSS:
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-color: #f00;
background-position: 50% 50%;
background-image: url(".....jpg");
background-size: cover;
}
Script:
TweenLite.set('div', {
backfaceVisibility: 'hidden',
perspective: 1000
});
TweenLite.fromTo('div', 10, {
scale: 1.1
}, {
scale: 1
});
When the image is a simple img element, the same scale animation works fine. The transition is smooth:
http://codepen.io/anon/pen/pPyvdp
The examples use GASP for animations. I need a solution which use GSAP to scale the div with better result.
Do you any idea how to make it smooth with background image?
Try this:
Add transition: all 1s linear; so it scale smoothly.
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-image: url("https://smartslider3.com/wp-content/uploads/2015/10/slide52.jpg");
background-size: cover;
transition: all 1s linear;
}
Hey maybe you can try out this css animation. For better browser support add
-webkit-animation
-moz-animation
-o-animation
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-image: url("https://smartslider3.com/wp-content/uploads/2015/10/slide52.jpg");
background-size: cover;
-webkit-animation: animate 5s forwards;
animation: animate 5s forwards;
}
#-webkit-keyframes animate {
0% { transform: scale(1); }
100% { transform: scale(1.1); }
}
#keyframes animate {
0% { transform: scale(1); }
100% { transform: scale(1.1); }
}
<div>
</div>
CSS3 allows you to add native transition to your transformations. Try to use code below:
document.body.addEventListener('click', function(){
var div = document.getElementById('img');
div.style.transform = 'scale(.5)';
})
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-image: url("https://smartslider3.com/wp-content/uploads/2015/10/slide52.jpg");
background-size: cover;
transition: transform 30s;
}
<div id="img"></div>
It uses css property "transition" and starts transition on body click.
Just use css, way better. If you open up your inspector you'll see that your tweenlite code is setting/ updating the style attribute of your div very fast with this piece of code: transform: translate3d(0px, 0px, 0px) scale(1.00212, 1.00212);.
This is JS calculating something and then telling CSS what to do (very basic explanation). CSS can do this on it's own. Why do you want to stick with your GSAP engine so badly?