CSS3 transform on click using pure CSS - css

I'm trying to get an image (a plus symbol) to rotate 45 degrees to create a cross symbol. I have so far managed to achieve this using the code below but its working on hover, I wanted to have it rotate on click.
Is there a simple way of doing so using CSS?
My code is:
CSS
img {
display: block;
margin: 20px;
}
.crossRotate {
-webkit-transition-duration: 1s;
-moz-transition-duration: 1s;
-o-transition-duration: 1s;
transition-duration: 1s;
-webkit-transition-property: -webkit-transform;
-moz-transition-property: -moz-transform;
-o-transition-property: -o-transform;
transition-property: transform;
}
.crossRotate:hover {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
HTML
<body>
<img class="crossRotate" src="images/cross.png" alt="Cross Menu button" />
</body>
Here is the jsfiddle demo.

If you want a css only solution you can use active
.crossRotate:active {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
}
But the transformation will not persist when the activity moves. For that you need javascript (jquery click and css is the cleanest IMO).
$( ".crossRotate" ).click(function() {
if ( $( this ).css( "transform" ) == 'none' ){
$(this).css("transform","rotate(45deg)");
} else {
$(this).css("transform","" );
}
});
Fiddle

Method #1: CSS :focus pseudo-class
As pure CSS solution, you could achieve sort of the effect by using a tabindex attribute for the image, and :focus pseudo-class as follows:
<img class="crossRotate" src="http://placehold.it/100" tabindex="1" />
.crossRotate {
outline: 0;
/* other styles... */
}
.crossRotate:focus {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
WORKING DEMO.
Note: Using this approach, the image gets rotated onclick (focused), to negate the rotation, you'll need to click somewhere out of the image (blured).
Method #2: Hidden input & :checked pseudo-class
This is one of my favorite methods. In this approach, there's a hidden checkbox input and a <label> element which wraps the image.
Once you click on the image, the hidden input is checked because of using for attribute for the label.
Hence by using the :checked pseudo-class and adjacent sibling selector +, we could get the image to be rotated:
<input type="checkbox" id="hacky-input">
<label for="hacky-input">
<img class="crossRotate" src="http://placehold.it/100">
</label>
#hacky-input {
display: none; /* Hide the input */
}
#hacky-input:checked + label img.crossRotate {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
WORKING DEMO #1.
WORKING DEMO #2 (Applying the rotate to the label gives a better experience).
Method #3: Toggling a class via JavaScript
If using JavaScript/jQuery is an option, you could toggle a .active class by .toggleClass() to trigger the rotation effect, as follows:
$('.crossRotate').on('click', function(){
$(this).toggleClass('active');
});
.crossRotate.active {
/* vendor-prefixes here... */
transform: rotate(45deg);
}
WORKING DEMO.

Voila!
div {
background-color: red;
color: white;
font-weight: bold;
width: 48px;
height: 48px;
transform: rotate(360deg);
transition: transform 0.5s;
}
div:active {
transform: rotate(0deg);
transition: 0s;
}
<div></div>

You can also affect differente DOM elements using :target pseudo class.
If an element is the destination of an anchor target it will get the :target pseudo element.
<style>
p { color:black; }
p:target { color:red; }
</style>
Click me
<p id="elem">And I will change</p>
Here is a fiddle : https://jsfiddle.net/k86b81jv/

As jeremyjjbrow said, :active pseudo won't persist. But there's a hack for doing it on pure css. You can wrap it on a <a> tag, and apply the :active on it, like this:
<a class="test">
<img class="crossRotate" src="images/cross.png" alt="Cross Menu button" />
</a>
And the css:
.test:active .crossRotate {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
}
Try it out... It works (at least on Chrome)!

You can use WebkitTransform along with Transition (transition: all 2s;) to make the desired rotation with animation.
<style>
div.a {
width: 150px;
height: 80px;
background-color: yellow;
transition: all 2s;
}
</style>
<div class="a" id="box">Your Image Here</div>
<button onclick="rotate()">Rotate </button>
<script>
function rotate()
{
x= document.getElementById("box");
x.style.WebkitTransform = 'rotate(' + 20 +'deg)';
}
</script>
The advantage with this method is that you can do it programmatically. You can specify the angle using javascript (Although this is not required in your partcular case).

Refer this.
.c-btn:hover,.c-btn-active {
transform: rotate(45deg);
}

You can use JavaScript to do this, with onClick method.
This maybe helps CSS3 transition click event

Related

CSS transform: How can I make transform value a combination of two different classes? [duplicate]

I have an element with two classes, one called "rotate" that will rotate the element 360 degrees and another called "doublesize" that will scale the element 2x its normal size:
.rotate {
transform: rotate(0deg);
}
.rotate:hover {
transform: rotate(360deg);
}
.doublesize {
transform: scale(1);
}
.doublesize:hover {
transform: scale(2);
}
http://jsfiddle.net/Sbw8W/
I'm guessing this does not work because the classes override each other's transform property?
I know that I could easily do this in one CSS rule like:
.doublerotatesize {
transform: scale(1) rotate(0deg);
}
.doublerotatesize:hover {
transform: scale(2) rotate(360deg);
}
But I would like to be able to apply each class separately from the other if it is possible.
I'm guessing this does not work because the classes override each other's transform property?
Correct. This is an unfortunate limitation as a side-effect of how the cascade works.
You will have to specify both functions in a single transform declaration. You could simply chain both class selectors together instead of creating a new class for a combined transform:
.doublesize.rotate {
-webkit-transform: scale(1) rotate(0deg);
}
.doublesize.rotate:hover {
-webkit-transform: scale(2) rotate(360deg);
}
... but as you can see, the issue lies in the transform property rather than in the selector.
This is expected to be rectified in Transforms level 2, where each transform has been promoted to its own property, which would allow you to combine transforms simply by declaring them separately as you would any other combination of CSS properties. This means you would be able to simply do this:
/* Note that rotate: 0deg and scale: 1 are omitted
as they're the initial values */
.rotate:hover {
rotate: 360deg;
}
.doublesize:hover {
scale: 2;
}
... and take advantage of the cascade rather than be hindered by it. No need for specialized class names or combined CSS rules.
Using CSS variables you can have this separation. The idea is to chain as many transformation as you want inside the element using CSS variables then later you update each variable individually:
div {
width: 100px;
height: 100px;
display: inline-block;
background-color: red;
transform:
/* I prepared 3 placeholder so we can chain 3 transformation later */
var(--t1,) /* we need "nothing" as fallbak*/
var(--t2,)
var(--t3,);
}
.transitionease {
transition: all 1s ease;
}
.transitionease:hover {
transition: all 3s ease;
}
.rotate {
--t1: rotate(0deg);
}
.rotate:hover {
--t1: rotate(360deg);
}
.doublesize {
--t2: scale(1);
}
.doublesize:hover {
--t2: scale(2);
}
<div class="transitionease"></div>
<div class="transitionease doublesize rotate "></div>
<div class="transitionease doublesize"></div>
You can surely combine multiple animation, but not by combining CSS classes. See the first answer here : combining multiple css animations into one overall animation
The first part tells you how to combine animation with CSS with some parameters (delay, duration) :
.outside.animate {
-webkit-animation-delay: 0s, .5s, .5s;
-webkit-animation-duration: 500ms, 1000ms, 1000ms;
-webkit-animation-name: button-bounce, rotate, skyblue;
}
For sure, you firstly need to define your animations.
You can't do this using just CSS, but if you don't mind using some jQuery you can attach this effect:
var $elem = $('.cssDropPinImage');
$({deg: 0}).animate({deg: 360}, {
duration: 600,
step: function(now) {
var scale = (2 * now / 360);
$elem.css({
transform: 'rotate(' + now + 'deg) scale(' + scale + ')'
});
}
});
body {
padding: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img src="https://via.placeholder.com/40" class="cssDropPinImage">
The question hints at a scale and rotate animation on hover. Another pragmatic way of solving this, is by rearranging the elements in the HTML and applying the individual transforms to the parent and the child, only responding to the hover on the parent element.
That looks something like this:
<div class="doublesize">
<div class="rotate"></div>
</div>
.doublesize {
transition: transform 1s ease;
}
.rotate {
width: 100px;
height: 100px;
background-color: red;
transition: transform 1s ease;
}
.doublesize:hover {
transform: scale(2);
}
.doublesize:hover .rotate {
transform: rotate(360deg);
}
http://jsfiddle.net/n38csxy1/4/
I know this is quite a leap from the original setup, but I hope this perspective helps someone nevertheless.

Using Shadow Dom CSS Animations on distributed (i.e., light dom) nodes with Polymer.dart

I am creating a "Radial Selector" custom element which animates on mouse-enter and on mouse-leave.
I would like users of my custom element to be able to wrap their own content with the radial-selector tag like so:
<radial-selector img="url(assets/phone.png)" style = "width: 200px; top:100px; left: 100px">
<img src="assets/phone.png" style = "height: 50px; width: 50px"/>
<img src="assets/house.png" style = "height: 50px; width: 50px"/>
<img src="assets/house.png" style = "height: 50px; width: 50px"/>
<img src="assets/house.png" style = "height: 50px; width: 50px"/>
<img src="assets/house.png" style = "height: 50px; width: 50px"/>
<img src="assets/house.png" style = "height: 50px; width: 50px"/>
</radial-selector>
I'm trying to animate the light DOM children without bringing them into the shadow DOM of my element, which seems like it might be overkill for this task. I want the definitions of these animations to exist within the custom element's template tag for obvious encapsulation reasons. I figured this would all be possible to do since you can reveal light DOM nodes to the custom element using the insertion tag, and then target the inserted light DOM nodes with a CSS Style by using the ::content pseudo-selector.
This is what I tried to do in the following radial selector html definition:
<!DOCTYPE html>
<polymer-element name="radial-selector">
<template>
<style>
:host {
display: block;
position: absolute;
}
::content .leaf {
position: absolute;
-webkit-transform: scale({{maxLeafScale}}, {{maxLeafScale}});
opacity: {{maxLeafOpa}};
}
::content .expand {
-webkit-animation: expand 1s;
}
::content .close {
-webkit-animation: close 1s;
}
::content .bump {
-webkit-animation: bump 1s;
}
::content .unbump {
-webkit-animation: unbump 1s;
}
::content #stem {
position: absolute;
-webkit-transform: scale({{maxStemScale}}, {{maxStemScale}});
}
#-webkit-keyframes expand {
from {opacity: {{currLeafOpa}};
-webkit-transform: scale({{currLeafScale}}, {{currLeafScale}});
}
to {opacity: {{maxLeafOpa}};
-webkit-transform: scale({{maxLeafScale}}, {{maxLeafScale}});
}
}
#-webkit-keyframes bump {
from {
-webkit-transform: scale({{currStemScale}}, {{currStemScale}});
}
to {
-webkit-transform: scale({{maxStemScale}},{{maxStemScale}});
}
}
#-webkit-keyframes unbump {
from {
-webkit-transform: scale({{currStemScale}}, {{currStemScale}});
}
to {
-webkit-transform: scale({{minStemScale}}, {{minStemScale}});
}
}
#-webkit-keyframes close {
from {opacity: {{currLeafOpa}};
-webkit-transform: scale({{currLeafScale}}, {{currLeafScale}});
}
to {opacity: {{maxLeafOpa}};
-webkit-transform: scale({{minLeafScale}}, .{{minLeafScale}});
}
}
</style>
<content></content>
</template>
<script type="application/dart" src="radialselector.dart"></script>
</polymer-element>
However, the element is not animating at all. I add and remove the appropriate classes in response to the proper events, and the inspector shows the classes/styles changing.
The ::content pseudo-selectors work in applying regular styles (e.g., position: absolute), but not the -webkit-animation properties. Maybe it's because the #keyframes definitions still live completely in the shadow dom? There's no way to add a ::content pseudo-selector to them, right? I tried ::content #keyframes ..etc. but no luck.
Do I have to bite the bullet and bring the light DOM children into the shadow dom? Or is there a way to animate the light DOM children using css animations defined in the custom element?
I believe #keyframes, like #font-face, have to be in document level CSS so you'll need to pull them out of your element. Here's an example: http://jsbin.com/zisupu/6/edit
Previously this was documented in the Polymer docs but has since been commented out. I've opened a thread to see if we can sort out a recommendation. https://github.com/Polymer/docs/issues/434
edit
Opened Chromium bug #382498

Applying CSS rules based on input checkbox status

I'm currently developing a site that uses the :checked variable to apply rules to the CSS. I've got a checkbox input that when triggered, should accomplish two things. The first thing it should do is expand a div from a height of 0 to 200 when checked, and back to 0 when unchecked. I had no problems with triggering that first task. The second thing that should be accomplished upon checking the box, is a transform: rotate(45deg) of a div with a "+" in it that should rotate 45 degrees into an "x" (not an actual x, but a rotated +).
I've currently got my code setup to display the animation on :hover, but that's just for illustrative purposes, that wouldn't be in my final code. So hover over the "+ to see what I'm trying to accomplish with the :checked input.
If you're willing to take a look at my code, and tell me what I'm doing wrong, I'd be greatly appreciative! Let me know if you have any questions.
Note: Ideally I'm looking for a pure CSS solution without the need for JS. Let me know if this isn't possible.
Here's my code pen.
I wrote a similar solution the other day, here.
Basically, you are limited when using the :checked method. You are relying on the adjacent and general sibling combinators, +, ~. If the element isn't a general preceding sibling, it isn't going to work.
In this example, .expand was not a preceding sibling. Therefore the solution is to place the input element at the root of the document, and then use the selector input[name='panel']:checked ~ label .rotate to change the .rotate element. Note, that the general sibling combinator, ~ is now also being used as opposed to the adjacent sibling combinator, +.
No need for JS - UPDATED EXAMPLE
Modified HTML:
<input type="checkbox" name="panel" class="hidden" id="panel"/>
<label for="panel">
Click Me
<div class="rotate">+</div>
</label>
<div class="expand">
Content goes here.
</div>
Updated CSS:
input[name='panel']:checked ~ label .rotate {
transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
It's worth noting that I moved the transition properties to the .rotate element too.
jQuery Solution:
http://jsfiddle.net/SinisterSystems/PUwh6/2/
Use an ID so jQuery can map out what you're doing easily without searching for classes all over the place.
HTML:
<label for="panel">
Click Me
<div id="rotate">+</div>
</label>
CSS:
#rotate {
width: 12px;
float: right;
font-size: 18px;
margin-top: -6px;
text-align: center;
transition: all 1s ease;
-o-transition: all 1s ease;
-moz-transition: all 1s ease;
-webkit-transition: all 1s ease;
}
#rotate.spin {
transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
jQuery:
$('#panel').on('click',function() {
$('#rotate').toggleClass('spin');
});

How can I apply multiple transform declarations to one element?

I have an element with two classes, one called "rotate" that will rotate the element 360 degrees and another called "doublesize" that will scale the element 2x its normal size:
.rotate {
transform: rotate(0deg);
}
.rotate:hover {
transform: rotate(360deg);
}
.doublesize {
transform: scale(1);
}
.doublesize:hover {
transform: scale(2);
}
http://jsfiddle.net/Sbw8W/
I'm guessing this does not work because the classes override each other's transform property?
I know that I could easily do this in one CSS rule like:
.doublerotatesize {
transform: scale(1) rotate(0deg);
}
.doublerotatesize:hover {
transform: scale(2) rotate(360deg);
}
But I would like to be able to apply each class separately from the other if it is possible.
I'm guessing this does not work because the classes override each other's transform property?
Correct. This is an unfortunate limitation as a side-effect of how the cascade works.
You will have to specify both functions in a single transform declaration. You could simply chain both class selectors together instead of creating a new class for a combined transform:
.doublesize.rotate {
-webkit-transform: scale(1) rotate(0deg);
}
.doublesize.rotate:hover {
-webkit-transform: scale(2) rotate(360deg);
}
... but as you can see, the issue lies in the transform property rather than in the selector.
This is expected to be rectified in Transforms level 2, where each transform has been promoted to its own property, which would allow you to combine transforms simply by declaring them separately as you would any other combination of CSS properties. This means you would be able to simply do this:
/* Note that rotate: 0deg and scale: 1 are omitted
as they're the initial values */
.rotate:hover {
rotate: 360deg;
}
.doublesize:hover {
scale: 2;
}
... and take advantage of the cascade rather than be hindered by it. No need for specialized class names or combined CSS rules.
Using CSS variables you can have this separation. The idea is to chain as many transformation as you want inside the element using CSS variables then later you update each variable individually:
div {
width: 100px;
height: 100px;
display: inline-block;
background-color: red;
transform:
/* I prepared 3 placeholder so we can chain 3 transformation later */
var(--t1,) /* we need "nothing" as fallbak*/
var(--t2,)
var(--t3,);
}
.transitionease {
transition: all 1s ease;
}
.transitionease:hover {
transition: all 3s ease;
}
.rotate {
--t1: rotate(0deg);
}
.rotate:hover {
--t1: rotate(360deg);
}
.doublesize {
--t2: scale(1);
}
.doublesize:hover {
--t2: scale(2);
}
<div class="transitionease"></div>
<div class="transitionease doublesize rotate "></div>
<div class="transitionease doublesize"></div>
You can surely combine multiple animation, but not by combining CSS classes. See the first answer here : combining multiple css animations into one overall animation
The first part tells you how to combine animation with CSS with some parameters (delay, duration) :
.outside.animate {
-webkit-animation-delay: 0s, .5s, .5s;
-webkit-animation-duration: 500ms, 1000ms, 1000ms;
-webkit-animation-name: button-bounce, rotate, skyblue;
}
For sure, you firstly need to define your animations.
You can't do this using just CSS, but if you don't mind using some jQuery you can attach this effect:
var $elem = $('.cssDropPinImage');
$({deg: 0}).animate({deg: 360}, {
duration: 600,
step: function(now) {
var scale = (2 * now / 360);
$elem.css({
transform: 'rotate(' + now + 'deg) scale(' + scale + ')'
});
}
});
body {
padding: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img src="https://via.placeholder.com/40" class="cssDropPinImage">
The question hints at a scale and rotate animation on hover. Another pragmatic way of solving this, is by rearranging the elements in the HTML and applying the individual transforms to the parent and the child, only responding to the hover on the parent element.
That looks something like this:
<div class="doublesize">
<div class="rotate"></div>
</div>
.doublesize {
transition: transform 1s ease;
}
.rotate {
width: 100px;
height: 100px;
background-color: red;
transition: transform 1s ease;
}
.doublesize:hover {
transform: scale(2);
}
.doublesize:hover .rotate {
transform: rotate(360deg);
}
http://jsfiddle.net/n38csxy1/4/
I know this is quite a leap from the original setup, but I hope this perspective helps someone nevertheless.

CSS transition effect makes image blurry / moves image 1px, in Chrome?

I have some CSS that on hover, a CSS transition effect will moves a div.
The problem, as you can see in the example, is that the translate transition has the horrible side effect of making the image in the div move by 1px down/right (and possibly resize ever so slightly?) so that it appears out of place and out of focus...
The glitch seems to apply the whole time the hover effect is applied, and from a process of trial and error I can safely say only seems to occur when the translate transition moves the div (box shadow and opacity are also applied but make no difference to the error when removed).
The problem only seems to happen when the page has scrollbars. So the example with just one instance of the div is fine, but once more identical divs are added and the page therefore requires a scrollbar the problem strikes again...
2020 update
If you have issues with blurry images, be sure to check answers from below as well, especially the image-rendering CSS property.
For best practice accessibility and SEO wise you could replace the background image with an <img> tag using object-fit CSS property.
Original answer
Try this in your CSS:
.your-class-name {
/* ... */
-webkit-backface-visibility: hidden;
-webkit-transform: translateZ(0) scale(1, 1);
}
What this does is it makes the division to behave "more 2D".
Backface is drawn as a default to allow flipping things with rotate
and such. There's no need to that if you only move left, right, up, down, scale or rotate (counter-)clockwise.
Translate Z-axis to always have a zero value.
Chrome now handles backface-visibility and transform without the -webkit- prefix. I currently don't know how this affects other browsers rendering (FF, IE), so use the non-prefixed versions with caution.
You need to apply 3d transform to the element, so it will get its own composite layer.
For instance:
.element{
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
or
.element{
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
More about layer creation criteria you can read right here: Accelerated Rendering in Chrome
An explanation:
Examples (hover green box):
Problem: Transition may cause blink effect on sibling elements (OSx Lion, Chrome 30)
Solution: An element on its own composite layer
When you use any transition on your element it cause browser to recalculate styles, then re-layout your content even if transition property is visual (in my examples it is an opacity) and finaly paint an element:
The issue here is re-layout of the content that can make an effect of "dancing" or "blinking" elements on the page while transition happens.
If you will go to settings, check "Show composite layers" checkbox and then apply 3d transform to an element, you will see that it gets it's own layer which outlined with orange border.
After element gets its own layer, browser just needs to composite layers on transition without re-layout or even paint operations so problem have to be solved:
Had the same problem with embeded youtube iframe (Translations were used for centering iframe element). None of the solutions above worked until tried reset css filters and magic happened.
Structure:
<div class="translate">
<iframe/>
</div>
Style [before]
.translate {
transform: translateX(-50%);
-webkit-transform: translateX(-50%);
}
Style [after]
.translate {
transform: translateX(-50%);
-webkit-transform: translateX(-50%);
filter: blur(0);
-webkit-filter: blur(0);
}
I recommended an experimental new attribute CSS I tested on latest browser and it's good:
image-rendering: optimizeSpeed; /* */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Chrome (and Safari) */
image-rendering: optimize-contrast; /* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor; /* IE8+ */
With this the browser will know the algorithm for rendering
Just found another reason why an element goes blurry when being transformed. I was using transform: translate3d(-5.5px, -18px, 0); to re-position an element once it had been loaded in, however that element became blurry.
I tried all the suggestions above but it turned out that it was due to me using a decimal value for one of the translate values. Whole numbers don't cause the blur, and the further away I went from the whole number the worse the blur became.
i.e. 5.5px blurs the element the most, 5.1px the least.
Just thought I'd chuck this here in case it helps anybody.
I cheated problem using transition by steps, not smoothly
transition-timing-function: steps(10, end);
It is not a solving, it is a cheating and can not be applied everywhere.
I can't explain it, but it works for me. None of another answers helps me (OSX, Chrome 63, Non-Retina display).
https://jsfiddle.net/tuzae6a9/6/
Scaling to double and bringing down to half with zoom worked for me.
transform: scale(2);
zoom: 0.5;
Try filter: blur(0);
It worked for me
I've tried around 10 possibly solutions. Mixed them up and they still didn't work correctly. There was always 1px shake at the end.
I find solution by reducing transition time on filter.
This didn't work:
.elem {
filter: blur(0);
transition: filter 1.2s ease;
}
.elem:hover {
filter: blur(7px);
}
Solution:
.elem {
filter: blur(0);
transition: filter .7s ease;
}
.elem:hover {
filter: blur(7px);
}
Try this in fiddle:
.blur {
border: none;
outline: none;
width: 100px; height: 100px;
background: #f0f;
margin: 30px;
-webkit-filter: blur(10px);
transition: all .7s ease-out;
/* transition: all .2s ease-out; */
}
.blur:hover {
-webkit-filter: blur(0);
}
.blur2 {
border: none;
outline: none;
width: 100px; height: 100px;
background: tomato;
margin: 30px;
-webkit-filter: blur(10px);
transition: all .2s ease-out;
}
.blur2:hover {
-webkit-filter: blur(0);
}
<div class="blur"></div>
<div class="blur2"></div>
I hope this helps someone.
For me, now in 2018. The only thing that fixed my problem (a white glitchy-flicker line running through an image on hover) was applying this to my link element holding the image element that has transform: scale(1.05)
a {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transform: translateZ(0) scale(1.0, 1.0);
transform: translateZ(0) scale(1.0, 1.0);
-webkit-filter: blur(0);
filter: blur(0);
}
a > .imageElement {
transition: transform 3s ease-in-out;
}
None of this worked, what worked for me is scaling image down.
So depending on what size you want the image or what resoultion your image is, you can do something like this:
.ok {
transform: perspective(100px) rotateY(0deg) scale(0.5);
transition: transform 1s;
object-fit:contain;
}
.ok:hover{
transform: perspective(100px) rotateY(-10deg) scale(0.5);
}
/* Demo Preview Stuff */
.bad {
max-width: 320px;
object-fit:contain;
transform: perspective(100px) rotateY(0deg);
transition: transform 1s;
}
.bad:hover{
transform: perspective(100px) rotateY(-10deg);
}
div {
text-align: center;
position: relative;
display: flex;
}
h3{
position: absolute;
bottom: 30px;
left: 0;
right: 0;
}
.b {
display: flex;
}
<center>
<h2>Hover on images</h2>
<div class="b">
<div>
<img class="ok" src='https://www.howtogeek.com/wp-content/uploads/2018/10/preview-11.png'>
<h3>Sharp</h3>
</div>
<div>
<img class="bad" src='https://www.howtogeek.com/wp-content/uploads/2018/10/preview-11.png'>
<h3>Blurry</h3>
</div>
</div>
</center>
The image should be scaled down, make sure you have a big image resoultion
I had a similar problem with blurry text but only the succeeding div was affected. For some reason the next div after the one that I was doing the transform in was blurry.
I tried everything that is recommended in this thread but nothing worked.
For me rearranging my divs worked. I moved the div that blurres the following div to the end of parents div.
If someone know why just let me know.
#before
<header class="container">
<div class="transformed div">
<span class="transform wrapper">
<span class="transformed"></span>
<span class="transformed"></span>
</span>
</div>
<div class="affected div">
</div>
</header>
#after
<header class="container">
<div class="affected div">
</div>
<div class="transformed div">
<span class="transform wrapper">
<span class="transformed"></span>
<span class="transformed"></span>
</span>
</div>
</header>
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration
I was helped by setting the value of transition duration .3s equal transition timing steps .3s
The blurring occurred for me in Chrome only (Windows and Mac) when animating 'transform' in a keyframe animation. For me, the -webkit-optimize-contrast setting only partially helped. For best results I also had to use a "magic value" for scaleX (slightly larger than 1 instead of 1).
Here's the code that worked:
img {
image-rendering: -webkit-optimize-contrast;
}
#keyframes scale-in-left {
0% {
transform: scaleX(0);
opacity: 0;
}
100% {
transform: scaleX(1.000001);
opacity: 1;
}
}
Here's the code that didn't work (caused blurry images in Chrome):
#keyframes scale-in-left {
0% {
transform: scaleX(0);
opacity: 0;
}
100% {
transform: scaleX(1);
opacity: 1;
}
}
In the end, the "working" code removed most of the blurring, but not all of it. Safari and Firefox were still clearer without any special settings.
Note also that just resizing the browser window cleared up the unwanted blurring, suggesting perhaps that something is causing Chrome to fail to execute a final render pass (?).

Resources