IMHO there are 3 possible ways to declare an animation for certain HTML elements on the page:
* { transition: all .3s ease; } - Regarding lines of code, file size, and ease of use, I find this the most suiting solution to handle CSS animations on a page. But I do know using the asterisk selector has quite a heavy impact on performance, so this option doesn't seem like the most efficient one. Also, this sometimes causes for unwanted animations on objects where it's not needed.
.animated { transition: all .3 ease; } - Again regarding lines of code, file size and ease of use (in CSS), this looks like the optimal solution. We create a class specifically for animations, and just add this class to all elements we need an animation on. Variations can be made (adjusting the speed etc.) with other classes. But, this does require that every single HTML element you would like to animate should get this class, which means that when for some reason the classname changes one day, all these references should be updated.
.class1, .class2, .class3, ... { transition: all .3s ease; } - Another solution to this problem could be to have one giant selector for every HTML element in need of animation. This could be causing a giant CSS selector, which is not very file size friendly, nor very readable IMO. But, it does have some advantages too - there's only one place to be updated whenever an element needs animation.
So my question is:
What is the most efficient way to handle CSS animations on a HTML page?
Related
I use the following CSS to animate the change in background color for a div:
#availability-button.red-add, #availability-button.red-remove, #availability-button.green-add, #availability-button.green-remove{
transition: background-color 2000ms linear;
}
#availability-button.red, #availability-button.red-add, #availability-button.red-add-active{
background-color: #c21807;
}
#availability-button.green, #availability-button.green-add, #availability-button.green-add-active{
background-color: #68af28;
}
The above works only one way - when you transition from green to red.
What is causing this?
Fiddle
You only need #availability-button.red and #availability-button.green. The animation life-cycle classes like red-add and red-remove are useful if you're using animations, but for transitions can be tricky since you're just transitioning the change in properties between selectors.
In this case, it seems like multiple selectors are matched in the red-* and green-* groups, which causes undefined behavior in how the transition is completed.
Updated Fiddle
I'm learning about transitions in CSS3 via sololearn.com, where the only examples given for using transitions are in conjunction with the :hover selector.
Everything else I can find uses either that or :active with no explanation of what other selectors can be used or why selectors other than these two are not shown as examples.
Is there a way to start transitions without interaction from the user? Or would that require JavaScript?
tl;dr
You can use any selector to initiate a transition, but you don't really need one for it. All you need is to:
set the transition properties on the element
change the value of the property to be transitioned.
You can do both of the above without using CSS selectors, which are nothing more than a handy method available for setting DOM element properties.
initial answer
transitions work with any selector whatsoever. But they are not related to any selector and you don't really need selectors to perform CSS transitions.
All you need for a transition to work is to set the following transition properties:
transition-duration,
transition-delay,
transition-timing-function
transition-property. (has to be animatable for transition to work).
After this, whenever the property named in transition-property changes its value between two animatable values, the change between the initial and the set value happens according to the set transition properties.
This happens regardless of what exactly triggers the change of value for the transitioned property
It could:
change because a particular CSS selector (you defined) starts or stops applying (matching the element);
be changed directly using JavaScript.
Or, of course, by a combination of the two (i.e. use JavaScript to apply a class, which changes the value of the property being transitioned)
So, in effect, the answer to your question is: transitions work with any selector but they also work without one. They work based on DOM element property values, regardless of any selector.
A common way to demonstrate a transition is using :hover state because all one needs to do to switch between selectors (which is to control / demonstrate / observe the transition) is. well,... hover!
On:
For example is there a way to start transitions without interaction from the user?
Of course there is! A very basic example is to add a class on <body> when all page resources have finished loading.
When <body> element is created it doesn't have the class and when all resources have finished loading, the Window's onload event triggers. We can use this event to add the class. If a transition is properly defined on body and the transitioned property changes because a stronger selector now applies on the element, the transition will happen. Without any user interaction.
See it working:
window.onload = function() {
document.querySelector('body').classList.add('loaded')
}
body {
background-color: #fff;
transition: background-color 1s linear;
}
.loaded { background-color: #212121;}
You could also set a recursive function that toggles the state of an element and calls itself after a set amount of time, effectively toggling the state back after the set time, in a continuous cycle:
For the above example this would mean:
window.onload = toggleBodyClass;
function toggleBodyClass() {
document.querySelector('body').classList.toggle('loaded');
setTimeout(toggleBodyClass, 1234);
}
body {
background-color: #fff;
transition: background-color 1s linear;
}
.loaded { background-color: #212121;}
If the question is: "Can a selector start/stop applying without the use of JavaScript and/or user interaction?" It really translates to:
"Are there transitions triggered by something else than what usually triggers a transition?", with possible answers varying from:
"Why do you want to know?" to "Is there web browsing without JavaScript and/or user interaction?"
Transitions are, as Paulie_D says, changes in state. What this "state" refers to, is simply the value of any style property (that can be animated, anyway). Even the spec describes it the same way:
Normally when the value of a CSS property changes, the rendered result is instantly updated, with the affected elements immediately changing from the old property value to the new property value. This section describes a way to specify transitions using new CSS properties. These properties are used to animate smoothly from the old state to the new state over time.
This means that you don't actually need a selector to start transitions. Styles can be changed via CSS, JavaScript, or the inline style attribute. All of these are subject to transitions, because they all modify style property values. Selectors just happen to be the most common way of doing it because selectors and declaration blocks are the two fundamental components that make up style rules, themselves the building blocks of CSS.
Most other ways of using transitions with or without user interaction do in fact involve JavaScript because CSS doesn't support much state change without requiring user interaction (outside of animations, which are a different beast from transitions), but that doesn't mean that JavaScript is inherently required for transitions to work, because transitions are about state change, regardless of how that state change is invoked (JS or not).
Most tutorials use :hover and :active to demonstrate transitions simply because user interaction is the easiest and most intuitive way for readers to see transitions in action, and to learn what it means for an element to change state (albeit a different kind of state, but the principle is the same). It's also by far the most common use case for transitions: animating changes in state in response to user interaction.
But you don't actually need to change property values with a user interaction pseudo-class in order for transitions to work. You can change them with any selector, even if user interaction is handled by a different element (and that element doesn't have to start transitions using :hover or :active either)...
label {
transition: color 1s linear;
}
:checked + label {
color: #f00;
}
<p><input type=checkbox id=check><label for=check>Label</label>
... or by the page itself...
h1 {
transition: color 1s linear;
}
:target {
color: #f00;
}
<p><a href=#sec1>Section 1</a> <a href=#sec2>Section 2</a>
<h1 id=sec1>Section 1</h1>
<h1 id=sec2>Section 2</h1>
Once you add JavaScript into the mix, you can set property values directly (i.e. not use a selector)...
setTimeout(function() {
document.querySelector('p').style.color = '#f00';
}, 1000);
p {
transition: color 1s linear;
}
<p>Wait for it...
... change an element's class, ID or other attribute...
setTimeout(function() {
document.querySelector('p.foo').className = 'bar';
}, 1000);
setTimeout(function() {
document.getElementById('foo').id = 'bar';
}, 2000);
setTimeout(function() {
document.querySelector('p[data-attr]').dataset.attr = 'bar';
}, 3000);
p {
transition: color 1s linear;
}
p.bar { color: #f00; }
p#bar { color: #090; }
p[data-attr=bar] { color: #00f; }
<p class=foo>Wait for it...
<p id=foo>Wait for it...
<p data-attr=foo>Wait for it...
... or even move elements around in the DOM tree (although this does have limitations — notice that the Foo item fails to start its transition because it's getting detached before being reattached, while the Bar item is able to start its transition once it notices it's now first because it never leaves the DOM tree)...
setTimeout(function() {
var ul = document.querySelector('ul');
ul.appendChild(ul.firstChild);
}, 1000);
li {
transition: color 1s linear;
}
li:first-child { color: #f00; }
<ul><li>Foo<li>Bar</ul>
... and be able to start transitions all the same. Notice that all the JavaScript examples start transitions automatically, no user interaction required.
So, in conclusion, transitions are about state change, and said state change pertains to changes in style property values. These are independent of selectors or JavaScript, although selectors are a fundamental part of CSS and you do need JavaScript for most things.
so this is just a sample of what I am trying to do. I want to use Angularjs to animate the opacity of the element on hover but I can't get it to do anything. I have been reading the documentation but I can't seem to figure out what is wrong. Any help is appreciated. See example below.
http://jsbin.com/AdIXIKU/1/edit
Thank you in advance
You do not need to use angular if you want transitions on hover:
.reveal-animation {
// add the vendor prefixed versions as well
transition: all 1s;
}
.reveal-animation:hover {
opacity: 0.5;
}
Should be sufficient.
If you want to animate the entering and leaving of elements, you'll need to use some more angular constructs to ensure that elements do enter and leave like this: http://jsbin.com/iwudOjAW/1/edit (contains both hover and enter/leave effects).
I have used the ng-route module and made the ng-view element enter and leave by changing the hash of the URL.
I'm new to HTML/CSS and I just need some educating on the basics. I have researched how to do what I'm asking but none of the answers on the internet work for my project, I don't know if this is because I'm working on Tumblr or not.
Basically this is the code. I want #notesbox to fade in when the mouse hovers over #post.
This is the CSS used for the two Div's:
#post{
position: relative;
width:250px;
height: 250px;
overflow:hidden;
float:left;
font-family: "helvetica";
opacity: 1;
transition: opacity .25s ease-in-out;
-moz-transition: opacity .25s ease-in-out;
-webkit-transition: opacity .25s ease-in-out;
}
and
#notesbox {
color: white;
position: absolute;
text-align: center;
float: center;
width: 100%;
height:20px;
background-color: black;
opacity: 0;
-webkit-transition: all ease 1s;
-moz-transition: all ease 1s;
-o-transition: all ease 1s;
-ms-transition: all ease 1s;
transition: all ease 1s;
}
Thankyou for any help and sorry for my ignorance, as I've said I am new so go easy on me!
EDIT: Here is the HTML for it.
<center>
<div id = "postholder">
{block:Posts}
<div id="cent">
</div>
<div id="post">
{block:Title}{Title}{/block:Title}
{block:Text}{Body}{/block:Text}
{block:Photo}
<div id = "photo">
<div id = "notesbox">
<div id = "notes">
REBLOGGED FROM
<div id = "reblogged">
{block:RebloggedFrom} {ReblogParentName} {/block:RebloggedFrom}
</div>
</div>
</div>
<img class = "default" img src="{PhotoURL-500}" width="250"/>
</div>
{/block:Photo}
The {/block:Post} comes later on in the code.
As said on some comments, your html would help here a lot, but I think I can help you overcome your issue anyway.
My solution uses javascript. There are many stuff you can do with javascript, and it's not that hard to learn, i suggest that if you are building a website you learn it.
On your html, add a "onmouseover" event to #post.
<div id="post" onmouseover="someFunction()"></div>
The code above means, when a mouse is over the division (or whatever it is), the function "someFunction()" (that's just a made up name) from the script will be triggered.
this is the script (you can add it in somewhere between your head tags if you don't have many scripts. Usually I use a separate javascript file, but it's not necessary).
<script language="JavaScript" type="text/javascript">
function someFunction(){
document.getElementById("notesbox").style.opacity="0.25";
document.getElementById("notesbox").style.filter="alpha(opacity=25)";
}
</script>
What it does is, when the function 'someFunction()' is triggered, it searches the document for the element with the 'id' "notesbox" and changes it's css (style) to include "opacity:0.25;"
The second row does the same thing and changes to css to include "filter:alpha(opacity=25);" Both of the rows are needed for the code to work on every browser.
Hope I answered your question. Feel free to ask if something isn't clear.
EDIT: Answer for your comment.
There are many divisions with the same 'Id', that makes a problem when working with javascript. The script above, which you have entered, finds the FIRST element with the 'Id' "notesbox" ONLY.
I have 2 solutions for that- one is to change the 'Id's to be different for each division, if you wish "notesbox1", "notesbox2" etc. Then you should have many functions, one for each "notesbox". Each row in the javascript will have to change accordingly:
...getElementById("notesbox1")...
CSS as well:
#notesbox1{}
#notesbox2{}
I like the second idea more. The second one uses 'class'es instead of 'id's. Classes are better than divisions when it comes to having the same css/javascript for many elements. This is much more complicated than just using many function for each different division and changing the IDs but it works better and faster. After starting to explain the second idea, I found out that I wrote a lot and didn't even get to the half. If you have the time and will to learn a little javascript, I'd love to help you out, but before putting so much effort into it, I want to know that you will actually use it.
EDIT: Idea #2
I do believe there are easier ways to do it, but as I said in the comment, I'm kind of an amateur myself. Either way, that will teach you a lot.
First, change your division from:
<div id="notesbox"></div>
To
<div class="notesbox"></div>
Then, your css, from:
#notesbox {}
To:
.notesbox {} /* On CSS, the '.' marks a class and the '#' marks an id. */
Then your javascript has to be changed as well.
That was the row earlier:
document.getElementById("notesbox").style.opacity="0.25";
It has to be changed accordingly to find class insted of an ID.
document.getElementsByClassName("notesbox")[0].style.opacity="0.25";
There are a few differences to notice.
when javascript gets a class, the word "Id" has to change to "ClassName".
When javascript gets a class, the word "Element" has to change to "Elements"- This even indicates what I said before: classes are for more than 1 element.
After the '("notesbox") comes a [number], a '0' in the top example. The [0] means that the element chosen will be the FIRST element with the ClassName("notesbox"). Javascript starts counting from 0, not from 1- therefore the second object will be with [1], third with [2] and so on.
After all that is understood, you should make a 'variable' in javascript to get the picture number. The code will make that if you hover over a picture which will be given the number 1, the first element in "notesbox" class will appear (the element ("notesbox")[0])
var pic_number;
Now make functions.
function change_pic_number_1()
{
pic_number=1;
}
The above functions, when triggered, changes pic_number to 1. I will assume there are 2 pics only, after you get the hang of it you can add more as needed.
function change_pic_number_2()
{
pic_number=2;
}
The function that makes the 'notesbox' be shown will use a 'switch' in it. A switch is a method to check a variable's content and act by it. It's close to 'if' but much more useful when there are many options. So:
function showNotesBox(){
switch (pic_number){
case 1:
document.getElementsByClassName("notesbox")[0].style.opacity="0.25";
break;
case 2:
document.getElementsByClassName("notesbox")[1].style.opacity="0.25";
break;
}
}
the code above means: In 'case' that the var 'pic_number' equals 1, excute the following things until 'break'. In 'case' that the var 'pic_number' equals 2, execute the following things until 'break'. You can see in case 2, the [0] changes to [1].
In the html:
<div class="notesbox" onmouseover="change_pic_number_1(); showNotesBox()"></div> //This only makes that when you hover over the notesbox it will be triggered. You need to add the trigger to the photo as well.
So what it does is, when you mouse over the division, first the function "change_pic_number_1()" will be triggered, then "showNotesBox()". Go over it your mind, and you'll see that this will change the opacity of the division to '0.25'.
If you understood it already (that's very unlikely) and have done it, you'll encounter a problem in which after you hover over the division, it will stay like that. To encounter that we need another var, switch and function. But first understand the part above.
Again, ask me what you find not clear. You can also read about switch http://www.w3schools.com/js/js_switch.asp to understand it better. Read what I wrote a couple of times, until you think you understood what you can from it.
I've just noticed that Webkit now has some support regarding the CSS Values and Units Module Level spec. And I was wondering if anyone knows if there is a way to reference another CSS selectors (or DOM style) property from a CSS selector?
I'm expecting something like this to be the answer here. Which I know is most likely the case for current browser implementations; but please keep reading...
For instance, in the case where an animation might resize an element (NOTE the ${.element2.width} is fictitious syntax):
<style type="text/css">
.element1 {
.width: /*-webkit-,-o-,-moz-*/calc(80% - ${.element2.width});
}
.element2 {
.width: 100px;
}
.element2:hover {
width: 200px;
transition: all 0.4s ease-in-out;
}
</style>
In this case I would expect the .element1's width to be re-evaluated based off the transition triggered from the hover events on .element2.
I realize that the aforementioned spec. is only a working draft but perhaps the syntax for referring to such a 'referential selector property' is defined within another spec. which I'm yet to discover? Or simply just not a case for concern (thanks to an overlooked work around)?
I added an answer to the question you linked: https://stackoverflow.com/a/11071806/137626
You can use the same declaration block with as many selectors as you want by grouping them (selectors are separated by commas)
You can't reuse the same declaration block later with a different CSS selector without rewriting the whole declaration block preceded by this selector or using a preprocessor/macro that'll do that for you. Or add it to the existing declaration block as above
Now with your example of an element resized by CSS itself: you could use CSS3 Media Queries and its #media rules containing as many declaration blocks as you want. These media queries would adapt to the width of viewport here.
Mixing expanding elements via animation and media queries that would've the reverse effect will be very soon very complicated (and I'll wonder what content you're playing with); if you want to Keep It Simple, then JS is the way to go. There are variables, loops, events ;) and you can start a CSS3 animation by adding or removing a single class from an element (or whatever CSS selector).
CSS3 won't replace JS (and you shouldn't use JS to style HTML as JS isn't activated or existing everywhere and there's already a nice fallback named CSS).
Other than using a pre-compiler such as sass/scss or less, I believe all you can do is wait or hard-code it.