CSS transition duration not applying on first instance of transition effect - javascript

I'm trying to create a series of sliding divs triggered on press of a button. The idea is that each div will have a thumbnail and some text tied to it. Upon clicking left/right button, the divs will move their position accordingly.
My code can be seen in the jsfiddle below. I'm encountering 3 problems:
1) The "transition: left 2s" rule isn't applying on the first transition effect, it does on the subsequent ones.
2) I'd like the repeat pressing of the corresponding buttons to apply the left property value again so that I can slide the divs repeatedly.
3) Instead of the "right" button re-positioning the "left" property back to 0, I'd like to shift it back in the opposite direction with the previous left property value.
Essentially I'm trying to recreate the slider found on this side.
http://www.euphoriumbakery.com/
Any help or input will be greatly appreciated.
Thank you very much for your help.
https://jsfiddle.net/kshatriiya/g709swLg/1/
window.onload = function() {
$("#left").on("click", function() {
$("#view").css("left", "-262px");
});
$("#right").on("click", function() {
$("#view").css("left", "0px");
});
}
#galwrapper {
width: 650px;
height: 400px;
display: block;
overflow: hidden;
}
#view {
position: relative;
width: 1423px;
transition: left 2s;
}
.col-md {
display: inline-block;
margin-top: 100px;
width: 18%;
}
.thumb img {
opacity: 0.9;
height: auto;
width: auto;
max-height: 150px;
max-width: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="galwrapper">
<div id="view">
<div class="col-md">
<div class="thumb">
<img class="img-rounded" src="http://netdna.walyou.netdna-cdn.com/wp-content/uploads/2010/09/retrocake1.jpg">
<div class="caption">
<h4>Retro Cake</h4>
</div>
</div>
</div>
<div class="col-md">
<a href="#" class="thumb active">
<img class="img-rounded" src="https://i.ytimg.com/vi/dh8ii5sbvyc/maxresdefault.jpg">
<div class="caption">
<h4>Strawberry Cake</h4>
</div>
</a>
</div>
<div class="col-md" id="mid">
<a href="#" class="thumb">
<img src="https://i.ytimg.com/vi/dh8ii5sbvyc/maxresdefault.jpg">
<div class="caption">
<h4>Retro Cake</h4>
</div>
</a>
</div>

#view {
position: relative;
width: 1423px;
left:0;
transition: left 2s;
}
Initially make left:0; for the div with id view https://jsfiddle.net/81tqeof4/6/
and for sliding effect get the current left position and update the position.check fiddle for an example
$("#left").on("click", function(){
var leftPosition = parseInt($("#view").position().left) - 256;
$("#view").css("left", -Math.abs(leftPosition));
});

transition works only on an existing property
So initially(in your CSS) you do not have a left property available in your #view. It is only later on a click that your JavaScript adds the left and your transition starts working.
So basically you need to set the left property to a value in your CSS, before your JavaScript takes effect and adds the left
#view {
position: relative;
width: 1423px;
left: 0; //initiate
transition: left 2s;
}

Related

Slide a div into appearance without jQuery

I am using onclick method on a link in order to display a div. However, it doesn't slide, it simply appears. How do I make it appear with a slide effect without using jQuery. The reason I don't want to use jQuery is because I want the page to load as fast as possible.
function view() {
document.getElementById('topmenu').setAttribute('style', 'display:block');
}
#topbar {
background-color: yellow;
overflow: auto;
}
#topmenu {
display: none;
}
<header>
<div id="topbar">
<img src="/images/santorini-wedding-photographer-logo.png" style="float: left;">
<span style="float: right;">MENU</span>
</div>
<div id="topmenu">
some text here
</div>
</header>
It can be done using Javascript
setInterval() and clearInterval() functions.
See code samples here
JavaScript slidedown without jQuery
You can't apply transition to display property - you can transition scale instead - see demo below:
function view() {
// add a class to show the element
document.getElementById('topmenu').classList.add('show');
}
#topbar {
background-color: yellow;
overflow: auto;
}
#topmenu {
transform: scaleY(0); /* scale to zero vertically */
transform-origin: top; /* set origin to top */
overflow: hidden;
transition: transform 1s; /* apply transition to only scale */
}
#topmenu.show {
transform: scaleY(1); /* scale to full height */
}
<header>
<div id="topbar">
<img src="https://via.placeholder.com/50" style="float: left;">
<span style="float: right;">MENU</span>
</div>
<div id="topmenu">
some text here
</div>
</header>

Changing image on hover and back using fade

I'm trying to change an image on hover and back again.
The idea is that when I hover over an image, it fades into a different image and when my mouse leaves, the image fades back to the original.
Here is what I have tried so far, using jQuery:
<img src="https://www.shareicon.net/data/128x128/2015/08/17/86675_cat_256x256.png" />
<script>
$("img").hover(function(event) {
event.preventDefault();
console.log("hover");
$("img").fadeOut(400, function() {
$("img").attr("src", "http://files.softicons.com/download/animal-icons/meow-icon-set-by-iconka/png/128x128/cat_purr.png")
}).fadeIn(400, function() {
$("img").attr("src", "https://www.shareicon.net/data/128x128/2015/08/17/86675_cat_256x256.png")
});
});
</script>
You can actually do this with plain CSS and it would be more efficient.
Just create a div, put both images inside, absolute position so one is on top of another, and when hover apply opacity: 0 with a transition to the front image.
You can achieve this with position absolute, z-index, and hover pseudo selector.
.container{
width: 300px;
height: 300px;
position: relative;
}
img{
position: absolute;
top: 0;
left: 0;
}
.img-top{
z-index: 999999;
transition: 0.3s linear all;
}
.img-top:hover{
opacity: 0;
}
<div class="container">
<img class="img-bottom" src="https://www.cesarsway.com/sites/newcesarsway/files/d6/images/askthevet/checklist.jpg" alt="">
<img class="img-top" src="https://i.ebayimg.com/images/g/k2gAAOSwT5tWKhVS/s-l300.jpg" alt="">
</div>

How to position a div above another div?

My code is:
HTML:
<section>
<div id="banner">
<div class="container">
<p class="para">hello world</p>
</div>
<div class="container banner-bottom">
<div class="card card-primary text-center z-depth-2 contact-main-text">
<div class="card-block">
<p class="white-text">Please fill out the form below and ESC
staff will be in contact with you shortly.</p>
</div>
</div>
</div>
</div>
</section>
CSS:
.para{
color:white;
background: red;
padding:70px;
text-align:center;}
.white-text{
background:green;
padding:20px;}
Output is: Bootply
And i want:
Could anyone help me with that?
You can set negative top margin to overlay the second div, see the live example:
<div class="container banner-bottom" style="margin-top:-5%;padding:2%">
http://www.bootply.com/MorC45NB4V
PS: I have used inline css just to show, avoid inline css.
My solution uses jQuery and some calculations. My calculation works even if you move the elements around the document. I also used CSS for the margins you wanted.
jQuery
//location of bottom of the red container
var bottomOfContainer = $('#onTopOfMe').offset().top + $('#onTopOfMe').height();
//gets the bottom 4th of the red container
var placement = bottomOfContainer - ($('#onTopOfMe').height() / 4);
//setter of top for green container
$('#placeMe').offset({"top": placement});
CSS
p.white-text{
margin-left:5%;
margin-right:5%;
}
Output
bootply
1) In case you want your lower banner to have a full width:
You could add position: relative; to the lower banner and position it adding a bottom value and use margin to create the same visual effect asked in the question.
.banner-bottom {
position: relative;
bottom: 45px;
margin: 0 40px;
}
2) In case you don't need to have a banner with full width and just center it, then no need to use margins. Remember to set one parent as position: relative;:
#banner { position:relative;}
.banner-bottom {
position: absolute;
top:75%;
right:0;
bottom:auto;
left:0;
}
CODEPEN
http://codepen.io/alexincarnati/pen/PWOPjY
Here's my solution for this.
Basically just make the position of the card block "relative", position the "top" position accordingly, then set the margin to "auto" to center it.
.card-block {
position: relative;
top: -50px;
margin: auto;
width: 80%;
}
A bit of position could help you, here's a rough version that will hopefully get you thinking what you need to do:
#banner { position:relative;}
.banner-bottom { position: absolute; top:75%;right:0;bottom:auto;left:0; }
Heres a forked bootply: http://www.bootply.com/Imuh4wUj50

Issue when animating on hover effects with callbacks

So I am having this issue when I am using the hover event in jQuery. I have two containers side by side. I have hover events on both of them. When hover, a div with additional info slides up into frame. When you hover off, it slides back down.
Simple right? When you hover on an element it should remove the "hide-me" class and start sliding the info up (animating). When you hover off of an element the "hide-me" class should be removed once the animation is complete.This works fine when you hover on and hover off onto an element that is not a grid-item. When you hover off of an item onto another grid-item it seems to just add the class "hide-me" to the currently hovered element. Even though the hover off event hasn't fired yet.
Anyways enough talk here is the code on JS Fiddle:
https://jsfiddle.net/joemoe_1984/2k22yLmd/2/
For testing here is what works:
Hover from below/above image then hover out from below/above image
For testing how it doesn't work:
Hover from below/above image then hover out onto other image
UPDATE
Just to clarify a bit as I had an answer that got me the effect I wanted but didn't exactly solve the issue I was having exactly. I would like to know why the animation callbacks on complete don't properly work when hovering from one image to the other. This is the part that has been bugging me the most. When you hover on an image and then out it removes the class on hover then adds the class after the animation called from the hover out event finishes. This is the expected behaviour. When I hover over an image then onto the other image you will see that instead of adding the class to the first image on hover out, it adds it to the image you are current hovering. Its as if the animation callback is calling the wrong callback function once it animates up on hover.
The on hover state should never have the class added. It should be removed at this point. The class should also not be added during any of the animation states.
Just in case links aren't ok, here is the full html, css and javascript:
HTML
<div class="grid-container">
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
</div>
CSS
.grid-item {
width: 25%;
float: left;
overflow: hidden;
}
.grid-item img {
max-width: 100%;
height: auto;
}
.grid-inner {
position: relative;
display: block;
}
.grid-info {
position: absolute;
background: blue;
color: white;
width: 100%;
height: 100%;
}
.hide-me {
display: none;
}
.middle-align {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
Javascript
$(document).ready(function() {
$('.grid-item').hover(hover_in, hover_out);
function hover_in(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.css('top', target_height).removeClass('hide-me');
$info.stop().animate({
'top': 0,
}, 500, function() {
console.log('animated up');
});
}
function hover_out(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.stop().animate({
'top': target_height,
}, 500, function() {
console.log('animated down');
$info.addClass('hide-me');
});
}
});
Try substituting using .show() after call to .stop() for .removeClass('hide-me') at hover_in
$(document).ready(function() {
$('.grid-item').hover(hover_in, hover_out);
function hover_in(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.css('top', target_height) //.removeClass('hide-me')
.stop()
.show()
.animate({
'top': 0,
}, 500, function() {
console.log('animated up');
});
}
function hover_out(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.stop().animate({
'top': target_height,
}, 500, function() {
console.log('animated down');
$info.addClass('hide-me');
});
}
});
.grid-item {
width: 25%;
float: left;
overflow: hidden;
}
.grid-item img {
max-width: 100%;
height: auto;
}
.grid-inner {
position: relative;
display: block;
}
.grid-info {
position: absolute;
background: blue;
color: white;
width: 100%;
height: 100%;
}
.hide-me {
display: none;
}
.middle-align {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<body>
<h1>Animation grid</h1>
<div class="grid-container">
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
</div>
</body>
jsfiddle https://jsfiddle.net/2k22yLmd/3/
Ok. So I figured it out. It turned out to be a scope issue. The problem stemmed from using e.currentTarget (or this) within the hover event scope. I stored that instance into a variable and then later used it in the callback of the animation sequence.
It appears that the current target changes from when the animation callback uses it giving me the unexpected results. For the animation callbacks I should have used the instance (this) within the scope of the animation callback function like so:
$info.stop().animate({
'top': target_height,
}, 500, function() {
console.log('animated down');
$(this).addClass('hide-me'); // this refers to the current animated object. This is the correct one.
$info.addClass('wrong-one'); // $info refers to the current hover event target which is the on hover item when it should be the hover off item. This is incorrect
});
You can test it out and see that going from one image to the next will now add the class hide-me to the correct one and add the class wrong-one to the currently hovered item which is not the expected behaviour I was looking for.
Thanks to everyone for pitching in on the answers and providing alternative solutions but this was real issue for me.

jquery-ui slide left doesn't work first time

When I'm using show() and hide() methods from jquery-ui:
var current = 1;
function slide(buttonNum) {
if (current != buttonNum){
$("#page" + current).hide("slide", { direction: "left" }, 800, function() {
$("#page" + buttonNum).show("slide", { direction: "right" }, 800);
});
current = buttonNum;
}
}
My intention is that every time button is clicked for this function the page would scroll left to change to required page.
The problem is that it doesn't work first time I'm clicking page number with function above(the current div would slide to the left, but div which I change to just pops up without animation) but works normally other times.
my css is as follows:
.slider {
width: 400px;
height: 300px;
overflow: hidden;
}
.slider .content {
position: relative;
}
.slider .content .page {
float: left;
width: 400px;
height: 300px;
background-size: cover;
}
and HTML:
<div class="slider">
<div class="content">
<div id='page1' class="page">
<!-- stuff -->
</div>
<div id='page2' class="page">
<!-- stuff -->
</div>
<div id='page3' class="page">
<!-- stuff -->
</div>
</div>
</div>
<a onclick='slide(1)' href="#">1</a>
<a onclick='slide(2)' href='#'>2</a>
Try hiding the elements that you expect not to be visible at the beginning, so that the show animation will actually execute. E.g. add this at the top:
$("#page2").hide();
$("#page3").hide();
That way running .show() on them will have an effect.

Categories