Rotating images based on CSS nth-child - javascript

I was able to write a JavaScript carousel and thought it might be more compact to use CSS transitions with nth-child selectors like this:
img {
transition: all 1s linear; /* or corresponding vendor prefixes */
position:absolute;
}
img:nth-child(1) {
top: 0%;
left: 0%;
}
img:nth-child(2) {
top: 0%;
left: 50%;
}
/*and so on...*/
The items would then be rotated by appending the first child or prepending the last child of the container:
parent.appendChild(parent.children[0]);
This approach works well for all but the appended element. It is removed entirely and then reattached, so it ends up in the right spot but does not use the transition effect. Is there a way to use CSS transitions even when relocating an element in the DOM?
jsFiddle Demo - Click the document to advance the images.

What you can do is you can add or remove a class name from an element. Example you have a div element. And its class value is class="item". If you add another class name which has animation to that element's class name list, then that div element will show that animation at that moment immediately.
eg. div.className += " animatedClass";

A very interesting issue indeed. And here is the solution I came up with. Adds some markup and some CSS, but accomplishes it while still using nth-child. Honestly, I may work on this some more later and see if I can't come up with a more elegant solution, but for now, I forked off a jsFiddle.
The core of it is switching a class on a wrapper div, and using that to rotate through the styles.
However, as far as your actual question of can you animate an append image, you can, but not in the way you're thinking here. It would be an initial append animation, which would mean when the page first loaded it will animate. You can do this using #keyframes, and set it so that the image you want slides into place from a starting position of where it would be. But, again, this will happen on first load as well. You can fake it by 'spinning into place' for the first load. So, have all images spin once on load.

I ended up using a data-* attribute and selector. It is a little more verbose than nth-child, but has the advantage of working. It is also cleaner than parsing through class lists.
Each element has a data-order attribute, which can be assigned with HTML or JavaScript:
<img src="http://placekitten.com/203/203" data-order=0 />
Replace nth-child with the attribute selector:
img[data-order="1"] {
top: 0%;
left: 50%;
}
When rotating, increment the order in the dataset. This seems to update the attribute, even though we are modifying the property:
var forEach = [].forEach,
nodes = document.body.children,
length = nodes.length;
//On rotate:
forEach.call(nodes, function(node) {
node.dataset.order++;
node.dataset.order %= length;
});
Here is the final result.

Related

Adding a Class vs Removing a Class to Show Elements on a Web Page

Current Design
In a website I am designing I have a number of elements that initially will appear hidden, until the user needs to see them. For example they have scrolled to a desired height on the page.
Currently this works by JavaScript adding a class line.classList.add('show-header-line');
Which in CSS will be defined next to the main styling for the element. This show variant of the class will only contain attributes required to make the element visible opacity: 1. The main styling for the element will contain the opposite attributes required to hide the element initially opacity: 0.
The Alternative
Of course this could work the other way around. With a class designed to hide the element initially being set in the html, then to be removed when required by JavaScript.
HTML
<div class="header-line hide-header-line" />
JS
line.classList.remove('hide-header-line');
Note
Of course I could add and remove styles directly (without the need for extra classes) in the JavaScript, but this seems much worse. Regarding a lack of separation of concerns.
Question
My current approach means the resulting rendered DOM is littered with elements that have main style class and a show class. The alternative means my html file is littered with elements with a main style class and a hide class. Which is considered better practice? Is there another cleaner way I could be doing this?
I would strongly suggest against using opacity:0 for this, rather use display: none. The reason being that an element with opacity: 0 still occupies space in the markup, whereas display: none will add the element to the DOM, but it won't be rendered in the markup (if that makes sense).
Here is a more detailed explanation
Also, an example using the scroll pass certain point you said, this is how I would do it, note code is untested.
window.addEventListener('scroll', function(){
document.querySelector('#navigation').classList[this.scrollTop > 200 ? 'add' : 'remove']('fixed-nav');
});
css
.fixed-nav {
width: 100%;
position: fixed;
top: 0;
left: 0;
}

FadeIn animation using CSS3 in Javascript

As jQuery.fadeIn is not very smooth on mobile devices I try to use CSS but it doesn't work as expected. How to create a smooth CSS animation using Javascript?
In general this is what I'm trying:
$('div')
.css('opacity', 0) // at first, set it transparent
.css('display', 'block') // make it appear
.css('transition', 'opacity 1000ms linear') // set a transition
.css('opacity', 1); // let it fade in
https://jsfiddle.net/8xa89y04/
EDIT1:
I'm not searching a solution using static CSS classes. The point is: I need to set this dynamically in Javascript code - a replacement for jQuerys fadeIn() for example.
Your logic isn't quite right. Firstly you cannot animate display, so to achieve what you require the element has to always be rendered in the DOM (ie. anything but display: none). Secondly, the transition property should be placed within the CSS styling itself. Finally you can make this much more simple by setting all the rules in CSS classes and just turning the class on/off. Try this:
div {
position: absolute;
width: 100px;
height: 100px;
background-color: black;
opacity: 0;
transition: opacity 1000ms linear;
}
.foo {
opacity: 1;
}
$('div').addClass('foo');
Working example
Use this code.
CSS
div {
width: 100px;
height: 100px;
background-color: black;
transition:opacity 2s;
}
JavaScript
$('div').hover(function(){
$(this).css('opacity','0');
})
Without using CSS properly, you are going the long way about it. You'll need to emulate what you would normally do in CSS, using JavaScript, so you'll be setting all your CSS properties, transitions etc, then applying them with js.
I can't personally see any benefit in doing this. Using actual CSS would be cleaner, more efficient, more maintainable, and simply a plain better solution to what you need.
I think this is what you are looking for.
$('div').css({"display":"block", "opacity":"0"}) //Make div visible and opacity as "0"
$('div').animate({opacity :1}, 1000); //Animate div to opacity "1"
Take a look at this Demo
Found the cause here: CSS transitions do not work when assigned trough JavaScript
To give this attention I need to give the browser some time - or better: a working slot to activate the transition as the time seems not to be a problem.
The following code cuts the process in two by using setTimeout()... and it works!
var div = $('div');
// first process
div
.css('opacity', 0) // initial opacity
.css('display', 'block') // make it appear (but still transparent)
.css('transition', 'opacity 1s linear'); // set up a transition for opacity
// break - start the transition in a new "thread" by using setTimeout()
window.setTimeout(function(){
div.css('opacity', 1); // start fade in
}, 1); // on my desktop browser only 1ms is enough but this
// may depend on the device performance
// maybe we need a bigger timeout on mobile devices

Element disappears when animating relative wrapper width with jQuery

I have a strange problem that happens when I animate the width of a relative positioned element which contains an absolute element. While the animation is running, inner element dissapears. When the animation is complete, inner element shows.
Here is the demo:
http://jsfiddle.net/R4Cj5/
When I remove parent element position: relative then inner element is shown while animation is running, but then I can't position it relatively to the parent.
Basically box with the % should be visible al the time
Does anyone have any idea whats happening here?
FIXED : I just added overflow: visible !important; to relative
positioned element
working example : http://jsfiddle.net/R4Cj5/26/
I think it might be a jQuery animate thing. I would love to see a working solution without any hacks, but for now here is something you might find useful! :-)
I basically added another function in the animate, upon completion it will animate the 90% to hover above the progress-bar
complete: function() {
$percent.animate({top: "-26px"})
}
in this use-case scenario, you can also remove/comment out the top: -26px from .progressbar .percent in the stylesheet. Also I added height: 20px; to the styling for .progressbar .percentage so you could see the % change as it glides across.

How to insert an html element before another without shifting the originals position

I would like to be able to insert an element that a user can navigate (left) to without disturbing what the user currently sees. that is, the new element will be inserted offscreen, to the left, but the currently "focused" element (and the other visible ones) shouldn't be seen to move.
Currently I am doing this using insertbefore, measuring the clientWidth of the new element and subtracting that from the margin of the container element. However, clientWidth is expensive to get, and this method is proving problematic when I add transitions. Is there a cleverer way to do this? I would have thought it's a fairly common problem - insert an element before another without shifting everything else.
You could use some CSS to achieve this. Insert a wrapping div with no height, but overflow: visible, insert the elements you want inside this div:
.wrapper {
height: 0;
overflow: visible;
}
.wrapper div {
margin-left: 100%;
}

CSS for dynamic inserted elements

Currently I'm working on a website where I'd like to show some toolstips for specific DIV elements. My weapon of choice is jQuery Tools.
So when I use $(".toolTipMe").tooltip(); it works quite nice. As soon as I hover the element a new DIV appears in the DOM:
<div class="tooltip" style="display: none; position: absolute; top: 313.65px; left: 798.5px;">foo</div>
However the design is done by our very own css-monster (you should this this guy!) and he's using a a lot of z-indexes so the .tooltip-DIV is behind the other elements.
Now the question:
The following code in our .css File is not having any effect:
.tooltip{
z-index: 9001;
}
In fact the attribute is not even showing up when debugging the website. But the following will work:
$(".toolTipMe").tooltip({
onShow: function(){
$(this).css("z-index","9001");
}
});
I'm not sure how CSS Rules are applied for dynamic inserted DOM Elements but what I really detest in the current workaround is the mixture of functionality and style. Any chance to clean up this mess? :C
I am not familiar with jquery tools, but if your z-index is not working you must need a !important tag or making it position:relative or position:absolute
In jquery tools tooltip you need to specify the z-index inside the tooltip constructor like:
$(".toolTipMe").tooltip({ z-index: '9001'});
I'm not sure if it is z-index or zindex.. check it out

Categories