JavaScript / CSS hover function - javascript

Would it be possible to create something like what I have in the code below with just vanilla JavaScript or CSS? I also want it to have the hover div stay open until a button click, which would then slide the original div back down. Anything helps, cheers!
$(document).ready(function(){
$('.up-down').mouseover(function(){
$('.default').stop().animate({
height: 0
}, 200);
}).mouseout(function(){
$('.default').stop().animate({
height: 200
}, 200)
})
});
.up-down {
overflow:hidden;
height:200px;
width:200px;
}
.slide {
width:200px;
height:200px;
}
.default {
background-color:#ccc;
}
.onhover {
background-color:#1DB7CB;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="up-down">
<div class="slide default"></div>
<div class="slide onhover"></div>
</div>

Using your code as background, you can do it like this:
Remember Jquery is just a library of Javascript, anything you can do o Jquery you can do it on Javascript.
var updown = document.querySelector('.up-down');
var def = document.querySelector('.default');
var btn = document.querySelector('.clickMe');
updown.addEventListener('mouseover', function() {
def.style.height = '0px';
});
btn.addEventListener('click', function() {
def.style.height = '200px';
});
.up-down {
overflow:hidden;
height:200px;
width:200px;
}
.slide {
width:200px;
height:200px;
}
.default {
background-color:#ccc;
transition: height .2s linear;
}
.onhover {
background-color:#1DB7CB;
}
<div class="up-down">
<div class="slide default"></div>
<div class="slide onhover"><button class="clickMe">
Click me
</button></div>
</div>

Are you looking for something like this?
.up-down {
height: 200px;
width: 200px;
}
.slide {
width: 100%;
height: 100%;
transition: all 0.5s;
}
.default {
background: blue;
}
.onhover {
background: green;
height: 0%;
}
.up-down:hover .default {
height: 0%;
}
.up-down:hover .onhover {
height: 100%;
}
<div class="up-down">
<div class="slide default"></div>
<div class="slide onhover"></div>
</div>

Use CSS3 transition for height value of the div with onhoverclass attribute:
.up-down {
position: relative;
overflow: hidden;
height: 200px;
width: 200px;
}
.slide {
width: 200px;
height: 200px;
}
.default {
background-color: #ccc;
}
.onhover {
position: absolute;
bottom: 0;
height: 0;
background-color: #1DB7CB;
-webkit-transition: height 1s ease-out 0.5s;
-moz-transition: height 1s ease-out 0.5s;
-o-transition: height 1s ease-out 0.5s;
transition: height 1s ease-out 0.5s;
}
.up-down:hover .onhover {
height: 200px;
}
<div class="up-down">
<div class="slide onhover"></div>
<div class="slide default"></div>
</div>
To change effect direction use top: 0; instead of bottom: 0;

Would it be possible to create something like what I have in the code below with just vanilla JavaScript ?
Yes, everything that's done with jquery is doable with javascript.
With css
It sure is. Here is something to get you started
.up-down {
overflow:hidden;
height:200px;
width:200px;
position: relative;
}
.slide {
width:200px;
height:200px;
position:absolute;
}
.default {
background-color:#ccc;
}
.onhover {
background-color:#1DB7CB;
z-index: 2;
top: 200px;
transition: top 0.4s;
}
.up-down:hover .onhover {
top: 0px;
}
<div class="up-down">
<div class="slide default"></div>
<div class="slide onhover"></div>
</div>
So to explain the code somewhat:
.up-down:hover .onhover {
top: 0px;
}
on hover of up-down put the .onhover back up.
.onhover {
top: 200px;
transition: top 0.4s;
}
Initial position under the grey div, the transition makes it so :hover will be done on the span of 0.4s.
If you want the div to stay blue when the mouseleave, just add a class on mouseenter. You probably still can do it with pure css but I guess it would be harder than this:
.onhover {
background-color:#1DB7CB;
z-index: 2;
top: 200px;
transition: top 0.4s;
}
addedClass{
top: 0px;
}
// target is up-down
target.addEventListener("mouseenter", e => {
// element is your onhover elem
element.classList.add("addedClass");
});
target.addEventListener("click", e => {
element.classList.remove(" addedClass");
});

You can add event listeners with addEventListener.
The animation can be implemented with the transition property so a change in height will slowly transition instead of happening immediately.
I also added the button like you requested in your edit.
var updown = document.querySelector('.up-down');
var def = document.querySelector('.default');
var btn = document.querySelector('#btn');
updown.addEventListener('mouseover', function() {
def.style.height = '0px';
});
updown.addEventListener('mouseout', function() {
def.style.height = '200px';
});
btn.addEventListener('click', function() {
var isDown = def.style.height === '200px';
def.style.height = isDown ? '0px' : '200px';
});
.up-down {
overflow:hidden;
height:200px;
width:200px;
}
.slide {
width:200px;
height:200px;
}
.default {
background-color:#ccc;
transition: height .2s linear;
}
.onhover {
background-color:#1DB7CB;
}
<button type="button" id="btn">Toggle</button>
<div class="up-down">
<div class="slide default"></div>
<div class="slide onhover"></div>
</div>

Related

CSS transition not working when adding class via jquery

I am adding a class to show an image when the mouse is over a div, but the transition isnt working at all.
I am using opacity, I know that the visibily: hidden is not animable.
The code is in the snippet:
$(document).ready(function() {
$("#trigger").on("mouseenter", function () {
$("#imgPuffo").addClass("visible");
$("#trigger").on("mouseout", function () {
$("#imgPuffo").removeClass("visible");
});
});
});
#trigger {
height: 100px;
width: 100px;
background: red;
}
img {
opacity: 0;
animation: opacity 2s;
}
.visible {
visibility: visible;
opacity: 1;
animation: opacity 2s;
}
.imgPuffo {
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">
There's a bit of confusion as animation is being used, but animation will look for an #keyframes sequence to tell it what animation to run. In fact it looks as though we don't need a full CSS animation in this case, just a CSS transition.
I've added transition: all 2s in case you want to transition anything else in future, like the scale, but if you just want to stick with transitioning opacity you could do transition: opacity 2s instead.
$(document).ready(function() {
$("#trigger").on("mouseenter", function () {
$("#imgPuffo").addClass("visible");
$("#trigger").on("mouseout", function () {
$("#imgPuffo").removeClass("visible");
});
});
});
#trigger {
height: 100px;
width: 100px;
background: red;
}
img {
opacity: 0;
/* animation: opacity 2s; */
transition: all 2s;
}
.visible {
visibility: visible;
opacity: 1;
/* animation: opacity 2s; */
}
.imgPuffo {
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">
if you want to use animations check the docs. You need to use #keyframes
$(document).ready(function() {
$("#trigger").on("mouseenter", function () {
$("#imgPuffo").addClass("visible");
$("#trigger").on("mouseout", function () {
$("#imgPuffo").removeClass("visible");
});
});
});
#trigger {
height: 100px;
width: 100px;
background: red;
}
img {
opacity: 0;
animation: opacity 2s;
}
.visible {
visibility: visible;
opacity: 1;
transition: opacity 2s ease-in-out;
}
.imgPuffo {
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">
How about a solution for css using a :hover, without jquery?
#trigger {
height: 100px;
width: 100px;
background: red;
}
#trigger:hover + .imgPuffo {
opacity: 1;
}
.imgPuffo {
opacity: 0;
height: 200px;
transition: opacity 2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">

Background transition does not work properly

I'm going to change back ground an element in a setInterval function. the background is getting changed imediately, but I would like to make it transited in couple of seconds.
var act = true;
setInterval(function(){
if (act) {
$("div").addClass("back2")
$("div").removeClass("back")
act = false
} else {
$("div").addClass("back")
$("div").removeClass("back2")
act = true
}
}, 10000)
.back{
width:100px;
height:100px;
background-image:url("https://www.skoobe.de/static/v/7b2334ac8a86ab5d764bc6e94df87df4aa5b4e2adc78c783e73ae2cbaf613745.jpg");
display:block;
transition: .5s ;
}
.back2{
width:100px;
height:100px;
background-image:url("https://www.skoobe.de/static/v/a5c0d3825217f88c4c893e7b630c4f1c5eb4c9bec834e1112383614270b5d583.jpg");
display:block;
transition: .5s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="c">tz</div>
background-image is not an animatable property. As you can see in this list on the mozilla dev page, this is not possible: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties
What you can do is have two divs with one background image each overlapping each other and then make one of them transparent to create a blending effect.
I made a fiddle to illustrate the idea:
https://jsfiddle.net/Lpduw3mq/
// find elements
var firstDiv = $("#first")
var secondDiv = $("#second")
// Swap backgrounds
var act = true;
setInterval(function(){
if (act) {
firstDiv.addClass("transparent")
secondDiv.removeClass("transparent")
act = false
} else {
firstDiv.removeClass("transparent")
secondDiv.addClass("transparent")
act = true
}
}, 5000)
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
.base {
position: absolute;
top: 0;
left: 0;
}
.back {
width: 100px;
height: 100px;
background-image: url("https://www.skoobe.de/static/v/7b2334ac8a86ab5d764bc6e94df87df4aa5b4e2adc78c783e73ae2cbaf613745.jpg");
display: block;
opacity: 1;
transition: opacity 0.5s;
}
.back2 {
width: 100px;
height: 100px;
background-image: url("https://www.skoobe.de/static/v/a5c0d3825217f88c4c893e7b630c4f1c5eb4c9bec834e1112383614270b5d583.jpg");
display: block;
opacity: 1;
transition: opacity 0.5s;
}
.transparent {
opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="first" class="base back"></div>
<div id="second" class="base back2 transparent"></div>
You can use an unordered list of two items absolutely styled with the image backgrounds and use keyframe animation to change between these two items while smoothly changing a background opacity. Check this out http://tympanus.net/codrops/2012/01/02/fullscreen-background-image-slideshow-with-css3/

Hard transition of other properties when display property is involved

I want to fade between two differently sized elements within a container overlaying each other. The first element should be faded out, then the container resized and finally the other element faded in.
Here's the related snippet:
var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");
function switchLayers() {
layer1.addEventListener("transitionend", function() {
layer2.classList.add("fadein");
});
layer1.classList.add("fadeout");
}
#container {
position: relative;
background-color: yellow;
padding: 10px;
overflow: hidden;
}
.layer {
position: relative;
width: 400px;
}
#layer1 {
height: 100px;
float: left;
background-color: blue;
}
#layer2 {
height: 150px;
background-color: red;
display: none;
opacity: 0;
}
#layer1.fadeout {
opacity: 0;
transition: opacity 1s ease-out;
}
#layer2.fadein {
display: block;
opacity: 1;
transition: opacity 1s ease-out;
}
<button onclick="switchLayers()">Switch layers</button>
<div id="container">
<div id="layer1" class="layer"></div>
<div id="layer2" class="layer"></div>
</div>
When the second layer's display property is set to block it works as expected, i.e. the opacity is changed from 0 to 1 within a second. Though if it's set to none, the transition suddenly is discrete.
I've tried to set all within the transition value to transition all properties and also tried to include the display property in the transition like this:
transition: display 0s, opacity 1s ease-out;
Though without success. Note that because the container should resize to the size of the currently displayed layer, the visibility property can't be used (as it hides the element but still lets it occupy the space).
How to made this work?
Try using the visibility property instead of display.
For more information regarding the state changes in visibility and display, refer article.
For transitioning the parent height, you have to manually change the height property of the #container. Using display: block & display: none will never transition the parent.
Refer code:
var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");
function switchLayers() {
layer1.addEventListener("transitionend", function() {
layer2.classList.add("fadein");
document.getElementById("container").style.height = "170px";
});
layer1.classList.add("fadeout");
}
#container {
position: relative;
background-color: yellow;
padding: 10px;
height: 100px;
overflow: hidden;
transition: all 0.5s;
}
.layer {
position: relative;
width: 400px;
}
#layer1 {
height: 100px;
float: left;
background-color: blue;
}
#layer2 {
height: 150px;
background-color: red;
visibility: none;
opacity: 0;
}
#layer1.fadeout {
visibility: none;
opacity: 0;
transition: all 1s ease-out;
}
#layer2.fadein {
visibility: visible;
opacity: 1;
transition: all 1s ease-out;
}
<button onclick="switchLayers()">Switch layers</button>
<div id="container">
<div id="layer1" class="layer"></div>
<div id="layer2" class="layer"></div>
</div>
There is no straightforward way. Transitions do not work on display, nor do they work on auto height. So, visibility is a good bet.
Note that because the container should resize to the size of the
currently displayed layer, the visibility property can't be used (as
it hides the element but still lets it occupy the space).
Then, you will need to hack it out. You can make use of min-height. Give a faux min-height to your container, and then apply the height of your layer2 to it once the transition ends. Also, because display on layer2 will block the transition, you need to separate out the classes for display and opacity and space out their application using a zero timeout in between.
Here is a crude idea:
var layer1 = document.getElementById("layer1"),
layer2 = document.getElementById("layer2"),
container = document.getElementById("container"),
h = window.getComputedStyle(layer2).getPropertyValue("height");
container.addEventListener("transitionend", function(e) {
if (e.target.id === 'layer1') {
// apply layer2 height to container min-height
container.style.minHeight = h;
}
if (e.target.id === 'container') {
// First show the layer2
layer2.classList.add("show");
// Then a dummy pause to fadein
setTimeout(function(){
layer2.classList.add("fadein");
}, 0);
}
}, false);
function switchLayers() {
layer1.classList.add("fadeout");
}
#container {
position: relative;
background-color: yellow;
padding: 10px; overflow: hidden;
min-height: 1px; /* faux min-height */
transition: min-height 1s linear;
}
.layer { position: relative; width: 400px; }
#layer1 {
height: 100px; float: left;
background-color: blue;
transition: all 1s linear;
}
#layer2 {
height: 150px; background-color: red;
display: none; opacity: 0;
transition: opacity 1s linear;
}
#layer1.fadeout { opacity: 0; }
#layer2.show { display: block; } /* Separate out display */
#layer2.fadein { opacity: 1; } /* Separate out opacity */
<button onclick="switchLayers()">Switch layers</button>
<div id="container">
<div id="layer1" class="layer"></div>
<div id="layer2" class="layer"></div>
</div>

CSS transiction and JS toggle at the same moment

I've got not displayed block with JS toggle performance on mouseover/mouseout(http://jsfiddle.net/4bytz20h/2/):
html:
<div id="menu" onmouseover="toggle_extra_panel()" onmouseout="toggle_extra_panel()">
<a>hover me</a>
<div id="list">
Some Text
</div>
</div>
js:
function toggle_extra_panel() {
var sys_val = document.getElementById('list');
sys_val.style.display = (sys_val.style.display == 'none' ||
sys_val.style.display == '') ? 'block' : 'none';
}
css:
#menu #list {
display: none;
}
Trying to add some animation effects(by CSS transictions)(http://jsfiddle.net/4bytz20h/1/):
html(without changes):
<div id="menu" onmouseover="toggle_extra_panel()" onmouseout="toggle_extra_panel()">
<a>hover me</a>
<div id="list">
Some Text
</div>
</div>
JS:
<!-- empty here -->
CSS:
#menu #list {
height: 0;
width: 0;
transition: all 1.5s ease-out;
background: #d5d5d5;
}
#menu:hover #list {
height: 250px;
width: 250px;
transition: all 2.5s ease-in;
}
But I lost (forgot to use) my JS toggle code. In next example I'm trying to combine JS logic(display form 'none' to 'block' when mouseover) and CCS transiction effect(height and width from '0' to 'auto' when mouseover). Here not wroking well code(http://jsfiddle.net/4bytz20h/):
html(without changes):
<div id="menu" onmouseover="toggle_extra_panel()" onmouseout="toggle_extra_panel()">
<a>hover me</a>
<div id="list">
Some Text
</div>
</div>
js(without changes):
function toggle_extra_panel() {
var sys_val = document.getElementById('list');
sys_val.style.display = (sys_val.style.display == 'none' ||
sys_val.style.display == '') ? 'block' : 'none';
}
css:
#menu #list {
height: 0;
width: 0;
transition: height 1.5s ease-out;
transition: width 1.5s ease-out;
background: #d5d5d5;
display: none;
}
#menu:hover #list {
height: 250px;
width: 250px;
transition: height 2.5s ease-in;
transition: width 2.5s ease-in;
}
Better way to execute all desires using only by ccs transictions.
But how about this combine way: in one moment JS makes the item to be displayed and in this same moment ccs tries to draw rectangle-text-area from 0 to bigger gabarite
I think this may be what you're trying to do.
.hide {
height: 0px;
width: 0px;
transition: all 2.5s ease-in;
background: #d5d5d5;
opacity: 0;
}
.current:hover .hide {
height: 250px;
width: 250px;
opacity: 1;
}
<div class="current">HOVER ME
<div class="hide">SOME TEXT</div>
</div>

JavaScript induced CSS animation not working

Following advice from this CSS Tricks article, I tried to write some code to induce a CSS transition using JavaScript.
(Here's my jsFiddle.)
HTML:
<button id="button" onclick="doMove2()" value="play">Play</button>
<div class="foo"></div>
CSS:
#button {
position: absolute;
width: 200px;
height: 50px;
top: 185px;
left: 0px;
}
.foo {
position: absolute;
width: 50px;
height: 50px;
border: 1px dashed black;
left: 0px;
top: 120px;
}
.foo.horizTranslate {
-webkit-transition: 3s;
-moz-transition: 3s;
-ms-transition: 3s;
-o-transition: 3s;
transition: 3s;
margin-left: 50% !important;
}
JavaScript:
var foo = document.getElementsByClassName('foo')[0];
function doMove2(){
document.getElementById("button").onclick = function(){
if(this.innerHTML === 'Play'){
this.innerHTML = 'Pause';
foo.classList.add('horizTranslate');
} else {
this.innerHTML = 'Play';
var computedStyle = window.getComputedStyle(foo2),
marginLeft = computedStyle.getPropertyValue('margin-left');
foo.style.marginLeft = marginLeft;
foo.classList.remove('horizTranslate');
}
}
}
Why doesn't this work?
Could someone explain the difference between a transition and an animation?
Firstly, I don't recommend using jsfiddle, sometimes its glitchy and unreliable. I use jsbin, check my demo: http://jsbin.com/guceneku/1/
I removed the onclick in your HTML tag, since you already had a trigger in js, so it becomes:
<button id="button" value="play">Play</button>
<div class="foo"></div>
Next your js becomes:
var foo = document.getElementsByClassName('foo')[0];
document.getElementById("button").onclick = function(){
if(this.innerHTML === 'Play'){
this.innerHTML = 'Pause';
foo.classList.add('horizTranslate');
} else{
this.innerHTML = 'Play';
var computedStyle = window.getComputedStyle(foo2),
marginLeft = computedStyle.getPropertyValue('margin-left');
foo.style.marginLeft = marginLeft;
foo.classList.remove('horizTranslate');
}
}
You have no initial value defined. It's defaulting to a margin of auto, and auto is not transitionable.
Also, you should define the transitions on the "base" state, otherwise it won't transition when removing the class.
So:
.foo {
position:absolute;
width:50px;
height:50px;
border:1px dashed black;
left:0px;
top:120px;
margin-left: 0; /* ADD THIS */
transition: 3s; /* all browsers support unprefixed now */
}
.foo.horizTranslate {
margin-left: 50%;
}

Categories