css transition on class change but not on hover - javascript

I wanna animate the background-color of an html element by class change (via js). The hover effect of the same element on the other hand shouldn't animate the change of the background-color.
Here is the scenario:
.cd-btn {
background-color: $black;
transition: background-color $colorChangeDuration ease;
&:hover {
background-color: $blue;
}
&.light-mode {
background-color: $lightgrey;
&:hover {
background-color: $blue;
}
}
}
The class 'light-mode' toggles with a other element with a javascript click event listener.
How can I keep the background-color transition on class change meanwhile there is no background-color transition on hover?

You can avoid transition on hover.
It's more difficult to avoid it also on unhover. Is this a request ?
function toggle() {
var ele = document.getElementById('test');
ele.classList.toggle ("alt");
}
.test {
height: 80px;
color: white;
background-color: black;
transition: 2s background-color;
}
.test.alt {
background-color: gray;
}
.test:hover {
background-color: blue;
transition: none;
}
<div class="test" id="test" >TEST</div>
<button onclick="toggle();">CHANGE</button>
I you want also the unhover without transition, you need a JS solution for this.
One posibility would be to meove the transition class after a timeout
function toggle() {
var ele = document.getElementById('test');
ele.classList.toggle ("alt");
ele.classList.add ("trans");
window.setTimeout (notrans, 2000);
}
function notrans() {
var ele = document.getElementById('test');
ele.classList.remove ("trans");
}
.test {
height: 80px;
color: white;
background-color: black;
}
.test.alt {
background-color: gray;
}
.test:hover {
background-color: blue;
}
.trans {
transition: 2s background-color;
}
<div class="test" id="test" >TEST</div>
<button onclick="toggle();">CHANGE</button>

I'm not sure I understand the question.
Here is the code working with hover
.cd-btn {
color: white;
background-color: black;
transition: background-color 0.5s ease;
}
.cd-btn:hover {
background-color: blue;
}
.cd-btn.light-mode {
background-color: lightgrey;
}
.cd-btn.light-mode:hover {
background-color: blue;
}
<h1>Hover to toggle</h1>
<button type="button" class="cd-btn">Normal cd-btn</button>
<button type="button" class="cd-btn light-mode">Light cd-btn</button>
Here is the transition working on click instead of on hover:
function toggle(el) {
el.classList.toggle('enable');
}
const elements = document.querySelectorAll('.cd-btn');
for (let el of elements) {
el.addEventListener('click', () => toggle(el));
}
.cd-btn {
color: white;
background-color: black;
transition: background-color 0.5s ease;
}
.cd-btn.light-mode {
background-color: lightgrey;
}
.cd-btn.enable {
background-color: blue;
}
<h1>Click to toggle</h1>
<button type="button" class="cd-btn">Normal cd-btn</button>
<button type="button" class="cd-btn light-mode">Light cd-btn</button>

The simple solution to this is to create a seperate class for just the transition:
.trans {
transition: .5s ease all;
}
Then use jQuery with the mouseenter / mouseleave events to apply the class, adding the transition effect duration as the amount of a delay on the mouseleave event, before reinstating the transition on the element.
$(document).on ('mouseenter', '.scrollToTop', function() {
$(this).removeClass ('trans');
});
$(document).on ('mouseleave', '.scrollToTop', function(e) {
setTimeout (function (e) {
$('.scrollToTop').addClass ('trans');
}, 500);
});
As long as the duration is > 0 then you get no transition effect; as the class state is already changed back prior to the class being added back to the dom (.5 of a second later, the duration of the transition effect).

Related

Styling only the newest line of output in div

I have a simple app that outputs messages when some actions are performed on a page, and it is done through the javascript createElement function, what I want to do is add a special style to only the newest message, so if a newer messages comes up the old newest message would revert to the old style. Is there any way to do this? when I createElement it seems all the divs would have to have the same class, and anything I try just applies the style to all the messages.
So is there anything to use in CSS that allows me to only apply a style to the newest member of a certain class?
here is how I create the new messages
function selfMsg(message) {
const msg = document.createElement('div');
msg.style.cssText = 'display: flex; justify-content: flex-end;background-color:aquamarine';
msg.innerText = message;
display.append(msg);
}
but all this does is style all the divs the same style, and I have no idea how I'm supposed to remove the style if a newer message comes up.
Ideally I'm looking for something in CSS that I can use in my stylesheet file that can target an entire class like how ".classnamehere" works, but only applies the style to the newest member of that class.
Depending on the container your divs are in, you can use CSS last:child (https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child) like this:
So if your container has the class display, you'd do
.display div:last-child {
display: flex;
justify-content: flex-end;
background-color:aquamarine
}
In case you don't know how to use this outside of javascript, simply wrap the above code in a style tag and add it to the head of your html document.
For clarity and possibly-upcoming-changes reasons, i highly suggest giving all of your divs a class on creation and using that instead of just div in the CSS. It's just easier to maintain that way.
.message-wrapper .message:last-child {
color: red;
}
<div class="message-wrapper">
<div class="message">Message 1</div>
<div class="message">Message 2</div>
<div class="message">Message 3</div>
</div>
You can use the :last-child pseudo selector. Something like:
.display div:last-child{
// your style
}
You can add a class to your messages like this:
msg.classList.add("mystyle");
Then use a css selector to only apply styles to the last element of this type
div.mystyle:last-of-type {
/* ... your styles */
}
Here's an example you can play with, from w3schools: https://www.w3schools.com/cssref/tryit.asp?filename=trycss3_last-of-type
If you want to use pure javascript, you could use element.removeAttribute("style") or element.style.cssText = null, but you would have to keep track of the previous message elements, or get ALL messages and loop through them, removing the style from all before adding the newest element. I'd recommend just using CSS.
Something along this line
The key is the :last-child pseudo class
"use strict";
console.clear();
document.getElementById('add').addEventListener('click', e => {
const target = document.getElementById('add-target')
const div = document.createElement('div')
const text = document.createTextNode(`#${target.querySelectorAll('div').length+1}`)
div.appendChild(text)
target.appendChild(div)
})
.container {
width: 600px;
margin: auto;
border: 1px solid gray;
}
.container > div {
--bg-in: lightgray;
--bg-out: transparent;
transition: background-color 1s;
padding: 20px;
font-family: sans-serif;
}
.container > div:not(:last-child) {
border-bottom: 1px solid gray;
-webkit-animation: anim-out 1s .3s both;
animation: anim-out 1s .3s both;
}
.container > div:last-child {
-webkit-animation: anim-in 1s both;
animation: anim-in 1s both;
}
#-webkit-keyframes anim-in {
from {
background-color: var(--bg-out, white);
}
to {
background-color: var(--bg-in, pink);
}
}
#keyframes anim-in {
from {
background-color: var(--bg-out, white);
}
to {
background-color: var(--bg-in, pink);
}
}
#-webkit-keyframes anim-out {
from {
background-color: var(--bg-in, pink);
}
to {
background-color: var(--bg-out, white);
}
}
#keyframes anim-out {
from {
background-color: var(--bg-in, pink);
}
to {
background-color: var(--bg-out, white);
}
}
<button id="add">Add</button>
<div class="container" id="add-target">
<div>#1</div>
<div>#2</div>
<div>#3</div>
</div>
Or—a little bit more sophisticated—with animationend event to implement a fadeoutafter some time
"use strict";
console.clear();
document.getElementById('add').addEventListener('click', e => {
const target = document.getElementById('add-target')
const div = document.createElement('div')
div.classList.add('in')
const text = document.createTextNode(`#${target.querySelectorAll('div').length+1}`)
div.appendChild(text)
target.appendChild(div)
})
document.addEventListener('animationend', e => {
e.target.classList.add('out');
e.target.classList.remove('in');
})
.container {
width: 600px;
margin: auto;
border: 1px solid gray;
}
.container > div {
--bg-in: lightgray;
--bg-peak: gray;
--bg-out: transparent;
transition: background-color 1s;
padding: 20px;
font-family: sans-serif;
}
.container > div:not(:last-child) {
border-bottom: 1px solid gray;
}
.container > div.out {
-webkit-animation: anim-out 1s 5s both ease-out;
animation: anim-out 1s 5s both ease-out;
}
.container > div.in {
-webkit-animation: anim-in 1s both;
animation: anim-in 1s both;
}
#-webkit-keyframes anim-in {
0% {
background-color: var(--bg-out, white);
}
25% {
background-color: var(--bg-peak, black);
}
100% {
background-color: var(--bg-in, pink);
}
}
#keyframes anim-in {
0% {
background-color: var(--bg-out, white);
}
25% {
background-color: var(--bg-peak, black);
}
100% {
background-color: var(--bg-in, pink);
}
}
#-webkit-keyframes anim-out {
from {
background-color: var(--bg-in, pink);
}
to {
background-color: var(--bg-out, white);
}
}
#keyframes anim-out {
from {
background-color: var(--bg-in, pink);
}
to {
background-color: var(--bg-out, white);
}
}
<button id="add">Add</button>
<div class="container" id="add-target">
<div>#1</div>
<div>#2</div>
<div>#3</div>
</div>

Is there a way to add a delay on a hover efect?

What I would like to accomplish is that when the image changes after the hover it stays like that for a few seconds, and then it returns to the original image.
What I would like to know is if there's a way to add that kind of delay. I have attached my code below.
<html>
<body>
<img src='http://www.freedigitalphotos.net/images/img/homepage/87357.jpg'
width='142' height='162'
onmouseover="this.src='http://7606-presscdn-0-74.pagely.netdna-cdn.com/wp-content/uploads/2016/03/Dubai-Photos-Images-Oicture-Dubai-Landmarks-800x600.jpg';"
onmouseout="this.src=http://7606-presscdn-0-74.pagely.netdna-cdn.com/wp-content/uploads/2016/03/Dubai-Photos-Images-Oicture-Dubai-Landmarks-800x600.jpg';" />
</body>
</html>
Use CSS transitions with the transition-delay property.
.classname {
width: 100px;
height: 100px;
background-color: red;
transition-property: background-color;
transition-delay: 1s;
transition-duration: 0.1s;
}
.classname:hover {
transition-delay: 0s;
background-color: blue;
}
.image {
width: 142px;
height: 162px;
background-image: url('http://www.freedigitalphotos.net/images/img/homepage/87357.jpg');
background-size: 100% 100%;
transition-property: background-image;
transition-delay: 1s;
transition-duration: 0.1s;
}
.image:hover {
transition-delay: 0s;
background-image: url('http://7606-presscdn-0-74.pagely.netdna-cdn.com/wp-content/uploads/2016/03/Dubai-Photos-Images-Oicture-Dubai-Landmarks-800x600.jpg')
}
<div class="classname"></div>
<div class="image"></div>
Change your onmouseout event to call a JS function with setTimeout
setTimeout(function(){
this.src= "...";
}, 5000);
Where 5000 is the time in milliseconds you want to delay.
You could just use CSS transitions.
.button {
background-color: #222;
color: #fff;
padding: 14px 36px;
text-decoration: none;
transition: 0.6s background-color ease
}
.button:hover {
background-color: #555;
}
<a href='#' class='button'>Hover me</a>
See this example to change <img> src with onmouseover event and wait 3's then get back to original image onmouseout
//copy original img to variable
var original = $("img")[0].src;
//mouse over event
$("img").mouseover(function() {
$(this).fadeOut("fast").fadeIn("fast");
//change image
$(this)[0].src = "http://7606-presscdn-0-74.pagely.netdna-cdn.com/wp-content/uploads/2016/03/Dubai-Photos-Images-Oicture-Dubai-Landmarks-800x600.jpg";
});
//mouse out event
$("img").mouseout(function() {
var img = $(this);
//on mouse over wait 3 second and getback to original img
setTimeout(function() {
img.fadeOut("fast").fadeIn("fast");
img[0].src = original;
}, 3000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src='http://www.freedigitalphotos.net/images/img/homepage/87357.jpg' width='142' height='162' />
There is a several ways to do this.
You can try the snippet below:
<div>
<img src='http://7606-presscdn-0-74.pagely.netdna-cdn.com/wp-content/uploads/2016/03/Dubai-Photos-Images-Oicture-Dubai-Landmarks-800x600.jpg' width='142' height='162'/>
<img src='http://www.freedigitalphotos.net/images/img/homepage/87357.jpg' width='142' height='162'/>
</div>
div{
width:142px;
height:162px;
overflow: hidden; /*required*/
}
div img{
position: absolute;
transition: opacity .5s ease;
transition-delay: .5s; /*time of transition that you want*/
}
div img:hover{
opacity: 0;
}
Another way is just use a background of this images and manage each one.
Full example: jsbin

Trigger opacity transition on mouse in and out

I want to trigger a opacity transition. If an element is hovered by the cursor, the cursor shall fade out, change its background-image and then fade in again. I wanted to achieve that by adding and removing a css class. It's not working, what is wrong?
js fiddle
HTML
<div class="wrapper">
<div class="cursor">
</div>
<div id="grey">
</div>
</div>
CSS
.wrapper {
width: 100%;
height: 100%;
background-color: lightgrey;
padding: 60px;
cursor: none;
}
#grey {
width: 100px;
height: 100px;
background: grey;
}
.cursor {
position: fixed;
width: 20px;
height: 20px;
pointer-events: none;
opacity: 0;
-webkit-transition: opacity .3s; /* Safari */
transition: opacity .3s;
}
.red {
background: red;
opacity: 1;
}
.green {
background: green;
opacity: 1;
}
JS
$('.wrapper').on('mousemove', function(e){
$('.cursor').css('left', e.clientX-10).css('top', e.clientY -10);
if ($.contains($('.wrapper')[0], e.target)){
$('.cursor').removeClass('green').addClass('red');
}else{
$('.cursor').removeClass('red').addClass('green');
}
});
DEMO HERE
Ok, here you go. You need to keep track of 2 things here which you already achieved partially and also wait for fadeOut to complete and add a callback for adding and removing respective class
Whether cursor has entered element
Whether cursor has left element
Below is how you could actually do it.
var entered=false;//global variables to show the position of cursor
var left=false;
$('.wrapper').on('mousemove', function(e){
$('.cursor').css('left', e.clientX-10).css('top', e.clientY -10);
if ($.contains($('.wrapper')[0], e.target)){
if(!entered)
{
//just to do it once and not on every mousemove you need to check here whether
//it has already entered and moving inside the element
entered=true;
left=false;//to check the vice versa operation
$('.cursor').fadeOut('fast',function(){
//callback function after fadeOut completes
$(this).removeClass('green').addClass('red');
}).fadeIn('fast');
}
}else{
if(!left)
{
left=true;
entered=false;
//same goes here too
$('.cursor').fadeOut('fast',function(){
$(this).removeClass('red').addClass('green');
}).fadeIn('fast');
}
}
});
you have to change background color , not opacity ( opacity is always 1 )
CSS
.cursor {
position: fixed;
width: 20px;
height: 20px;
pointer-events: none;
opacity: 0;
-webkit-transition: background-color .3s; /* Safari */
transition: background-color .3s ;
}
.red {
background-color: red;
opacity: 1;
}
.green {
background-color: green;
opacity: 1;
}
So you said your question is wrong, it is "no, I just made it easier for hier, in reality it is an background image" - so you transition between two background-images.
Here is how you do it:
You can not do it with CSS transition in ONE element/div
You will have to make two divs wich one background each
Increase the zIndex of the div you want to fade out in by one
Fade out div, while the new div stays at opacity: 1

How can a hover-over element still change other element styles when they're all in separate divs?

I understand that an element can change the style of associated elements upon hovering as long as they're within the same divs, but how can the same functionality be achieved when they're all in separate elements such as div, section, article, h1, etc.
I have set up a jsfiddle that consists of a version that works and a version that doesn't. As best, I would like to find out a way to achieve this through CSS only, but if it is an issue that only javascript can solve, that'll be okay.
I've been looking around StackOverflow but there doesn't seem to be an answer to what to do when the elements are within separate elements.
HTML
<h1>This version works fine...</h1>
... <span class="a1">fruits</span> and <span class="b1">vegetables</span>... <span class="a2">apple</span>, <span class="b2">asparagus</span>
<h1>...but how can I get this to work?</h1>
... <div class="div1"><span class="a1">fruits</span> and <span class="b1">vegetables</span></div>... <div class="div2"><span class="a2">apple</span>, <span class="b2">asparagus</span></div>
CSS
.a1, .b1 {
border:1px solid #333333;
padding: 0 1% 0 1%;
text-align: center;
-o-transition: color 0.2s ease-out;
-ms-transition: color 0.2s ease-out;
-moz-transition: color 0.2s ease-out;
-webkit-transition: color 0.2s ease-out;
transition: color 0.2s ease-out;
}
.a2, .b2 {
border:1px solid #dddddd;
padding: 0 1% 0 1%;
text-align: center;
-o-transition: color 0.2s ease-out;
-ms-transition: color 0.2s ease-out;
-moz-transition: color 0.2s ease-out;
-webkit-transition: color 0.2s ease-out;
transition: color 0.2s ease-out;
}
.a1:hover {
border:1px solid red;
color: white;
background-color: red;
}
.b1:hover {
border:1px solid green;
color: white;
background-color: green;
}
.a1:hover ~ .a2 {
border:1px solid red;
color: white;
background-color: red;
}
.b1:hover ~ .b2 {
border:1px solid green;
color: white;
background-color: green;
}
I've found out what the problem is.
Go to your code, fix or take off the lines below from the problematic part
</div>
<div class="div2">
Two problems
1 Closing DIV without a starting part
1 Opening DIV without closing part
See it working here
For jQuery: you can do something like
$(".a1").hover(function () {
$(".a2, .a1").css({"color":"white", "background-color":"red"});
});
See the jQuery example here
Note: If you have the DIV's there for a reason, try the jQuery method
CSS
.a1:hover, .a2.light { /* your css */ }
.b1:hover, .b2.light { /* your css */ }
JAVASCRIPT
var fruits = document.querySelectorAll('.div2 .a2'),
vegets = document.querySelectorAll('.div2 .b2'),
spanf = document.querySelector('.div1 .a1'),
spanv = document.querySelector('.div1 .b1');
spanf.addEventListener('mouseenter', function() {
[].forEach.call(fruits, function(el) {
el.classList.add('light');
});
});
spanf.addEventListener('mouseleave', function() {
[].forEach.call(fruits, function(el) {
el.classList.remove('light');
});
});
spanv.addEventListener('mouseenter', function() {
[].forEach.call(vegets, function(el) {
el.classList.add('light');
});
});
spanv.addEventListener('mouseleave', function() {
[].forEach.call(vegets, function(el) {
el.classList.remove('light');
});
});
DEMO
NOTE Safari doesn't support mouseenter / mouseleave. You can use mouseover / mouseout instead.
If you prefer a solution with jQUERY (it's less to write, but does the same under the hood):
var fruits = $('.div2 .a2'),
vegets = $('.div2 .b2');
$('.div1 .a1').hover(function() {fruits.toggleClass('light');});
$('.div1 .b1').hover(function() {vegets.toggleClass('light');});

Hover over one div triggers other div hovers inside

Ok working on something and can't seem to figure it out have tried a few different things but nothing seems to solve it. So here is the link to what I'm doing...
http://modocom.ca/logo/
Now what I'm trying to do is have the outer div when you rollover it, it animates all the inner divs at once. Also trying to achieve so can click on the outer div to go to a link.
Here is the HTML...
<div>
<div class="hi-icon-wrap hi-icon-effect-5 hi-icon-effect-5d transition">
modo
</div>
<div class="hi-icon-wrap hi-icon-effect-6 hi-icon-effect-5d transition">
modo
</div>
<div class="hi-icon-wrap hi-icon-effect-5 hi-icon-effect-5d transition">
modo
</div>
<div class="hi-icon-wrap hi-icon-effect-6 hi-icon-effect-5d transition">
modo
</div>
Some of the CSS for the inner hovers...
.hi-icon-effect-5 .hi-icon {
border-top: 5px solid #C30;
overflow: hidden;
-webkit-transition: background 0.3s, color 0.3s, box-shadow 0.3s;
-moz-transition: background 0.3s, color 0.3s, box-shadow 0.3s;
transition: background 0.3s, color 0.3s, box-shadow 0.3s;
}
.hi-icon-effect-6 .hi-icon {
background: rgba(255,255,255,1);
border-top: 5px solid #000;
overflow: hidden;
-webkit-transition: background 0.3s, color 0.3s, box-shadow 0.3s;
-moz-transition: background 0.3s, color 0.3s, box-shadow 0.3s;
transition: background 0.3s, color 0.3s, box-shadow 0.3s;
}
.hi-icon-effect-5 .hi-icon:after {
display: none;
}
.hi-icon-effect-6 .hi-icon:after {
display: none;
}
.hi-icon-effect-7 .hi-icon:after {
display: none;
}
.no-touch .hi-icon-effect-5 .hi-icon:hover {
background: #C30;
color: #FFF; /* Hover Icon */
}
.no-touch .hi-icon-effect-6 .hi-icon:hover {
background: #000;
color: #FFF; /* Hover Icon */
}
Hopefully that makes sense.
You need to add a class to your main div... in this case lets say you add `class=maindiv' to the containing div.
Then in your css use this:
.maindiv:hover .no-touch .hi-icon-effect-5 .hi-icon {
background: #C30;
color: #FFF; /* Hover Icon */
}
.maindiv:hover .no-touch .hi-icon-effect-6 .hi-icon {
background: #000;
color: #FFF; /* Hover Icon */
}
instead of the effects applying when you hover over the .hi-icon the effects apply when you hover over the .maindiv
UPDATE
add this to your css instead of the above:
.maindiv:hover .hi-icon-effect-5 .hi-icon{
background: #C30;
color: #FFF; /* Hover Icon */
}
.maindiv:hover .hi-icon-effect-6 .hi-icon {
background: #000;
color: #FFF; /* Hover Icon */
}
I might be horribly off track, but could you use .addClass to each of those divs when you hover over the main div?
Something like this FIDDLE (I didnt add a class, i just used .animate to get my point accross)
$( "#Activate" ).mouseover(function() {
$("#Activate > .hi-icon-wrap").each(function (index) {
$(this).delay(index * 500).animate({
opacity: 0.5
}, 500);
});
});
$( "#Activate" ).mouseout(function() {
$(".hi-icon-wrap").animate({opacity: 1}, 500);
});
Apologies if this is nothing at all what you were looking for.

Categories

Resources