I've been trying for days to emulate a video editing effect using CSS3 with no luck. I have two background images (one on top of the other) and want to create an animation where I scale up or zoom the image on top while leaving the background image intact.
I have been able to successfully change the position of the top image while leaving the background intact, and I can also do an animation which scales both foreground and background images at the same time.
Here's some code to make this all a bit more clear:
My HTML:
<section id="about-photo" class = "light-bg img-bg" style = "background-image: url({% static "assets/images/art/cocuy-foreground.png" %}), url({% static "assets/images/art/cocuy-background.jpg" %});">
<div class="container inner">
<div class="row">
</div><!-- /.row -->
</div><!-- /.container -->
</section>
My CSS (only including webkit for sake of brevity)
#-webkit-keyframes hide {
from { background-position: 0px 0px, 0px 0px; }
to { background-position: 0px 300px, 0px 0px; }
}
#-webkit-keyframes zoom {
from {-webkit-transform: scale(1,1), scale(1,1) ;}
to {-webkit-transform: scale(2,2), scale(1,1) ;}
}
#about-photo {
background-repeat: no-repeat;
-webkit-animation-name: zoom;
-webkit-animation-duration: 4s;
-webkit-animation-delay: 1s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
}
When I apply the animation called "hide" things work fine, but when I use "zoom" nothing happens.
Any ideas/tips would be greatly appreciated!
Dennis
Not sure if you actually need to use keyframes for this. You can simply use transition and transform to achieve this. I made a jsFiddle showing how you can do that. Also be aware that you want to include other vendor prefixes so your code works in all browsers.
#about-photo {
position: relative;
}
.light-bg {
width: 1000px;
height: 1000px;
background: url('http://www.broomehovercraft.com.au/graphics/bht/popups/gallery-sunset-6.jpg');
background-repeat: no-repeat;
}
.smiley {
position: absolute;
top: 10%;
left: 20%;
width: 100px;
height: 100px;
z-index: 2;
background: url('http://www.wpclipart.com/smiley/assorted_smiley/assorted_3/smiley_a_bit_angry_T.png');
background-size: 100px 100px;
-webkit-transition: 1s ease-in-out;
-moz-transition: 1s ease-in-out;
-o-transition: 1s ease-in-out;
transition: 1s ease-in-out;
}
.smiley:hover {
-webkit-transform: scale(2);
-moz-transform: scale(2);
-o-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
}
<section id="about-photo" class="light-bg img-bg">
<div class="smiley"></div>
<!-- /.container -->
</section>
http://jsfiddle.net/augburto/44sbrooy/
The main thing to note is that on the element you wish to have a "zoom effect", you want to apply a transition so it knows that when a transform is applied to it, it will do it smoothly (if you don't have this, then it will do the action immediately.
Right now I have it so when you hover over the smiley, it will scale with a transform. However, you can easily change this to a class that you can apply. As long as your element has a transition, it will create that nice "zoom-in" effect. Then the actual scaling of the image can be applied to a separate class which you can apply whenever.
For more documentation on transitions, check out MDN.
If you really want to use keyframes, then update your question, but in my eyes it isn't necessary in this situation.
Related
I want to rotate a frame but not the image inside it. Here is a JSFiddle that does the rotation but the image still moves. How can I keep the image stationary but move the frame only.
https://jsfiddle.net/q6n2w4qm/2/
HTML:
<body>
<div class="center">
<div class="hexagon">
<div class="hexagon-in1">
<div class="hexagon-in2">
</div></div>
</div>
</div>
</body>
CSS:
.center{
width: 200px;
margin: auto;
margin-top: -50px;
}
.hexagon{
width: 200px;
height: 400px;
overflow: hidden;
visibility: hidden;
transform: rotate(120deg);
cursor: pointer;
-moz-transition: all 1s ease-in-out;
-webkit-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.hexagon-in1{
overflow: hidden;
width: 100%;
height: 100%;
transform: rotate(-60deg);
}
.hexagon-in2{
width: 100%;
height: 100%;
visibility: visible;
transform: rotate(-60deg);
background: url('http://lorempixel.com/g/250/350/city');
repeat: no-repeat;
position: relative;
}
.hexagon:hover{
-ms-transform: rotate(150deg); /* IE 9 */
-webkit-transform: rotate(150deg); /* Chrome, Safari, Opera */
transform: rotate(150deg);
}
1) PNG pseudo-mask overlay
I created a simple HTML/CSS solution, but is only possible with the following three criteria:
The background color behind the image is a solid color
There is enough margin on all sides of the image
You have Photoshop or some comparable image editing software
Working Example
body {
background-color:#222222;
}
.hex-hack {
position:relative;
top:0;
left:0;
}
.base-image {
position:relative;
top:0;
left:0;
z-index:1;
margin: 84px;
}
.hex-overlay {
position:absolute;
width:568px;
height:568px;
top:0px;
left:0px;
z-index:3;
-moz-transition: all 1s ease-in-out;
-webkit-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.hex-overlay:hover {
-ms-transform: rotate(30deg); /* IE 9 */
-webkit-transform: rotate(30deg); /* Chrome, Safari, Opera */
transform: rotate(30deg);
}
<body>
<div class="hex-hack">
<img class="base-image" src="https://lorempixel.com/output/technics-q-g-400-400-2.jpg" alt="" />
<img class="hex-overlay" src="https://i.imgur.com/zYa31Tw.png" alt="" />
</div>
</body>
Note that the margin of the top image is half of the difference between the widths of the bottom image and the top image to keep it centered.
How I Made the Hexagon Mask in Photoshop
I started with a 400 by 400 image on a 800 by 800 canvas and created a perfect circle around the image so that each corner pixel of the image touched the circle. I cropped the canvas down to the width of the circle (568px). The purpose of this is to guarantee that the image is completely covered as the hexagon mask rotates.
Next, I had to create a 350 by 400 hexagon with no fill, rotate it 30 degrees, and center it in the middle of the canvas. Then I selected the hexagon's pixels (ctrl + click the hexagon layer), inverted the selection (shift + ctrl + I), and filled a new layer with the #222222 background color. I hid every other layer and saved it as a png.
2) CSS clip-path and animate
Another possible solution for you to consider is to use CSS to animate an image's clipping path via the clip-path and animate properties. This might be an easier approach, however, the clip-path property is relatively new and doesn't have the greatest browser support - especially with IE, Edge, and Opera. Here are a couple resources to check out:
CSS Masking - Excellent article on the clip-path property (includes animation demo)
Clippy - Great tool for creating CSS clip-paths
3) SVG animation and clipPath
Finally, this is a very browser-friendly solution, but you'll need some software (like Illustrator) to create an SVG from an image. This is also something I have no actual experience with, but I'm positive it can be achieved with a little research, and some trial and error. Here are some resources to get you started.
SVG clipping/masking techniques
Animating SVGs with CSS
I have a bitmap with an applied animation style that spins it ad nausaum. I would like it to move to the left and resize about 50% when an event is triggered (hover in this case). I've been able to apply smoothly the movement towards the left, but i get no response with the transform: scale command. See jsfiddle here.
.wheel:hover {
margin-left: -228px;
transform: scale(0.5);
}
What I'm doing wrong?
it doesn't work because you have transform:rotate() on the image from the animation. and adding another transform on the same image, in the same time the animation is working, it's not possible
instead of transform:scale(0.5) you can use height:50%;width:auto . see snippet below or fiddle > jsFiddle
let me know if it helps
#keyframes spin {
from {transform:rotate(0deg);}
to {transform:rotate(360deg);}
}
.wheel {
position: fixed;
top: 30px;
left: 140px;
animation: spin 15s infinite linear;
transition: all 0.5s linear;
}
.wheel:hover {
margin-left: -228px;
width:auto;
height:50%;
}
<body>
<img src="https://pbs.twimg.com/profile_images/616542814319415296/McCTpH_E.jpg" class="wheel">
</body>
Once I start animating, on Chrome I get a ripple effect. My circle transform scales up. On Firefox, that exact same animation is ignored for some reason.
$("#animate").click(function() {
$("#square").toggleClass("animate");
$("#fab").toggleClass("ripple");
});
#keyframes ripple {
from {
transform: scale(0)
}
to {
transform: scale(20)
}
}
#square {
position: relative;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid red;
transition: background 0.1s linear 0.6s, transform 1s;
transform: rotate(0deg);
}
#fab {
position: absolute;
width: 56px;
height: 56px;
border-radius: 50%;
background: #4FB5AB;
top: 122px;
right: 0;
transform: scale(1);
transition: transform 1s;
}
.ripple {
animation: ripple 1s 0.5s;
transform: scale(20) !important;
/*Duration - delay */
transition: transform 0s 1s !important;
}
.animate {
transform: rotate(90deg) !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="square">
<div id="fab"></div>
</div>
<br />
<button id="animate">animate</button>
CodePen Demo
Before I start explaining the problem with your code, here is a word of caution - Do not use transitions and animations together. They generally end up causing problems like the one faced here.
When an animation is specified on an element, it will take complete control over the properties that are being animated unless there is a rule with !important setting. If !important setting is used then that rule takes precedence over the animation. (but unfortunately Chrome and Firefox seem to be handling this case differently).
As per W3C Spec:
CSS Animations affect computed property values. During the execution of an animation, the computed value for a property is controlled by the animation. This overrides the value specified in the normal styling system. Animations override all normal rules, but are overriden by !important rules.
emphasis is mine
In your code, there were two problems and they are as follows:
Within .ripple selector, you were specifying the transition-duration as 0s, which means, there is no transition at all and that the change of transform is an instant one. As explained in the W3C Spec, Firefox seems to be (correctly) giving the control to the rule with !important setting (that is, the transform and transition within .ripple selector) and so it transitions the state change immediately after the specified 1s delay+. Chrome lets animation take control and thus produces the effect you are looking for.
Firefox seems to animate the element quicker than Chrome does and so while a duration of 1s is enough for the animation in Chrome, FF needs it to be 2s to be slower and show the effect.
+ - You can further verify this by removing the !important settings on the rules. Once !important is removed, the animation would take control.
$("#animate").click(function() {
$("#square").toggleClass("animate");
$("#fab").toggleClass("ripple");
});
#keyframes ripple {
from {
transform: scale(0)
}
to {
transform: scale(20)
}
}
#square {
position: relative;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid red;
transition: background 0.1s linear 0.6s, transform 1s;
transform: rotate(0deg);
}
#fab {
position: absolute;
width: 56px;
height: 56px;
border-radius: 50%;
background: #4FB5AB;
top: 122px;
right: 0;
transform: scale(1);
transition: transform 1s;
}
#fab.ripple {
animation: ripple 2s 1s;
transform: scale(20);
/*Duration - delay */
transition: transform 1s 1s;
}
#square.animate {
transform: rotate(90deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="square">
<div id="fab"></div>
</div>
<br />
<button id="animate">animate</button>
Finally, please do not use !important unless it is mandatory. Instead just make the selector more specific. In the snippet, I have made it more specific by using the #id.class format.
I am trying to achieve an effect I saw recently, where background image zooms on hover. I pretty much did it with example here: https://jsfiddle.net/qyh6nbwt/ but it seems to be very shaky (you will understand what I mean by hovering over it), I'm on osx running latest chrome version, have not checked it in other browsers yet.
Is there a way to make it smoother, so it doesn't "shake" on zoom in?
HTML
<div id="example">
test
</div>
CSS
#example {
background-image: url(http://www.jeroenkemperman.nl/wp-content/uploads/2014/06/Johns_Inc_Pizza_Spaghetti_wikipediacommons.jpg);
background-position: center center;
width: 250px;
height: 250px;
transition:all 1000ms ease;
background-size: 100% auto;
}
#example:hover {
background-size: 160% auto;
}
just use transform, scale.
so just instead of setting the bg image to 160% use
transform:scale(1.5);
some information about the transform css property you can find here
to use the transform scale in your case you will need a wrapper with overflow hidden so just the inner div gets bigger and cut of by the outer div.
see updated fiddle.
greetings timmi
Used transform scale instead of a background-size change transition: https://jsfiddle.net/qyh6nbwt/
transform: scale(2, 2);
So I made this my mission to figure this out, turns out it wasn't quite as simple of a fix as I thought.
It's a little dirty, but you need to frame your div within a div like this:
<div class="example">
<div></div>
<p>test</p>
</div>
Then from here, you can target the zooms more accurately, like this:
div.example {
height: 250px;
width: 250px;
overflow: hidden;
position: relative;
}
div.example > div {
position: absolute;
height: 100%;
width: 100%;
-moz-transition: all 1.5s;
-webkit-transition: all 1.5s;
transition: all 1.5s;
-moz-transform: scale(1,1);
-webkit-transform: scale(1,1);
transform: scale(1,1);
background-image: url('http://www.jeroenkemperman.nl/wp-content/uploads/2014/06/Johns_Inc_Pizza_Spaghetti_wikipediacommons.jpg');
-moz-background-size: cover;
-webkit-background-size: cover;
background-size: cover;
z-index: -1;
}
div.example:hover > div {
-moz-transform: scale(2,2);
-webkit-transform: scale(2,2);
transform: scale(2,2);
}
You can adjust the zoom and speed using the scale and transition properties.
Here is a working fiddle to demonstrate. Hope this helps, I checked in Chrome/Safari/Firefox and it seems to work pretty well.
What the problem is
I have tested this scenario of perspective usage ( a w3C validated webpage with all necessary and optional CSS browser tags) in IE, Firefox, Chrome, and Opera and found different (all inaccurate) results. So far it appears that the web browsers have all implemented perspective with slightly different displays. This question is here to see if maybe I'm missing something and there is a cross browser solution available.
If no one has a solution, well then, we have an interesting situation. Before now, I've never seen a feature in CSS that acts noticeably and irreparably inaccurate between all browsers.
I hope I'm wrong, because if not, I have to create and maintain three separate style sheets via php or javascript browser checking, a method that is very clearly out of date and frowned upon in today's web design. We prefer to use Modernizr to check features rather than browsers now, but this situation would prove that solution inviable.
Example Situation:
In Chrome, I positioned an iPhone interface simulating the use of a particular home automation app on the phone to control the channel of the tv in the background (an actual video), where the tv and iphone are made to look like they are part of the image with perspective and transform.
However, when looking at this from Firefox, the elements are completely out of place, as you can see below.
Question:
Is there any cross browser solution that will allow me to produce this result without using separate style sheets for different browsers?
Live JS Fiddle:
http://jsfiddle.net/qZSYy/1/
Purpose:
I'm developing a website for a technology company, and one of the main services provided is home automation. With a remote, or an iPhone or iPad, you can control a home's lighting, music, tv, etc. Very cool. So, I've decided to develop a section of the home automation page that simulates this.
On Chrome, it looks like this right now:
On Firefox:
Notes:
The iphone screen is actually a separate element, that turns on when hovered over and remains lit up for 10 seconds. I'm designing an interface on the iphone that will control the room's different lights, the speakers, and the tv, which is actually a separate div also that can be controlled by the iPhone as well to change channels.
The background is an image that I've render through Blender and can render different versions for the lighting changes.
CSS:
.home-auto-interactive {
width: 1250px;
height: 700px;
background-color: gray;
background-image: url('http://www.testing.agcomputers.net/style/images/Room_1.jpg');
-webkit-background-size: 100% 100%;
-moz-background-size: 100% 100%;
background-size: 100% 100%;
overflow: hidden;
-webkit-perspective: 80;
margin-left: auto;
margin-right: auto;
}
.home-auto-wrap {
width: 100%;
background-color: #252525;
}
.tv-screen {
width: 8.12%;
height: 7.8%;
position: absolute;
-webkit-transition: -webkit-transform .5s;
-moz-transition: -moz-transform .5s;
-o-transition: -o-transform .5s;
-ms-transition: -ms-transform .5s;
transition: transform .5s;
-webkit-transform: rotateY(-2deg) rotateX(0deg) rotateZ(0deg) translateX(626.7%) translateY(490%);
-moz-transform: rotateY(-2deg) rotateX(0deg) rotateZ(0deg) translateX(626.7%) translateY(490%);
-o-transform: rotateY(-2deg) rotateX(0deg) rotateZ(0deg) translateX(626.7%) translateY(490%);
-ms-transform: rotateY(-2deg) rotateX(0deg) rotateZ(0deg) translateX(626.7%) translateY(490%);
transform: rotateY(-2deg) rotateX(0deg) rotateZ(0deg) translateX(626.7%) translateY(490%);
}
.iphone-screen {
width: 22.7%;
background-color: black;
background-image: url('http://www.testing.agcomputers.net/style/images/iphone_screen_test.jpg');
-webkit-background-size: 100% 100%;
-moz-background-size: 100% 100%;
background-size: 100% 100%;
height: 50.8%;
bottom: 12.7%;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity: 0;
position: absolute;
-webkit-transition-delay: 10s !important;
-moz-transition-delay: 10s !important;
-o-transition-delay: 10s !important;
-ms-transition-delay: 10s !important;
transition-delay: 10s !important;
-webkit-transition: opacity 0.5s;
-moz-transition: opacity 0.5s;
-o-transition: opacity 0.5s;
-ms-transition: opacity 0.5s;
transition: opacity 0.5s;
-webkit-transform: rotateY(-0.75deg) rotateX(1deg) rotateZ(-3deg) translateX(18.5%) translateY(0%);
-moz-transform: rotateY(-0.75deg) rotateX(1deg) rotateZ(-3deg) translateX(18.5%) translateY(0%);
-o-transform: rotateY(-0.75deg) rotateX(1deg) rotateZ(-3deg) translateX(18.5%) translateY(0%);
-ms-transform: rotateY(-0.75deg) rotateX(1deg) rotateZ(-3deg) translateX(18.5%) translateY(0%);
transform: rotateY(-0.75deg) rotateX(1deg) rotateZ(-3deg) translateX(18.5%) translateY(0%);
}
.iphone-screen:hover {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
filter: alpha(opacity=100);
opacity: 1;
-webkit-transition-delay: 0s !important;
-moz-transition-delay: 0s !important;
-o-transition-delay: 0s !important;
-ms-transition-delay: 0s !important;
transition-delay: 0s !important;
}
HTML:
<div class="home-auto-wrap">
<div class="home-auto-interactive"><!-- begin home auto interactive :: this has the purpose of displaying an interactive home automation area -->
<div class="tv-screen"><!-- begin tv screen -->
<iframe width="100%" height="100%" src="http://www.youtube.com/embed/9NFUgVa68hw?autoplay=1&rel=0&controls=0&showinfo=0&disablekb=1&iv_load_policy=3&modestbranding=1" frameborder="0" allowfullscreen></iframe>
</div><!-- end tv screen -->
<div class="iphone-screen"><!-- begin iphone screen -->
</div><!-- end iphone screen -->
</div><!-- end home auto interactive -->
</div>
You are missing the transform-style: preserve-3d; on the parent element. Also place the perspective property here, more on that later:
.home-auto-wrap {
width: 100%;
background-color: #252525;
transform-style: preserve-3d;
perspective: 80px;
}
This is part of the problem as Firefox requires it, Chrome does not - this explains why it works there. The next issue with Firefox is that overflow: hidden set on .home-auto-interactive causes all descendant elements to be flattened according to the spec: W3C Transform-style.
A workaround for this is to place the divs .tv-screen and .iphone-screen after .home-auto-interactive and position them atop. Now the 2 divs you are transforming will not be impeded.
Also opacity other than 1 will cause any descendant elements to flatten in 3D transforms, so be careful to keep that property for a div in the body with no transforming children (use z-index to position elements behind or in front of said div), or on the last node of a transforming element itself.
The background image property is not animatable, so you need to use an image tag to pull this off.
The issues you cite with TV could be due to:
The iframe, try applying the class to the iframe, though it should work as is.
The extra 0 transforms, get rid of these regardless.
The whole overflow thing, check the link above if you haven't done so.
Also, the filter property set other than none can lead to the same issue as the overflow and opacity, once again as per spec. It is not needed since IE 9, so unless you have some fallback reasons for doing so, removal is a good thing to consider. The opacity property has the same or better support than the 3D transforms:
Can I use opacity, check the 3d transforms too, I can't post more links yet. While you are at that page, check out the HTML5 video tag, it also has browser support as good as the 3d tranforms.
It looks like you need another prefix. Anywhere you call -webkit-perspective, you also need to call -moz-perspective. And the perspective needs a value: ems, px, etc..
https://developer.mozilla.org/en-US/docs/Web/CSS/perspective
http://css-tricks.com/almanac/properties/p/perspective/
This gave the elements perspective, but when you use position:absolute;, you need to also give a parent a defined position like position:relative;.
http://jsfiddle.net/NyXSa/7/
.home-auto-interactive {
width: 1250px;
height: 700px;
background-color: gray;
background-image: url('http://www.testing.agcomputers.net/style/images/Room_1.jpg');
-webkit-background-size: 100% 100%;
-moz-background-size: 100% 100%;
background-size: 100% 100%;
overflow: hidden;
-webkit-perspective: 80px;
-moz-perspective: 80px;
perspective: 80px;
margin-left: auto;
margin-right: auto;
position:relative;
}