Do Intersection Observer Animation and Hover effects not work together? - javascript

I'm working on a project that is using Intersection Observer to add animation to an element's style upon entry. However, what I'm noticing is that the : hover attribute no longer works when I apply the style. Am I doing this wrong, or, are these two not compatible? On the JS Fiddle, I've commented out the hover attribute by default. Try uncommenting it and see what happens.
I've tried banner.classList.add(/new class in here/) but that method also took away the :hover as well.
DEMO:
Demo

disable animation on hover because animations has a higher specificity
const options = {
root: null,
threshold: 1,
};
const banner = document.querySelector('.product-banner');
const observerAnim = new IntersectionObserver(function(entries, observer) {
entries.forEach(entry => {
if (!entry.isIntersecting) {
return;
}
banner.style.animation = '1s ease-in-out home-page-fade';
banner.style.animationFillMode = 'forwards';
observer.unobserve(banner);
});
}, options);
observerAnim.observe(banner);
body {
background-color: #fff;
min-height: 2000px;
}
img.product-banner {
opacity:0;
position: relative;
top: 1000px;
-moz-transition: all ease 0.3s;
-webkit-transition: all ease 0.3s;
transition: all ease 0.3s;
}
#keyframes home-page-fade {
0% {
transform: translateY(50%);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
img.product-banner:hover {
animation: none !important;
opacity: 0.8;
transform: scale(0.9);
-moz-transition: all ease 0.3s;
-webkit-transition: all ease 0.3s;
transition: all ease 0.3s;
}
<h1>
Scroll Effect
</h1>
<img class="product-banner" src="https://cdn.mos.cms.futurecdn.net/bQgcMwEnyhFu6ASuUFrtsn-1024-80.jpg" width="300">

Related

CSS Animated icons appearing on page load and popping in before animating properly

I'm trying to create a draft for a mobile website interface but I'm having some strange issues with the menu. Initially when the page loads it should display a blank footer except for a plus icon. When clicked, the plus icon expands and various other icons pop up that link to different parts of the interface. However, when I load the page these icons are visible. Further, when I try to expand and shrink the menu bar for the first time they disappear. However, if I then expand it again they pop in for a moment before vanishing then expanding like I expect.
I'm not sure why the transition effect works one way and not the other. I've tried messing with the timing of the opacity and visibility properties in the keyframes but so far it's still displaying this weird behavior. I've also tried adding a class that makes the elements hidden on page load and removing it the first time they're animating but that doesn't fix the pop in on subsequent cycles. I've included the relevant sections of the code below and a codepen of everything. I've slowed down the icon animations for the moment so it's easier to see their behavior.
JS
const mobile_menu = (() => {
const expandNavigation = (navButton, navBar, buttons) => {
navButton.addEventListener('click', () => {
let buttonType = ['slow', 'fast', 'fast', 'slow'];
if (navButton.classList.contains('clicked')) {
navButton.classList.add('unclicked');
navButton.classList.remove('clicked');
navBar.classList.add('retract');
navBar.classList.remove('expand');
for (let i = 0; i < buttons.length; i++) {
showButton(buttons[i], buttonType, 'retract');
}
}
else {
navButton.classList.add('clicked');
navButton.classList.remove('unclicked');
navBar.classList.add('expand');
navBar.classList.remove('retract');
for (let i = 0; i < buttons.length; i++) {
showButton(buttons[i], buttonType, 'expand');
}
}
});
}
const showButton = (button, type, direction) => {
if (direction === 'retract') {
if (type === 'slow') {
button.classList.remove('icon_appear_slow');
button.classList.add('icon_vanish_slow');
}
else {
button.classList.remove('icon_appear_fast');
button.classList.add('icon_vanish_fast');
}
}
else {
if (type === 'slow') {
button.classList.remove('icon_vanish_slow');
button.classList.add('icon_appear_slow');
}
else {
button.classList.remove('icon_vanish_fast');
button.classList.add('icon_appear_fast');
}
}
}
return { expandNavigation };
})();
HTML
<div class="screen">
<div class="page">Content</div>
<div class="nav_menu">
<span id="nav_bar"></span>
<div class="nav_button">
<i class = "material-icons call">call</i>
</div>
<div class="nav_button">
<i class = "material-icons message">chat</i>
</div>
<div class="nav_icon">
<i id="open_close" class = "material-icons unclicked">add</i>
</div>
<div class="nav_button">
<i class = "material-icons account">person</i>
</div>
<div class="nav_button">
<i class = "material-icons settings">settings</i>
</div>
</div>
</div>
CSS
.icon_appear_slow {
animation: grow 1s ease-in-out 2s 1 normal forwards;
}
.icon_appear_fast {
animation: grow 2s ease-in-out 1s 1 normal forwards;
}
.icon_vanish_slow {
animation: shrink 1s ease-in-out 2s 1 normal forwards;
}
.icon_vanish_fast {
animation: shrink 2s ease-in-out 1s 1 normal forwards;
}
#keyframes grow {
0% {
transform: rotate(0deg) scale(0.1);
visibility: hidden;
opacity: 0;
}
1% {
visibility: visible;
}
100% {
transform: rotate(360deg) scale(1);;
opacity: 1;
}
}
#keyframes shrink {
0% {
transform: rotate(0deg) scale(1);
visibility: visible;
opacity: 1;
}
99% {
visibility: hidden;
}
100% {
transform: rotate(-360deg) scale(0.1);
opacity: 0;
}
}
Change id="nav_bar" to class="nav_bar"
i dont really know but its not saving the changes with id
on the js part:
just change const navBar = document.getElementById('nav_bar');
to
const navBar = document.querySelector('.nav_bar');
on the css part:
.retract {
height: 60px;
width: 350px;
animation: retraction 0.3s ease-in-out 2.5s 1 normal forwards;
}
.icon_vanish_fast {
opacity:1;
animation: shrink 2s ease-in-out 1s 1 normal forwards;
}
.icon_vanish_slow {
opacity:1;
animation: shrink 1s ease-in-out 2s 1 normal forwards;
}
.nav_bar {
display: table-cell;
vertical-align: middle;
height: 50px;
width: 50px;
text-align: center;
background: rgb(30, 134, 30);
border-radius: 50%;
display: inline-block;
font-weight: bold;
font-size: 1.2em;
margin: 0 auto;
position: absolute;
}
.nav_button {
opacity:0;
}

CSS bug with transition on opacity, blur, and over-flow hidden on parent

I wrote an simple function which implements opacity on a blurred image on mouseover.
Note that parent is smaller than child(image), I need over-flow hidden.
You can see a bug, at the end of transition, the image size changes suddenly!
the problem disappears if I delete transition, (but I want transition)
the problem disappears if I supp blur (but I want blur)
the problem disappears if parent is bigger than child (but I want parent smaller with over-flow hidden)
there is a accumulation of parameter (opacity-transition, blur, overflow hidden on parent) which creates a bug, and I don't know how to fix it.
var my_parent = document.querySelector('.parent');
var my_child = document.querySelector('.child');
my_parent.addEventListener('mouseover', function() {
my_child.style.opacity = '1';
// SAME PROBLEM WITH ANIMATION
// my_child.style.animationName = 'my_animation';
// my_child.style.animationDuration = '1s';
// my_child.style.animationTimingFunction = 'ease-in-out';
// my_child.style.animationIterationCount = 'linear';
// my_child.style.webkitAnimationPlayState = 'running';
// my_child.style.animationFillMode = 'forwards';
});
.parent {
width: 200px;
height: 200px;
overflow: hidden;
}
.child {
width: 250px;
height: 250px;
opacity: 0;
-moz-filter: blur(40px);
-o-filter: blur(40px);
-ms-filter: blur(40px);
filter: blur(40px);
-webkit-transition: opacity 0.5s ease-out;
-moz-transition: opacity 0.5s ease-out;
-o-transition: opacity 0.5s ease-out;
transition: opacity 0.5s ease-out;
}
#-webkit-keyframes my_animation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes my_animation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<div class="parent">
<img class="child" src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg">
</div>

CSS3 not working when trigered by Javascript

I'm trying to make an splash loading with CSS/HTML/JS, but am having some problems.
The problem is when trying to make the splash screen disappear with a transition effect, but the transition effect isn't applying.
I am sure my JavaScript is work properly, as it appends the new class not-displayed to the div element.
const splash = document.querySelector('.splash');
console.log(splash);
document.addEventListener('DOMContentLoaded', (e) => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
.splash {
z-index: 100000;
position: fixed;
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffff;
}
//all of these code not working
.splash.not-displayed {
z-index: 20;
opacity: 0;
position: fixed;
height: 100vh;
width: 100%;
background-color: #f06c65;
transition: all 0.5298s ease-out;
-webkit-transition: all 0.5298s ease-out;
-moz-transition: all 0.5298s ease-out;
-o-transition: all 0.5298s ease-out;
}
#keyframes fadein {
to {
opacity: 1;
}
}
.fade-in {
opacity: 0;
animation: fadein 1s ease-in forwards;
}
<div class="splash">
<h1 class="fade-in">
hello
</h1>
</div>
You have two things going on here, a transition and an animation. First I removed a lot of unnecessary CSS code to make things clearer.
Your code is working as expected. When the page loads, the "fadein" animation is triggered by the fade-in class. The text "hello" fades in from opacity 0 to opacity 1 over the course of a second, as expected.
Meanwhile, your Javascript triggers on page load and adds the class not-displayed to the outer div after two seconds. This triggers the transition effect, which after half a second applies a red background to the div as it fades the div out, bringing it back to opacity 0.
I'm not sure what specifically you are trying to achieve here, but you have wired up a successful transition and animation effect.
const splash = document.querySelector('.splash');
console.log(splash);
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
.splash.not-displayed {
opacity: 0;
background-color: #f06c65;
transition: all 0.5298s ease-out;
}
.fade-in {
opacity: 0;
animation: fadein 1s ease-in forwards;
}
#keyframes fadein {
to {
opacity: 1;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="splash">
<h1 class="fade-in">
hello
</h1>
</div>
In your code
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
you are adding new class to remove the .splash and then add new class not-displayed
Everything is working just fine, except you have given opacity: 0 to the not-displayed class.
const splash = document.querySelector('.splash');
console.log(splash);
document.addEventListener('DOMContentLoaded', (e) => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
.splash {
z-index: 100000;
position: fixed;
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffff;
}
.not-displayed {
z-index: 20;
/* opacity: 0; */
position: fixed;
height: 100vh;
width: 100%;
background-color: #f06c65;
transition: all 0.5298s ease-out;
-webkit-transition: all 0.5298s ease-out;
-moz-transition: all 0.5298s ease-out;
-o-transition: all 0.5298s ease-out;
}
#keyframes fadein {
to {
opacity: 1;
}
}
.fade-in {
opacity: 0;
animation: fadein 1s ease-in forwards;
}
<div class="splash">
<h1 class="fade-in">
hello
</h1>
</div>
Codepen
You should set the transition to .splash not to .splash.not-displayed

Make a hamburger ID work in two headers

I am creating a clone of the header and when the scroll reach a certain height, the clone version will display. This works, as I want. The problem is that I am trying to get the “hamburger” action to work in both headers. Now it only works in first section. I need to get it working in section two also. I know I have used an ID (“trigger-overlay”), which should only be used one time and be unique.
Is this correct and the reason why it is not working? Do you guys know a workaround to fix this problem?
I need it to be an ID because of a more complex code in another script, but if it’s not possible to keep it I will do it in another way. I appreciate any help here. See JSFiddle
HTML
<section id="one">
<header class=""> <a id="trigger-overlay" class=""><span class="hamburger"></span></a>
</header>
</section>
<section id="two"></section>
CSS
section {
height:100vh;
}
#one{
background-color:#0097a7;
}
#two{
background-color:#00bcd4;
}
.hamburger, #trigger-overlay .hamburger:before, #trigger-overlay .hamburger:after {
cursor: pointer;
background-color:#80deea;
width:25px;
height:3px;
display:block;
border-radius:6px;
-webkit-transition:top 0.3s 0.2s ease, bottom 0.3s 0.2s ease, background-color 0.3s ease, -webkit-transform 0.3s ease;
transition:top 0.3s 0.2s ease, bottom 0.3s 0.2s ease, background-color 0.3s ease, transform 0.3s ease;
}
#trigger-overlay {
float: left;
margin-left:15px;
}
.hamburger:before, .hamburger:after {
content:"";
position:absolute;
}
.hamburger {
position:relative;
top:19px;
}
.hamburger:before {
top:-7px;
}
.hamburger:after {
bottom:-7px;
}
/*Hamburger hover*/
#trigger-overlay .hamburger:hover, #trigger-overlay .hamburger:hover:before, #trigger-overlay .hamburger:hover:after {
background-color: #00838f;
}
header {
position: relative;
width: 100%;
height: 60px;
background-color:#00acc1;
}
header.clone {
position: fixed;
background-color: #00acc1;
top: 0px;
left: 0;
right: 0;
transform: translateY(-100%);
transition: 0.2s transform cubic-bezier(.3, .73, .3, .74);
}
body.down header.clone {
transform: translateY(0);
}
Vanilla JS
var triggerBttn = document.getElementById( 'trigger-overlay' );
var sticky = {
sticky_after: 200,
init: function () {
this.header = document.getElementsByTagName("header")[0];
this.clone = this.header.cloneNode(true);
this.clone.classList.add("clone");
this.header.insertBefore(this.clone, this.header.childNodes[1]);
this.scroll();
this.events();
},
scroll: function () {
if (window.scrollY > this.sticky_after) {
document.body.classList.add("down");
} else {
document.body.classList.remove("down");
}
},
events: function () {
window.addEventListener("scroll", this.scroll.bind(this));
}
};
function toggleOverlay() {
alert("I want to be active in both headers ");
}
triggerBttn.addEventListener( 'click', toggleOverlay );
document.addEventListener("DOMContentLoaded", sticky.init.bind(sticky));
Unfortunately just using the same ID won't give you the same EventListeners. But, it's easy to get around your problem by simply adding the same EventListeners to the newly created clone:
document.getElementsByClassName('clone')[0].addEventListener('click', toggleOverlay);
See a working version of your Fiddle here: http://jsfiddle.net/qfbq2b0k/4/

Sliding and fading a div element

I am trying to animate a div element (slide and fade) with a button click. At first, the element is not visible to a user. When the button is clicked, it will slide to right and fade in. Once the button is clicked again, it will slide to left and fade out. I come up with two solutions, with css and with JQuery.
In the first one, I used JQuery. You can find the example in this JSFiddle 1.
HTML
<button id="my-button">Click me!</button>
<div id="my-modal"></div>
CSS
#my-modal {
opacity: 1;
position: fixed;
top: 50px;
left: 0;
left: -250px;
width: 250px;
height: 100%;
background-color: red;
}
JQuery
$("#my-button").click(function () {
var $modal = $("#my-modal");
$modal.stop(true, true).animate({
left: "toggle",
opacity: "toggle"
}, 1000);
});
Here, everything seems working but it does directly opposite of what I want. It first fades out, and with the second click, it fades in. It is because that the opacity of the element is 1, but if I turn it to 0, nothing happens.
Secondly, I tried to do that with css animation by using key-frames (changing opacity from 0 to 1) but it has also problem. It starts the animation exactly the way I want. However, when I click the button again, it disappears immediately. Here is the JSFiddle 2.
HTML
<button id="my-button">Click me!</button>
<div id="my-modal"></div>
CSS
#my-modal {
opacity: 0;
position: fixed;
top: 50px;
left: 0;
left: -250px;
width: 250px;
height: 100%;
background-color: red;
-moz-transition: all 1s ease;
-webkit-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
}
.move-my-modal {
-moz-transform: translate(250px, 0px);
-webkit-transform: translate(250px, 0px);
-ms-transform: translate(250px, 0px);
-o-transform: translate(250px, 0px);
}
.animate-opacity {
-webkit-animation: toggle-opacity 1s ease;
-moz-animation: toggle-opacity 1s ease;
-o-animation: toggle-opacity 1s ease;
animation: toggle-opacity 1s ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-o-keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
JQuery
$("#my-button").click(function () {
var $modal = $("#my-modal");
$modal.toggleClass("move-my-modal");
$modal.toggleClass("animate-opacity");
});
To this end, I have these questions;
1) What are the problems with these two approaches? Is there something that I missed or forgot to use? How can I correct them to meet the requirements that I mentioned at the beginning.
2) Which one is the better way to make this action? Is there any cons or pros of these approaches?
3) Is there any other way to make this action? I am new on this area and I might not notice a simpler way.
You can toggle an .active class to the element and use CSS transitions.
This way, if the browser is old enough to not support animations, it will still work but it won't slow down computers that do not handle animations well.
$("#my-button").click(function () {
$("#my-modal").toggleClass('active');
});
#my-modal.active {
opacity: 1;
left: 0;
}
$("#my-button").click(function () {
$("#my-modal").toggleClass('active');
});
#my-modal {
opacity: 0;
position: fixed;
top: 50px;
left: -250px;
width: 250px;
height: 100%;
background-color: red;
transition: all 1s linear;
}
#my-modal.active {
opacity: 1;
left: 0;
}
<button id="my-button">Click me!</button>
<div id="my-modal"></div>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Categories

Resources