CSS3 transition only when class is added, not when removed - css

I have the following CSS example:
.message{
background-color: red;
transition: background-color 5s;
-webkit-transition: background-color 5s; /* Safari */
transition-delay: 2s;
-webkit-transition-delay: 2s; /* Safari */
}
.unreadMessage{
background-color: blue;
}
Then, i have a DIV with .message class, and by pressing a Button, i add the class .unreadMessage, and by pressing another Button, i remove it.
With this example, every time i change background-color, by adding or removing .unreadMessage, it does the CSS transition.
What i want to do, is, if possible, to have an instant color change when i add .unreadMessage, and have the transition only when removing it.
The first thing that come in my mind, was to have a different class containing the CSS transition properties, and add it after adding .unreadMessage.
But it is possible to do it with only one class, or using a Javascript workaround?

If you want to only apply a transition when the .message element does not have the unreadMessage class, then put the transition properties in the .message:not(.unreadMessage) selector:
.message{
background-color: red;
}
.message:not(.unreadMessage) {
-webkit-transition: background-color 5s; /* Safari */
transition: background-color 5s;
-webkit-transition-delay: 2s; /* Safari */
transition-delay: 2s;
}
.unreadMessage{
background-color: blue;
}
Demo: http://jsfiddle.net/Hs8fa/
Documentation for :not()

There are two things to remember when using CSS transitions:
Transitions happen when an element's state is modified "using pseudo-classes like :hover or :active or dynamically set using JavaScript."
You have to have a starting point and an ending point or they won't work.
The biggest issue with OP's question isn't their CSS, it's their naming structure. A major pattern of CSS transitions is to modify an element's class (or in the MDN's language "dynamically set using Javascript"). In OP's example they're not modifying an element's class structure, they're changing classes. CSS transitions won't work when an element changes from one class to another, but they will work when a class is added or taken away.
The easiest example of this is going from .element to .element.active. If we put the transition on the base class, .element, and then add a modifying class, .active, the transitions applied to .element will transition from .element settings to .element.active. settings.
Here's a JSFiddle example of modifying a base class
Secondly, and this is one I forget all the time, the base class must have a starting style. I can't transition left in the modified state if I don't have left set in the base state.

This code snippet contains a div with transition: none;
On click, override transition property by adding a new class add-transition
On the second click, the same class is removed & no transition.
var elm = document.querySelector('.no-transition');
elm.onclick = () => (
elm.classList.toggle('add-transition')
);
.no-transition {
background-color: aliceblue;
transition: none;
}
.add-transition {
background-color: deepskyblue;
transition: background-color 3s;
}
/* Note: As like other any other CSS property
Specificity or CSS Order can make the difference.
Styles below are for code the snippet to look better. */
.wrapper {
padding: 20px;
margin: 20px;
text-align: center;
cursor: pointer;
border: 1px solid lightgray;
}
<div class="wrapper no-transition">
Run code snippet & click here !!!<hr/>
on load, No transition. <br/>
on click, transition added(bg color). <br/>
on second click, no transtion.
</div>
https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

Related

What is the difference between applying CSS transition property in hover rather than in its normal state?

I'm learning CSS3. Now, what I've seen in w3schools website is that:
CSS
#ID {
transition: transform 3s;
}
#ID:hover {
transform: rotateX(20deg);
}
And what I did is this:
CSS:
#ID:hover {
transform: rotateX(20deg);
transition: transform 3s;
}
Both are working. So, the question is: Can I put both transition and any transformation property in same selector? Or is it not the right way?
SHORT ANSWER:
If you define your transition property in element:hover, it will only get applied in that state.
EXPLANATION:
Whichever CSS properties you define in element:hover will only be applied when the element is in the hover state, whereas whichever CSS properties you define in your element will be applied in both states.
Transition property declared in normal state:
See how the transition always runs when the element's state is changed. When you stop hovering the element it will still make the transition back to its normal state.
CODE SNIPPET:
#ID {
width: 100px;
height: 100px;
margin: 0 auto;
background-color: royalblue;
transition: transform 1s;
}
#ID:hover {
transform: rotateX(60deg);
}
<div id="ID"></div>
Transition property declared in hovered state:
See how the transition breaks when you stop hovering the element and it jumps to its normal state immediately.
CODE SNIPPET:
#ID {
width: 100px;
height: 100px;
margin: 0 auto;
background-color: royalblue;
}
#ID:hover {
transition: transform 1s;
transform: rotateX(60deg);
}
<div id="ID"></div>
The first example is generally correct, as the transition timing is stated on the unaffected state. But that's based on the majority of examples I've seen of how to generate transitions on hover actions.
1st case :
All your transition in the #ID will have a transition of 3s.
When you hover your #ID, your transformation is rotateX(20deg).
2nd case :
When you hover your #ID, you have a transition of 3s.
Overall :
All the transitions from the first css will have a duration of 3s. Then you can apply transitions on your #ID from different places. Whereas in your second case you separate them and if you want to have another transitions triggerd by something else than hover, you will have to specify the duration again.
Both are correct
When a transition is specified for the :hover state, the transition won’t work on mouse out.

Is it possible to smoothly hide html element and remove it using css attribute selector and property display:none?

I am looking for the way to smoothly hide html element and then remove it at all to deny any interaction with hidden elements. I change css property "opacity" from 1 to 0.00001 to do this. The problem is that element hide, but it's still on the screen and user can hover it. Is it possible to remove transparent element using display:none without JavaScript? I tried to do this with CSS attribute selectors, but it does not work.
.element[opacity^=0.00001] {
display:none;
}
http://jsfiddle.net/DkX3L/
Since you're probably already using JavaScript to hide the elements, the best method would be to use that to stop the interaction as well. But since you've asked for a CSS solution, you could use this (IE11+):
.element {
-webkit-transition: 2s;
transition: 2s;
}
.element:hover { /* .element.hidden */
opacity: 0;
pointer-events: none; /* <-- This one */
}
DEMO

Angular, change opacity property when ng-show/hide is included

when I include ng-show display property of css comes into effect but I want to change opacity property.
In the documentation of angular it is written defining your own custom css using important will override the effect but it is not working.
<p ng-show="registrationForm.firstname.$invalid" class="help-block colorred">Enter only alphabets</p>
<style>
.help-block.ng-show{ opacity:1 !important;}
.help-block.ng-hide{opacity:0 !important;}
I am new to angular.js.
Any kind of link or suggestion would be helpful
It is important to note that the animations are applied to the state of either ng-show or ng-hide, e.g. whether an element with ng-hide is currently hidden (resolves to true) or not (resolves to false), the same for an element with ng-show.
So, for an element with ng-hide, change your CSS to:
.help-block.ng-hide-add, .help-block.ng-hide-remove {
-webkit-transition:all linear 0.5s;
-moz-transition:all linear 0.5s;
-o-transition:all linear 0.5s;
transition:all linear 0.5s;
display:block!important;
}
.help-block.ng-hide-add.ng-hide-add-active,
.help-block.ng-hide-remove {
opacity:0;
}
.help-block.ng-hide-add,
.help-block.ng-hide-remove.ng-hide-remove-active {
opacity:1;
}
I had the same problem; ng-hide push a display none. It is possible to put a display on the css class ng-hide.
.help-block.ng-hide {
opacity: 0;
display:block !important;
}
About !important, there is in documentation :
By using !important, the show and hide behavior will work as expected despite any clash between CSS selector specificity.

How to fade in and out a CSS ":after" pseudo element when adding or removing a class

I know there are a lot of other questions on using transitions on CSS pseudo element but after going through a whole bunch of them I still can't get my scenario to work.
Basically, I want to add a class to an element, the class has a :after pseudo element with some content and a background. I'd like a fading effect on the :after element when adding or removing the class.
I've been trying this out in this jsfiddle and the code I have so far it this:
HTML
<div id="divA">Div test</div>
<button id="btnAdd">Add it</button>
<button id="btnRemove">Take Away</button>
CSS
div {
width: 200px;
transition: all .5s linear;
background: red;
}
.test{
background: blue;
}
.test:after{
background: #0c0;
content: "Test";
}
jQuery
$("#btnAdd").click(function() {
$("#divA").addClass("test");
});
$("#btnRemove").click(function() {
$("#divA").removeClass("test");
});
Any help and hints would be most appreciated.
Forking #NilsKaspersson answer to make it work with your requirements.
Transition means from X to Y, you can't expect it to work with newly created attributes.
Then you have to create an initial attribute, and alter it later.
Since you don't want it to be there at the beginning, just use color: transparent; and background: transparent;
Running Demo
Code:
div {
width : 200px;
transition : all .5s linear;
background : red;
}
div:after {
transition : all .5s linear;
background : transparent;
color : transparent;
content : "Test";
}
.test{
background : blue;
}
.test:after{
background : #0c0;
color : black;
}
There are two things going on here.
1.) transition only works when there's something to transition from. Since your :after element is essentially created when the class test is added to it, there's no transition going on.
2.) transition doesn't inherit, so you'll need to declare it once again on the pseudo element.
Here's a quick n' dirty fork of your JSFiddle.
I moved the generic rules for the pseudo element to the classless div and added a transition to it. Then when the class test is added to it, the background changes and it can transition from it's old value.
If you don't want the pseudo element's content to be visible all the time, consider hiding it with opactiy: 0 and transition that to 1, or use the transparent color value for background and/or color.
Edit: Changing answer based on new fiddle.
On most case, CSS transition must apply on already-defined properties.
Additionnaly, the changing of a pseudo :after element content will make the element be removed and re-added, which removes the said properties at the same time.
I have made a demo with animating the text color and background-color while pre-setting the content, so the properties are already present.
CSS :
div {
width: 200px;
transition: all .5s linear;
background: red;
}
div:after {
transition: all .5s linear;
background: red;
color: red;
content: 'Test';
}
.test{
background: blue;
}
.test:after{
background: #0c0;
color: black;
}
Fiddle : http://jsfiddle.net/W5e9Q/10/

Use cases for CSS transitions and CSS animations

As far as I understand, there is no such thing we can implement using css transitions, but we can not to implement using css animations, but not vice versa.
That is, any transition has a css animation equivalent.
For example, this one
.ablock:hover {
position: relative;
-moz-transition-property: background-color, color;
-moz-transition-duration: 1s;
-webkit-transition-property: background-color, color;
-webkit-transition-duration: 1s;
color: red;
background-color:pink;
}
is an equivalent of following:
.ablock:hover {
-moz-animation-duration:1s;
-moz-animation-name:transition;
-webkit-animation-duration:1s;
-webkit-animation-name:transition;
}
#-moz-keyframes transition {
to {
color: red;
background-color: pink;
}
}
#-webkit-keyframes transition {
to {
color: red;
background-color: pink;
}
}
My question is - if we a talking about browser supporting both css transitions and animations, what are use cases for choosing one or another approach?
As for transitions, I can name only one - they have more succinct syntax, we don't have to copy paste huge chucks of code for #-moz-keyframes, #-webkit-keyframes and so on.
As for control from javascript, flexibility and complexity animations are much more appropriate tool (at least, at first glance). So, what are use cases?
UPD:
OK, let me try to list interesting info found in questions.
This one is contributed by Roman Komarov. Say, we have a div and child div. While parent div is hovered, we are transitioning the child element. Once we are taking away the mouse, transition is cancelled. Duration of this cancellation is exactly the time we've already spend for transitioning. Animation is cancelled "immediately". I don't know, nevertheless, how standard are those two behaviours.
Animations can be looped (and there can be keyframes, yeeah).
Transitions can be more flexible and you can easily make transitions to different values and in different circumstances.
While you can emulate some transitions by animations (like you mentioned in your post), the transitions are just more powerful:
You just tell which properties you must animate and in which conditions (using the different selectors)
You can trigger the transition in different ways:
Changing properties in CSS for pseudo-classed :hover, :active etc. (Creating pure CSS UI)
Changing properties in different classes for different purposes.
Changing properties in inline styles: in conjunction with JS it's just more powerful than animations.
With transitions you are able to transition between any value of the defined property, which you want to be transitioned. As an example, you want to transition the color of a link, when it's hovered and active:
a {
color: #000;
transition: color .4s ease;
}
a:hover {
color: #888;
}
a:active {
color: #faa;
}
You are independent, which color you choose.
Now if you want to use the animation style, you have to explicitly set the color value for the animation states. And you are not able to easily animate between the three states: normal, hover and active. You need more complex definitions. I'll try this one with animations:
a {
color: #000;
animation-duration: 0.4s;
animation-fill-mode: forwards;
animation-name: toDefault;
}
a:hover {
animation-duration: 0.4s;
animation-fill-mode: forwards;
animation-name: toHover;
}
a:active {
animation-duration: 0.4s;
animation-fill-mode: forwards;
animation-name: toActive;
}
#keyframes toDefault {
to {
color: #000;
}
}
#keyframes toHover {
to {
color: #888;
}
}
#keyframes toActive {
to {
color: #faa;
}
}
Now this does not include the animation back to the state before. I'm not sure if you can even fetch that.
So in short: with transitions you are able to animate an undefined set of properties and values, whilst keyframe animations are used for well defined animations and/or transitions.

Resources