Is it possible to animate CSS pseudo-classes?
Say I have:
#foo:after {
content: '';
width: 200px;
height: 200px;
background: red;
display: block;
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
}
#foo:hover:after {
width: 250px;
height: 250px;
}
Is this even possible? I've been testing and so far I can't seem to find a solution. I'm trying to trim down the amount of JavaScript support I need by using Modernizr.
I already have a JavaScript method, so please no JavaScript alternatives.
Demo: http://jsfiddle.net/MxTvw/
Your fiddle does work for me in Firefox. And as far as I know, and if this article is up to date this is the only browser that can animate pseudo-elements.
EDIT: As of 2016, the link to article is broken and the relevant WebKit bug was fixed 4 years ago. Read on to see other answers, this one is obsolete.
Google Chrome added the webkit bug fix to Version 27.0.1453.110 m
This WebKit bug was fixed: http://trac.webkit.org/changeset/138632
IT IS POSSIBLE to animate pseudo :before and :after, here are a couple of examples for animating the psuedo-elements :before and :after.
Here is a modification of your example above with some edits, that make it animate in and out more smoothly without the simulated mouseleave / mouseout delay on hover:
http://jsfiddle.net/MxTvw/234/
Try adding the main selector #foo with the grouped :hover pseudo-class in your second :hover pseudo-class rule. Also add the transition property, and not just the vendor specific prefixed properties for transition:
#foo:after{
display: block;
content: '';
width: 200px;
height: 200px;
background: red;
-webkit-transition: all .4s ease-in-out;
-moz-transition: all .4s ease-in-out;
-o-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
#foo,
#foo:hover:after,
#foo:hover:before{
width: 250px;
height: 250px;
}
Note that going forward any Pseudo Elements like :before and :after should use the double colon syntax ::before and ::after. This example simulates a fade in and out using a overlay background-color and a background-image on hover:
http://jsfiddle.net/MxTvw/233/
This example simulates a animate of rotation on hover:
http://jsfiddle.net/Jm54S/28/
Of course moving forward with css3 standards we could use ::before and ::after.
This works in latest Firefox, Chrome, Safari, Opera 18+, IE10, IE11 (IE9 and below do not support css3 transitions or animate.)
It does not seem to work now, however according to the W3 specs you can apply transitions to pseudo-elements. Maybe some time in future…
I just found out that you can animate :after and :before (:
Code example-
.model-item {
position: relative;
&:after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
right: 0;
background: transparent;
transition: all .3s;
}
}
.opc {
&:after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
right: 0;
background: rgba(0, 51, 92, .75);
}
}
I have the div .model-item and i needed to animate his :after.
So i've added another class which changes background and i added the transition code to the main :after (before animation)
Related
this question might be obvious but i'm new in css.
I'm animating a shape so when you hover it, it stretches. I've completed the hover on with a nice ease transition but when you move off the mouse the transition doesn't work. Is there a way to make it happen also in the hover off moment?
.shape1{
position: absolute;
background:red
top:512px;
width:180px;
height:140px;
}
.shape1:hover {
height: 160px;
top:492px;
transition: 0.2s ease;
}
Your answer
You have added the transition property on the hover state of the element. Therefore the transition is not applied when you leave the cursor from the element.
.shape1{
position: absolute;
background: red;
top: 512px;
width: 180px;
height: 140px;
transition: .2s ease; /* move this here from :hover */
}
Further information
Besides this you can also add specific properties to the transition. For example, if you only want the height to be animated you could it like this:
.shape1 {
transition: height .2s ease;
/* this inly affects height, nothing else */
}
You can even define different transition-times for each property:
.shape1 {
transition: height .2s ease, background-color .5s linear;
/* stacking transitions is easy */
}
Add the transition before the :hover, so the transition always applies
.shape1 {
transition: 0.2s ease;
}
The :hover selector is used to select elements when you mouse over them.
W3Schools
When you add also transition to your shape1 class it should works
I'm using css transitions to cause a fade-in and fade-out effect on a background-image property. The property gets changed via jquery when the user scrolls.
It initially did not work on any browser. I found that setting an completley empty/transparent PNG file on the original element made chrome work, but the other browsers still don't.
Here's an example of the code:
nav {
background:url(/img/empty.png);
background-origin:border-box;
background-position:top;
background-repeat:repeat;
background-size:50px 50px;
transition: background 1s ease-in-out;
-moz-transition: background 1s ease-in-out;
-webkit-transition: background 1s ease-in-out;
}
.contrast {
background:#3a3a3a url(/img/xnav.jpg);
background-origin:border-box;
background-position:top;
background-repeat:repeat;
background-size:50px 50px;
}
The contrast class gets applied to the nav element via jquery. It only seems to fade out on most browsers, but not fade in. It works properly in chrome.
Q1: Is there a cleaner way to do this? Adding a transparent PNG as a background element to the nav element seems like a hack.
Q2: This still doesn't work on firefox, IE or Safari. Can anyone suggest a clean fix?
You can "fake" the background-image opacity with pseudo-element on your:
nav{
position:relative;
}
nav::before{
content: "";
background: url(/img/xnav.jpg);
background-origin:border-box;
background-position:top;
background-repeat:repeat;
background-size:50px 50px;
opacity: 0;
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
transition: opacity 1s ease-in-out;
}
.contrast{ // applied on nav::before
opacity: 1;
}
Thanks to Nicolas Gallagher for this.
I'm having an issue when trying to position :before content in Safari. In Chrome/IE the content is positioned correctly, but Safari is interpreting the styles differently (see: http://jsfiddle.net/danwoods/Yb8aR/). my initial thought was to remove the position: absolute from the span:before, but that presents it's own issues...
Does anything look out of place? Any explanation as to why Safari is displaying things differently than Chrome?
Thanks,
Dan
I'm not sure what problems you were having with removing position absolute, but I've changed it to position: relative, used top: 4px to line it up with the text, and display: inline-block to allow margin right to separate it from the text.
span:before {
content: url(https://dl.dropboxusercontent.com/u/6114719/progress-2.png);
display: inline-block;
position: relative;
top: 4px;
margin-right: 5px;
transition: all 1.5s ease-in-out;
-webkit-transition: all 1.5s ease-in-out;
-moz-transition: all 1.5s ease-in-out;
-o-transition: all 1.5s ease-in-out;
}
Fiddle is here: http://jsfiddle.net/Yb8aR/5/ - tested in Chrome and Safari.
Note:
Looks like Safari aligns the before pseudo-element to the span element, whereas Chrome seems to align it to the text within the span element (which is centered). Why that happens, I'm really not sure.
I'm trying to apply a pseudo element to a <tr> but turns out it's not working as expected. I'm not sure if i'm missing anything or if it's just simply not possible.
Here's a jsfiddle example: http://jsfiddle.net/jDwCq/
Notice that if you change the display of tr to display: block;, the pseudo element will show up, but it is displayed as a block rather than a table, which i need.
Is it possible or am I doomed?
table tr:before{
position: relative; /* Needed for pseudo elem */
display: block; /*Uncomment me and see what happens*/
}
this should work...
tr:hover td{
background: pink or whatever;
}
tr:hover td:after{
background: yellow;
}
I don't see the need for pseudo elements.
I will say that having an element, which isn't a cell, directly inside a row, is asking for pain.
You could always have a pseudo-element inside every cell of a targeted row, though. With the right css, there will be no perceptible difference.
Example: http://jsfiddle.net/jDwCq/7/
Just set display: inline-block; to TDs, and give them a width (~33% each)... and remove position: absolute from the pseudoelement.
That's it: http://jsfiddle.net/jDwCq/6/
table tr {
/*position: relative; /* (REALLY NOT) Needed for pseudo elem */
display: block; /*Uncomment me and see what happens*/
}
td {
width: 32.9%; /* ADD THIS */
display: inline-block; /* AND THIS */
}
table tr:after {
/*position: absolute; REMOVE THIS TOO */
top: 0px;
left: 0px;
display: block;
content: '';
text-indent: -99999px;
background: red;
height: 2px;
/*width: 100%; NOT NEEDED */
}
To make the rows appear bigger using ::before and/or ::after pseudo-elements you'd have to apply those elements to the td elements, but select the td elements based on the :hover of the tr:
td::before,
td::after {
/* defines the default states/sizes */
height: 0;
display: block;
content: '';
}
tr:hover td::before,
tr:hover td::after {
/* adjusts attributes based on the parent tr's :hover event */
height: 1em;
}
JS Fiddle demo.
However, if the aim is to 'look cool1' then I'd suggest adjusting the styling of the td elements themselves (since that way they can be animated), rather than using the pseudo-elements which just 'appear':
td {
padding: 0;
-moz-transition: padding 1s linear;
-ms-transition: padding 1s linear;
-o-transition: padding 1s linear;
-webkit-transition: padding 1s linear;
transition: padding 1s linear;
}
tr:hover td {
padding: 1em 0;
-moz-transition: padding 1s linear;
-ms-transition: padding 1s linear;
-o-transition: padding 1s linear;
-webkit-transition: padding 1s linear;
transition: padding 1s linear;
}
JS Fiddle demo.
Of course using this approach, you can use transition effects on color, background-color, height, font-size border (-width or -color), and adjust the timing (as well as the easing).
To animate multiple properties it's easier to use the keyword all (rather than the individual property names).
Given that I'm over the age of thirty I'm having trouble defining, or even recognising, 'cool' these days; but my seven year old nephew assures me that animating the padding looks 'okay.' You may, perhaps, have to consult your own child-relatives for the coolness of alternative approaches.
I'm showing the title attribute of a link on :hover. The title attribute is appended to the link via :after…
Now I'm wondering how I can animate the opacity of the :after pseudo-element when hovering-in and hovering-out.
html
<a class="link" href="#" title="something"></a>
css
.link {
display:block;
width:50px;
height:50px;
background:red;
}
.link:after {
position:relative;
content: attr(title);
top:55px;
color:$blue;
zoom: 1;
filter: alpha(opacity=00);
opacity: 0;
-webkit-transition: opacity .15s ease-in-out;
-moz-transition: opacity .15s ease-in-out;
-ms-transition: opacity .15s ease-in-out;
-o-transition: opacity .15s ease-in-out;
transition: opacity .15s ease-in-out;
}
.link:hover:after {
zoom: 1;
filter: alpha(opacity=100);
opacity: 1;
}
Check out the demo: http://jsfiddle.net/d2KrC/
Any ideas why this is not working?
WebKit (Chrome, Safari) does not support transitions on pseudo elements.
https://bugs.webkit.org/show_bug.cgi?id=23209
http://code.google.com/p/chromium/issues/detail?id=54699
It should work in Firefox.
Edit: The issue in WebKit is now resolved. The patch allready landed in Chrome Carnery, so it will be supportet from version 26 on. I don't know about Safari.
Theres a fairly easy workaround to this webkit bug to make transitions work on pseudo classes. Here's a great blog post about it: http://xiel.de/webkit-fix-css-transitions-on-pseudo-elements/
Basically webkit doesnt support the transitions directly but you can apply the transition and style you want to change to its parent element. Then in the pseudo class you put the same style properties that you want to affect, but give them the value: inherit. That will cause them to inherit all of the parent elements values including the transition.
Here's a sample I did to animate the :after element, up and down
a {
position: static; /* explicitly defined so not to forget that it can't be relative or :after transition hack will not work */
top: 1px; /*doesnt move it because it is position static */
-webkit-transition: top 200ms ease 0;
}
a:after {
content: '';
position: absolute;
top: inherit;
}
a:hover {
top: 3px;
}
*Update
The bug has been fixed in Chrome Canary (as of February), but still appears to be broken in Safari. Can check the status and stay updated on it here:
https://code.google.com/p/chromium/issues/detail?id=54699