Pseudo elements on tables? - css

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.

Related

:active transition ended by :hover

I have these 3 rules:
.thingy{
display:inline-block;
position:relative;
width: 5em;
height: 5em;
background-color:#FF0000;
left:0em;
transition: left 4s linear, background-color 4s;
}
.thingy:active{
left:10em;
transition: left 0s linear;
}
.thingy:hover{
background-color:#00FF00;
transition: background-color 0s linear;
}
and this bit of basic HTML:
<div class="thingy"></div>
When the <div> is clicked, it will move to the right, as expected. However, whenever it is hovered over while it is returning to it's original position, it will snap back immediately.
I want it to, while returning to it's original position from being clicked, to be able to swap it's background-color (or any other property) then fade back to it's normal values without overriding any other transition currently going on.
For the purposes of the code, I can only use pure CSS, and I cannot utilize #key-frames or any property associated to it, such as animation-duration.
You can use CSS variable for this task
.thingy {
display: inline-block;
position: relative;
width: 5em;
height: 5em;
background-color: #FF0000;
left: 0em;
transition:
var(--t-left,left 4s linear),
var(--t-back,background-color 4s);
}
.thingy:active {
left: 10em;
--t-left: left 0s;
}
.thingy:hover {
background-color: #00FF00;
--t-back: background-color 0s
}
<div class="thingy"></div>

Is a new transition always applied before the new value?

Suppose I'm using transition, to smoothly change an element's position on hover. I also change the value of transition itself to achieve a different animation in each direction.
It seems like when I move the mouse over the elements, the new transition value is used for the "forward" transition, and when I un-hover, the old value is used for the "reverse" transition.
I couldn't find much documentation about this. Is the order guaranteed?
div {
background: red;
width: 40px;
height: 40px;
position: absolute;
top: 30px;
left: 0px;
transition: left 1s linear, top 1s ease-in-out;
}
:hover div {
top: 150px;
left: 400px;
transition: left 1s linear, top 1s linear;
}
div:nth-child(2) { transition-delay: 0.1s; }
div:nth-child(3) { transition-delay: 0.2s; }
div:nth-child(4) { transition-delay: 0.3s; }
Hover on me!
<div></div>
<div></div>
<div></div>
<div></div>
[...] all 3 properties change their values when I hover on the element, and it's not intuitively clear in which order the changes are applied, at least coming from background experience with a framework such as Core Animation where "model" and "presentation" layers are separate things and the parameters of an animation are set up before the animation starts running. I think your answer makes sense though...
I think the key difference here is that thinking about transition in terms of "animations starting while the element is/isn't :hovered" is the wrong way to think about it.
You are right, the paradigm you're used to (an MVC paradigm) doesn't really apply to CSS. At least not at the level where you as a CSS "writer" are affected. The relevant spec for this, by the way, is CSS Transitions
In CSS, changes to CSS properties apply immediately. Transitions allow you to apply a change to a value over some duration. In your case, you have four divs who are all set to be 30px from the top and 0px from the left edges of the screen.
On hover, thanks to your :hover div selector, new styles apply. Normally they'd apply instantaneously, but because you gave them a transition, it happens over a duration. You can see each one move individually thanks to the transition-delay you gave some of them, as well. To make it even easier to see, I changed the color of each div to be unique. It should be pretty clear which ones move first.
As soon as you remove your mouse, the :hover pseudo-class no longer applies, and so the styles under div are re-applied. Again, they would be instantaneously applied, but the transition you set (along with the transition-delay on 3 of the 4 divs) changes that to occur over a longer duration. So, just as when the :hover` styles apply, the red div moves first, then the others after an increasing 0.1s delay each.
div {
background: red;
width: 40px;
height: 40px;
position: absolute;
top: 30px;
left: 0px;
transition: left 1s linear, top 1s ease-in-out;
}
:hover div {
top: 150px;
left: 400px;
transition: left 1s linear, top 1s linear;
}
div:nth-child(2) { transition-delay: 0.1s; background: blue; }
div:nth-child(3) { transition-delay: 0.2s; background: green; }
div:nth-child(4) { transition-delay: 0.3s; background: yellow; }
Hover on me!
<div></div>
<div></div>
<div></div>
<div></div>

Chrome Transitions doesnt work. all other browsers do

I've created a menu that adjusts itself as it gets past a certain point of the screen. Everything works great, except for transitions and only on Chrome.
I tried adding a -webkit- version of the transition, but it doesn't work either.
This is my CSS
.past-main {
height: 97px !important;
margin-left: -40px;
width: 100%;
top: 0px !important;
position: absolute;
-webkit-transition: height 300ms opacity 300ms top 300ms ease 0s;
transition: height 300ms, opacity 300ms,top 300ms ease 0s;
opacity: 1!important;
height: 90px !important;
margin-top:0px !important;
}
.past-maina {
-webkit-transition: top 800ms ease 0s;
transition: top 800ms ease 0s!important;
top:0px!important;
}
.past-mainb {
-webkit-transition: all 800ms ease 0s;
transition: all 800ms ease 0s;
margin-top:0px!important;
}
To add more context, the various levels of your header menu gets those classes applied when the user scrolls past a certain point:
some wrapper elements get past-maina and past-main
each menu item (they are li elements) gets past-mainb
Before scrolling down, each menu item has varying margin-top values; afterwards they all get 0. These are set with style rules like
.desktop-nav ul li:nth-child(1) {
margin-top: -10px;
}
Now, this selector has a higher specificity (22) than your .past-mainb selector (10), which, I'm guessing, is why you added the !important annotation to the latter's rule: otherwise, it wouldn't take effect.
But this had an undesired side effect: important declarations always win over transitions! Thus, if you want your transitions to take effect you can't use !important.
The simple cheat is to up the specificity of the "past main" style rules. For example, add an ID selector. Or perhaps better: instead of adding a class when the user scrolls, remove a "before main" class instead, and rewrite all the rules giving specific menu-item margins to use it:
.desktop-nav.before-main ul li:nth-child(1) {
margin-top: -10px;
}

how to animate scaling an image over time via webkit

I have collection of images in a simple gallery that I want to transform from small to large smoothly on mouseover.
I am currently doing this by revealing the actual size of an image when the mouse is over but forcing it to a certain size when it is not and hiding the real size with display:none.
I want to include some webkit transformations to do this over a 1s period to improve the transitions. I understand webkit is to transform an element between two states however is there anyway I can make this happen.
I also want to avoid JavaScript.
.reveal a .preview
{
display: none;
}
.reveal a:hover .preview
{
display: block;
position: absolute;
z-index: 1;
}
.reveal img
{
background: #fff
padding: 2px;
vertical-align: top;
width: 100px;
height: 75px;
}
.reveal li
{
background: #eee;
display: inline;
float: left;
margin: 3px;
padding: 5px;
position: relative;
}
.reveal .preview
{
border-color: #000;
width: auto;
height: auto;
}
without the html (ie jsfiddle) it's hard for me to insert the solution within your code.. but here is a generic solution http://jsfiddle.net/9QVae/2/
img
{
width:100px;
height:100px;
background:red;
transition:width 1s, height 1s;
-moz-transition:width 1s, height 1s, -moz-transform 1s; /* Firefox 4 */
-webkit-transition:width 1s, height 1s, -webkit-transform 1s; /* Safari and Chrome */
-o-transition:width 1s, height 1s, -o-transform 1s; /* Opera */
}
on hover:
img:hover
{
width:200px;
height:200px;
}
so the trick is to specify the css property you want to add an effect to (ie width)
then specify the duration of the event ie transition:width 1s; then you specify the final dimension under the :hover selector
note: transition does not work on IE

Animate the CSS transition property within :after/:before pseudo-classes

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)

Resources