I have a slider with 3 images and 3 buttons which change the current image 'src' attribute (and hence change the current image), but now I want to add a smooth transition when I change the image and I would like to get this using css transitions.
So when I click on any bullet I need the current image fades out and then the new image fades in. how can I do this?
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
for (i = 0; i < listItemContainer.children.length; i++){
(function(index){
listItemContainer.children[i].onclick = function(){
bulletNumber = index;
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
}
})(i);
};
body{
text-align:center;
}
#carousel-index{
margin:0;
padding:0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
Here is a CODEPEN
PD: I want to do this without Jquery.
CodePen sample
I've added some css transitions to the css
div#image-container {
opacity:1;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
transition: opacity 1s;
}
div#image-container.fade {
opacity:0;
}
and some function to handle the event:
var image = document.getElementById('image-container');
if(image.className === 'fade'){
image.className = '';
setTimeout(function(){
image.className = 'fade';
},1000)
}else{
image.className = 'fade';
setTimeout(function(){
image.className = '';
},1000)
}
setTimeout(function(){
bulletNumber = index;
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
},1000);
use CSS3 animation with add class in javascript
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
for (i = 0; i < listItemContainer.children.length; i++) {
(function(index) {
listItemContainer.children[i].onclick = function() {
bulletNumber = index;
imageChanger[0].className = "hide";
setTimeout(function(){
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber + 1) + '.png');
},501);
setTimeout(function(){
imageChanger[0].className = "show";
}, 1001);
}
})(i);
};
body {
text-align: center;
}
#carousel-index {
margin: 0;
padding: 0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
#image-container img.show {
animation: show .5s;
animation-fill-mode: both;
}
#keyframes show {
from {
transform:scale(0.7);
opacity:0
}
to {
transform: scale(1);
opacity:1
}
}
#image-container img.hide {
animation: hide .5s;
animation-fill-mode: both;
}
#keyframes hide {
from {
transform:scale(1);
opacity:1
}
to {
transform:scale(0.7);
opacity:0
}
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png" />
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
You can use CSS transition, and i guess that desired property is opacity.
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
imageChanger[0].classList.add('fadeIn');
for (i = 0; i < listItemContainer.children.length; i++){
(function(index){
listItemContainer.children[i].onclick = function(){
bulletNumber = index;
imageChanger[0].classList.remove('fadeIn');
setTimeout(function(){
imageChanger[0].classList.add('fadeIn');
} , 100);
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
}
})(i);
};
body{
text-align:center;
}
#carousel-index{
margin:0;
padding:0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
img {
opacity:0;
}
img.fadeIn {
opacity:1;
transition:opacity 0.5s ease;
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
Start image opacity should be 0, of course:
img {
opacity:0;
}
img.fadeIn {
opacity:1;
transition:opacity 0.5s ease;
}
And then, on click (remove added class -> set opacity to 0 again), and add it again. You can play with values to get desired effect.
EDIT: fadeOut/fadeIn... it was little tricky, because of one container, and img src changing, but additional timeout solves it:
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
imageChanger[0].classList.add('fadeIn');
for (i = 0; i < listItemContainer.children.length; i++){
(function(index){
listItemContainer.children[i].onclick = function(){
bulletNumber = index;
imageChanger[0].classList.remove('fadeIn');
imageChanger[0].classList.add('fadeOut');
setTimeout(function(){
imageChanger[0].classList.add('fadeIn');
imageChanger[0].classList.remove('fadeOut');
} , 1000);
setTimeout(function(){
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
} , 1000);
}
})(i);
};
body{
text-align:center;
}
#carousel-index{
margin:0;
padding:0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
img {
opacity:0;
}
img.fadeIn {
opacity:1;
transition:opacity 0.5s ease;
}
img.fadeOut {
opacity:0;
transition:opacity 0.5s ease;
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
P.S. Images should be probably preloaded, in order to all work fine on first load.
One more alternative, JS based, didn't change HTML or CSS (explanation as comments in the code):
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img')[0];
var newSrc, fadeDelta=-0.01; //don't change 'delta', change 'fadeoutDelay' and 'fadeinDelay'
(function initImageChanger(i,count){
imageChanger.style.opacity = 1; //set opacity in JS, otherwise the value returns "" (empty)
listItemContainer.children[i].onclick = function(){
var fadeoutDelay=5, fadeinDelay=15, opacity=parseFloat(imageChanger.style.opacity); //change delays to alter fade-speed
function changeSrc(){
var src = imageChanger.getAttribute('src');
var ext = src.substring(src.lastIndexOf('.')); //store extension
src = src.substring(0,src.lastIndexOf('_')+1); //store source up to the identifying number
return src+i+ext; //combine parts into full source
}
function fade(delay){
imageChanger.style.opacity = (opacity+=fadeDelta);
if (fadeDelta<0 && opacity<=0){ //fade-out complete
imageChanger.setAttribute('src',newSrc);
fadeDelta*=-1, delay=fadeinDelay; //invert fade-direction
} else if (fadeDelta>0 && opacity>=1){newSrc=null, fadeDelta*=-1; return;} //fade-in complete, stop function
setTimeout(function(){fade(delay);},delay);
}
//start fade, but only if image isn't already fading, otherwise only change source (and reset)
if (changeSrc() != imageChanger.getAttribute('src')){
newSrc=changeSrc();
if (opacity==0 || opacity==1){fade(fadeoutDelay);}
else if (fadeDelta>0){fadeDelta *= -1;} //reset fade for new source
}
};
if (++i < count){initImageChanger(i,count);} //iterate to next element
})(0,listItemContainer.children.length); //supply start-arguments
body {text-align:center;}
#image-container img {width:auto; height:150px;}
#carousel-index {margin:0; padding:0;}
#carousel-index li {display:inline-block; width:2em; height:2em; border-radius:100%; background-color:#666; cursor:pointer;}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index"><li></li><li></li><li></li></ul>
</div>
codepen: http://codepen.io/anon/pen/xgwBre?editors=0010
It's not a perfect solution, but here's one way of doing it without jQuery:
First create a new function:
function fadeChange(element) {
var op = 0.1;
var timer = setInterval(function () {
if (op >= 1){
clearInterval(timer);
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1;
}, 10);
}
Then call that function when setting the new image:
fadeChange(imageChanger[0]);
This is demonstrated through the updated codepen here.
It's a bit clunky, but does fade the images. You may want to consider using a single image for the monitor, and then simply changing the contents of the monitor through this method.
Related
i made a blackjack game , i want to make the dealer cards flip from back to front everything works expect that when the shown cards appear they apper one under another .. how can i make them appear
in line ??
function TurnDealerCards()
{
DealerCards.innerHTML = "";
for (var i = 0; i < DealerArray.length; i++) {
var Dealercard = document.createElement('img');
var random = Math.floor((Math.random() * 10));
Dealercard.setAttribute("width", 50);
Dealercard.setAttribute("src", (allCards[random])[(DealerArray[i])]);
DealerCards.appendChild(Dealercard);
}
DealerCards.className = 'myDIV';
}
.myDIV {
display:inline-block;
border: 0px;
width: 50px;
background-color:transparent;
color: transparent;
animation: mymove 1s ;
}
#keyframes mymove {
50% {
transform: rotateY(180deg);
}
}
<table border="0" width="100%" height="100%" style="text-align: center">
<tr><th id="NewGame" onclick="MakeAnewGame();" style="float:left">
<img src="media/cards/new game.png" width="100" /><label>change table color</label><input id="changeBGC" type="button" onclick="changeBackground();">
</th></tr>
<tr><td style="height:100pt;width:100%;font-size:100pt;color:white"><div id="dealer"></div></td></tr>
Use display:flex to the wrap (myDiv) and use animation to each img
In js set animation-delay and increase the time one by one
var DealerCards=document.getElementById("cards");
DealerCards.innerHTML = "";
var DealerArray=[1,1,1];
for (var i = 0; i < DealerArray.length; i++) {
var Dealercard = document.createElement('img');
var random = Math.floor((Math.random() * 10));
Dealercard.setAttribute("width", 50);
Dealercard.setAttribute("src","jj");
Dealercard.style.animationDelay=(i + 0.5 )+'s';
DealerCards.appendChild(Dealercard);
}
DealerCards.className = 'myDIV';
.myDIV img{
border: 0px;
width: 50px;
animation: mymove 1s;
background-color:transparent;
color: transparent;
}
myDiv {
display:flex;
}
#keyframes mymove {
50% {
transform: rotateY(180deg);
}
}
<div id="cards"></div>
I am appending output to a ul element using li elements. I am able to generate the output as desired but I have no idea on how to use transitions and transform, as Javascript is creating those li elements.
I want to transform li elements as they appear from Javascript in the DOM.
Vanilla Javascript is preferred.
What I have, HTML:
<div class="add">
<input type="text" id="addTodoTextInput" placeholder="Add Task Here" onkeydown="handlers.addTodo()" > <!-- input text field to add <li> -->
<button onclick="search()"> <img src="add.png" height="20" width="20" alt=""> </button> <!-- button to add li -->
</div>
<ul class="result">
<!-- output generated with JavaScript will be appended here -->
</ul>
CSS:
li{
margin: 0 5px 0 5px;
padding: 5px;
font-family: cursive;
color: #006cff;
font-size: 1.3em;
background: rgba(43, 229, 43, 0.28);
transition: 2s;
}
li:hover{
transform: translateX(50px);
}
JavaScript:
var handlers = {
addTodo: function(){
var addToDoInput = document.getElementById('addTodoTextInput');
todoList.addToDo(addToDoInput.value);
addToDoInput.value = "";
view.displayTodo();
}
}
var view = {
displayTodo: function() {
var todosUl = document.querySelector('ul');
todosUl.innerHTML = '';
todoList.itemList.forEach(function(todo,position) {
var todosLi = document.createElement('li');
var todoTextWithCompletion = "";
if(todo.completed === true) {
todosLi.style.textDecoration = "line-through";
}
todosLi.id = position;
todosLi.textContent = todo.todoText;
todosLi.appendChild(this.createDeleteButton());
todosLi.appendChild(this.createToggleButton());
todosUl.appendChild(todosLi);
}, this);
}
}
function insertLI(EL_target, content) {
var EL_li = document.createElement("li");
var NODE_content = document.createTextNode(content);
EL_li.appendChild(NODE_content);
EL_target.appendChild(EL_li);
// Register a live classList change in order to trigger CSS transition
setTimeout(function() {
EL_li.classList.add("added");
}, 0);
}
var EL_ul = document.getElementById("myUL");
var i = 0;
document.getElementById("add").addEventListener("click", function() {
insertLI(EL_ul, "I'm number"+ i++);
})
ul li{
opacity: 0; /* initially set opacity to 0 */
}
.added{
transition: opacity 1s, color 3s; /* transition!! yey */
opacity:1;
color: fuchsia;
}
<button id=add>ADD <li></button>
<ul id=myUL></ul>
I would recommend simple solution with CSS animations. You will need a little change to your code to insert next item after animation of the previous completed. For this replace your for loop with this code:
(function insertNext (position) {
var todosLi = document.createElement('li');
var todo = todoList.itemList[position];
var todoTextWithCompletion = "";
if (todo.completed === true) {
todosLi.style.textDecoration = "line-through";
}
todosLi.id = position;
todosLi.textContent = todo.todoText;
todosLi.appendChild(this.createDeleteButton());
todosLi.appendChild(this.createToggleButton());
todosLi.addEventListener('animationend', function() {
if (todoList.itemList.length > position + 1) {
insertNext(position + 1)
}
})
todosUl.appendChild(todosLi);
}.bind(this))(0)
Then all you need to do is add CSS animation into your styles:
li {
/* ... */
animation: appear 1s forwards;
}
#keyframes appear {
from {
opacity: 0; background: #eee;
}
to {
opacity: 1; background: coral;
}
}
Demo: https://jsfiddle.net/Lf6t8sre/
I am doing the following but it is fading in/out the path all at once and not one after the other
var periodClass = jQuery(this).parent().attr("class");
jQuery("svg path").each(function(i) {
var elem = jQuery(this);
if (elem.hasClass(periodClass)) {
elem.addClass('active').css('transition-delay', i/5000 + 's');
} else {
elem.removeClass('active').css('transition-delay', i/5000 + 's');
}
});
CSS
path {
opacity: 0;
transition-property: opacity;
transition-duration: 0.7s;
}
path.active {
opacity: 1;
transition-property: opacity;
transition-duration: 0.7s;
}
Also tried this but still, all at once
var periodClass = jQuery(this).parent().attr("class");
jQuery("svg path").each(function(i) {
var elem = jQuery(this);
if (elem.hasClass(periodClass)) {
elem.addClass('active');
elem.each(function(index) {
$(this).delay(400*index).fadeIn(300);
});
} else {
elem.removeClass('active');
elem.each(function(index) {
$(this).delay(400*index).fadeOut(300);
});
}
});
You need to use setTimeout();
here's an example
$(document).ready(function(){
$('div').each(function(i){
var ThisIt = $(this);
setTimeout(function(){
ThisIt.addClass('active');
} , i * 1000);
});
});
div{
margin: 20px;
padding: 10px;
font-size: 30px;
text-align: center;
background : #eee;
display: none;
}
.active{
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
Well, one way to do it:
var pnum = 0;
var $paths = $("svg path");
nextFade();
function nextFade () {
$paths.eq(pnum).fadeOut( "slow", function() {
// Animation complete. Increase counter Call next fade.
pnum++;
if(pnum < $paths.length){
nextFade();
}
});
}
I don't know why people's are not answering this question.I'm making a horizontal infinite loop slider. What approach i'm using is making a ul container which has 3 images, for example if there are 3 images then clone the first image and place it to the end of the slider, same with last image make clone and place it before the first image. So now total images are 5. Default slider translation always start from first image not from clone one. Here is an example. What i'm facing is, I want to reset the slider after slider comes to the last clone image with same continuous loop like a carousel slider. I try using addEventListener with the event name transitionend but that event doesn't perform correctly and showing unsatisfied behavior. Is there a way to fix this?
(function () {
var resetTranslation = "translate3d(-300px,0px,0px)";
var elm = document.querySelector('.Working');
elm.style.transform = resetTranslation;
var arr = document.querySelectorAll('.Working li');
var clonefirst,
clonelast,
width = 300;
index = 2;
clonefirst = arr[0].cloneNode(true);
clonelast = arr[arr.length - 1].cloneNode(true);
elm.insertBefore(clonelast, arr[0]);
arr[arr.length - 1].parentNode.insertBefore(clonefirst, arr[arr.length - 1].nextSibling);
//Update
arr = document.querySelectorAll('.Working li');
elm.style.transition = 'transform 1.5s ease';
setInterval(function () {
elm.style.transform = 'translate3d(-' + index * width + 'px,0px,0px)';
if (index == arr.length - 1) {
elm.addEventListener('transitionend', function () {
elm.style.transform = resetTranslation;
});
index = 1;
}
index++;
}, 4000)
})();
*{
box-sizing: border-box;
}
.wrapper{
position: relative;
overflow: hidden;
height: 320px;
width: 300px;
}
.Working{
list-style: none;
margin: 0;
padding: 0;
position: relative;
width: 3125%;
}
.Working li{
position: relative;
float: left;
}
img{
max-width: 100%;
display: block;
}
.SubContainer:after{
display: table;
clear: both;
content: "";
}
<div class="wrapper">
<ul class="SubContainer Working">
<li> <img class="" src="http://i.imgur.com/HqQb9V9.jpg" /></li>
<li><img class="" src="http://i.imgur.com/PMBBc07.jpg" /></li>
<li><img class="" src="http://i.imgur.com/GRrGSxe.jpg" /></li>
</ul>
</div>
I've messed around with your code to hack in a fix: https://jsfiddle.net/rap8o3q0/
The changed part:
var currentItem = 1;
setInterval(function () {
var getWidth = window.innerWidth;
if(len === currentItem){
i = 1;
currentItem = 1;
} else {
currentItem++;
i++;
}
var val = 'translate3d(-' + (i-1) * getWidth + 'px,0px,0px)';
UnorderedListElement.style.transform = val;
}, 3000);
Your transition end event is not immediately fire because last transition doesn't computed when last clone image appear. You can easily achieve this thing by using setTimeout function and pass number of milliseconds to wait, after that reset the translation. I don't know it's an efficient solution but i think its easily done by using this function.
Now I'm fixing your code with this.
(function () {
var elm = document.querySelector('.Working');
var arr = document.querySelectorAll('.Working li');
var clonefirst,
clonelast,
width = 300;
index = 2;
clonefirst = arr[0].cloneNode(true);
clonelast = arr[arr.length - 1].cloneNode(true);
elm.insertBefore(clonelast, arr[0]);
arr[arr.length - 1].parentNode.insertBefore(clonefirst, arr[arr.length - 1].nextSibling);
//Update
arr = document.querySelectorAll('.Working li');
setInterval(function () {
$(elm).css({
'transform': 'translate3d(-' + (index * width) + 'px,0px,0px)',
'transition': 'transform 1.5s ease'
});
if (index == arr.length - 1) {
setTimeout(function () {
$(elm).css({'transform': 'translate3d(-300px,0px,0px)', 'transition': 'none'});
index = 1;
}, 1400);
}
index++;
}, 2000)
})();
* {
box-sizing: border-box;
}
.wrapper {
position: relative;
overflow: hidden;
height: 320px;
width: 300px;
margin-top: 8px;
}
.Working {
list-style: none;
margin: 0;
padding: 0;
position: relative;
transform: translateX(-300px);
width: 3125%;
}
.Working li {
position: relative;
float: left;
}
img {
max-width: 100%;
display: block;
}
.SubContainer:after {
display: table;
clear: both;
content: "";
}
#checkboxer:checked + .wrapper {
overflow: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="checkboxer">Remove Overflow Hidden</label>
<input type="checkbox" id="checkboxer" name="checkboxer"/>
<div class="wrapper">
<ul class="SubContainer Working">
<li> <img class="" src="http://i.imgur.com/HqQb9V9.jpg" /></li>
<li><img class="" src="http://i.imgur.com/PMBBc07.jpg" /></li>
<li><img class="" src="http://i.imgur.com/GRrGSxe.jpg" /></li>
</ul>
</div>
To come back your slider in its first position, you need to trigger a transition end event after the last (3th) translation, That works only one time.
$(UnorderedListElement).one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend", function ()
{
{
$(UnorderedListElement).css('transform', 'translate3d(0, 0, 0)');
}
});
But you need to make it to translate immediately. In link below you can see my slider that is very similar to yours, but works by absolute positioning and change the left property instead of transform.
Slider
Last thing: It is not a good idea to slide the hole of the image container. You must slide your images separately. In your way there is an obvious problem: When the page is sliding out the last image, there is not the next image to push it!
You can update your setInterval as
setInterval(function() {
var getWidth = window.innerWidth;
var val = 'translate3d(-' + i * getWidth + 'px,0px,0px)';
UnorderedListElement.style.transform = val;
i++;
if (i == 3) { //assuming three images here
i = 0
}
}, 3000)
var DomChanger;
(function() {
var listItem = document.querySelectorAll('.ah-slider li');
var len = listItem.length;
var getImage = document.querySelector('.ah-slider li img');
var UnorderedListElement = document.querySelector('.ah-slider');
var outerDiv = document.querySelector('.Slider');
UnorderedListElement.setAttribute('style', 'width:' + (len * 1000 + 215) + '%');
var i = 1;
DomChanger = function() {
for (var i = 0; i < len; ++i) {
listItem[i].setAttribute('style', 'width:' + window.innerWidth + 'px');
}
outerDiv.setAttribute('style', 'height:' + getImage.clientHeight + 'px');
};
setInterval(function() {
var getWidth = window.innerWidth;
var val = 'translate3d(-' + i * getWidth + 'px,0px,0px)';
UnorderedListElement.style.transform = val;
i++;
if (i == 3) {
i = 0
}
}, 3000)
})();
window.onload = function() {
DomChanger();
};
window.onresize = function() {
DomChanger();
};
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
background-color: #fff;
}
.Slider {
width: 100%;
margin: 50px 0 0;
position: relative;
overflow: hidden;
}
.ah-slider {
padding: 0;
margin: 0;
list-style: none;
position: relative;
transition: transform .5s ease;
}
.ah-slider li {
position: relative;
float: left;
}
.ah-slider li img {
max-width: 100%;
display: block;
}
.clearFix:after {
content: "";
display: table;
clear: both;
}
<div class="Slider">
<ul class="ah-slider clearFix">
<li>
<img class="" src="http://i.imgur.com/L9Zi1UR.jpg" title="" />
</li>
<li>
<img class="" src="http://i.imgur.com/FEcEwFs.jpg" title="" />
</li>
<li><img class="" src=http://i.imgur.com/hURSKNa.jpg" title="" /></li>
</ul>
</div>
I like to know the cleanest method to distribute elements vertically with jQuery. I nailed it but it's not very clean right >< ? I would like to get to do it without plugin... Thank you in advance ;-)
Here my JSFiddle
jQuery(document).ready(function($) {
var gap = 10;
var firstElem = $('#lorem');
if(firstElem.length){
var heightCall = (firstElem.offset().top)+(firstElem.outerHeight())+(gap);
var middleElem = $('#dolore');
middleElem.offset({top : heightCall});
var lastElem = $('#amet');
var NewHeightCall = (middleElem.offset().top)+(middleElem.outerHeight())+(gap);
lastElem.offset({top : NewHeightCall});
/* Animation */
$('#lorem, #dolore, #amet').hover(
function(){
$(this).stop().animate({left: (($(this).offset().left)-(20))+'px',opacity:'0.5'},'slow')
},
function(){
$(this).stop().animate({left: (($(this).offset().left)+(20))+'px',opacity:'1'},'slow')
});
}
});
I have fiddled around with your code:
This is a simplified version:
HTML:
<div id="lorem" class="vertical-block">My first ID div</div>
<div id="dolore" class="vertical-block">My second ID div.<br>My second ID div. My second ID div.</div>
<div id="amet" class="vertical-block">My third ID div</div>
CSS:
.vertical-block {
position: absolute;
padding:15px;
}
#lorem{
top:20%;
right:40px;
background:#f79673;
}
#dolore{
right:80px;
background:#cd7454;
}
#amet{
right:40px;
background:#a15338;
}
.vertical-block:hover {
opacity: 0.5;
padding-right: 30px;
-webkit-transition: all 2s;
transition: all 0.4s;
}
Javascript:
jQuery(document).ready(function($) {
var gap = 10;
var firstElem = $('#lorem');
var top = 0;
$('.vertical-block').each(function(element){
var $currentElement = $(this);
if (top === 0) {
top = $currentElement.offset().top + $currentElement.outerHeight() + gap;
} else {
$currentElement.offset({top: top});
top = top + $currentElement.outerHeight() + gap;
}
});
});
https://jsfiddle.net/rae2x4e0/1/
Now if you want to go for a purely css solution, then:
HTML:
<div class="container">
<div id="lorem" class="vertical-block">My first ID div</div>
<br />
<div id="dolore" class="vertical-block">My second ID div.<br>My second ID div. My second ID div.</div>
<br />
<div id="amet" class="vertical-block">My third ID div</div>
</div>
CSS:
.container {
position-relative;
text-align: right;
padding-top: 10%;
}
.vertical-block {
padding:15px;
display: inline-block;
margin-top: 20px;
}
#lorem{
right:40px;
background:#f79673;
}
#dolore{
right:80px;
background:#cd7454;
}
#amet{
right:40px;
background:#a15338;
}
.vertical-block:hover {
opacity: 0.5;
padding-right: 30px;
-webkit-transition: all 2s;
transition: all 0.4s;
}
https://jsfiddle.net/ycdwpjxw/1/