Example
i need to make divs appear like this, or any other fancy way. Can someone provide source or something that can help?
We can add the class name of a CSS attribute with a transition, and animate property to switch it from an opacity: 0 element to an opacity: 1 element, and assign it an animation attribute that slides it in using the CSS transform property.
We can use getBoundingClientRect and scrollTop to check when the element is in view, and add the class when it is.
This gives us something close to the desired effect.
document.addEventListener("scroll", (event) => {
const elementsToAnimate = Array.from(document.querySelectorAll(".stationary"));
for (element of elementsToAnimate) {
const {
scrollTop
} = document.querySelector("html");
const {
top
} = element.getBoundingClientRect();
const containsAnimateClass = element.classList.contains("from-left");
if (top < scrollTop / 2 && !containsAnimateClass)
element.classList.add("from-left");
}
});
body {
display: flex;
flex-direction: column;
gap: 1rem;
}
.stationary {
opacity: 0;
width: 100px;
height: 100px;
background: red;
}
.from-left {
transition: 1s ease;
opacity: 1;
animate: 1s ease slide-in-from-left;
}
#keyframes slide-in-from-left {
from {
transform: translateX(-50%);
}
to {
transform: translateX(0);
}
}
<body>
<div>Scroll!</div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
<div class="stationary"></div>
</body>
You can use simple libraries already implemented these animations:
https://github.com/matthieua/WOW
https://scrollrevealjs.org/
https://scrollmagic.io/examples/basic/reveal_on_scroll.html
https://michalsnik.github.io/aos/
(I personally love this, its easy to use)
Or in other hand make your own animation.
add event listener for scroll and create a keyframe animation. Then assign the class to the element when scroll reached to your desire number.
Related
I made a simple slide show with divs stacked one on top of the other.
I switch the div on display with display:none or display:block.
But when I add animations, I encounter a problem. The fade in works, but I have no idea how to fade out a vanishing slide. The slide just disappears and I can't get any fade out method that I have found to work. Where is the error please?
let pages = document.getElementsByClassName("page");
let buttons = document.getElementsByClassName("page-button");
let currentPage = 0;
pages[currentPage].style.display = "block";
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", () => changePage(i));
}
function changePage(k) {
pages[currentPage].style.display = "none";
pages[k].style.display = "block";
currentPage = k;
}
.content-container {
display: flex;
height: 90vh;
}
.page {
position: absolute;
display: none;
width: 100%;
height: 100%;
animation: fadeIn 3s;
}
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#slideshow {
flex-grow: 1;
position: relative;
}
<div class="content-container">
<div id="slideshow">
<div class="page" style="background-color: red;"></div>
<div class="page" style="background-color: green;"></div>
<div class="page" style="background-color: blue;"></div>
</div>
<button class="page-button">1</button>
<button class="page-button">2</button>
<button class="page-button">3</button>
</div>
For animation I use the library called Animate.css. Take a look at the following link:
https://animate.style/
You can install this library with NPM:
npm install animate.css --save
Then you can use this library like this:
<div class="page animate__fadeOutLeft" style="background-color: green;">
The issue is that you are using a display none, which will instantly remove the coloured block and fade in from white.
On click set the background colour of the 'content-container' to the item's colour to be removed, giving the impression of fading in from that colour.
var contentContainer = document.getElementsByClassName("content-container");
var replaceColour = pages[k].styles.getPropertyValue("background-color")
contentContainer.style.backgroundColor = replaceColour;
my scenario: I have basic image 100x50px. I have one hover jpeg image 300x150 px and it has 9 areas (3x3, each area is 100x50 px and has another image inside). Until there is no on hover event, just another image is shown. Now I am trying to do that on hover these 9 areas changes one by one after 0.3second in cyclic way. Once mouse is not on hover, first image appears back.
<div class="thumb">
<a href="click.php"><img src="image.jpg">
<img class="hovered" src="hover.jpg" style="margin-top: 0%; margin-left: 0%; display: none;">
</a>
</div>
<div class="thumb">
<a href="click.php"><img src="another.jpg">
<img class="hovered" src="hovX.jpg" style="margin-top: 0%; margin-left: 0%; display: none;">
</a>
</div>
how could I do this please?
(I think I should somehow call javascipt function to display hovered class and start changing position of image each 0.3s. But no idea how..)
MY IMAGES:
first image without hover:
3x3 hover source image:
on hover images cycle like this:
then after 0.3s
then after another 0.3s
etc
(numbers are just for reference)
final effect should look like when mouse on hover:
when mouse is not on hover then this image is shown
You could achieve this using css.
First, put the images into a container element.
<div id="img-container">
<div class="hover-img"/>
<div class="hover-img"/>
<div class="hover-img"/>
<div class="hover-img"/>
<div class="hover-img"/>
<div class="hover-img"/>
<div class="hover-img"/>
<div class="hover-img"/>
<div class="hover-img"/>
</div>
Now you can set the size and background image of each element in css:
#img-container {
width: 300px;
height: 150px;
}
.hover-img {
width: 100px;
height: 50px;
display: inline-block;
background-image: url('image.jpg');
background-size: cover;
transition: background-image 0.3s;
}
I added a transition of 0.3 seconds to the background image so the image will change gradually when we hover over the container. To apply the change on mouse hover, we can set a different image for the hover state of the container. This means that every image will transition to the new image when the container div is hovered over.
#img-container:hover>.hover-img {
background-image: url('hover.jpg');
}
Now you want each image to change one-by-one. To do this, you can add a transition delay. You can use css nth-child to target each image directly, though this is a bit long winded and might be better done programmatically with javascript.
.hover-img:nth-child(2) {
transition-delay: 0.3s;
}
.hover-img:nth-child(3) {
transition-delay: 0.6s;
}
.hover-img:nth-child(4) {
transition-delay: 0.9s;
}
.hover-img:nth-child(5) {
transition-delay: 1.2s;
}
.hover-img:nth-child(6) {
transition-delay: 1.5s;
}
.hover-img:nth-child(7) {
transition-delay: 1.8s;
}
.hover-img:nth-child(8) {
transition-delay: 2.1s;
}
.hover-img:nth-child(9) {
transition-delay: 2.4s;
}
I'm not sure if this exactly what you want but I hope it gives some idea of how you could achieve what you want using pure css.
Is this what you meant (but with images)? You can use onmousover and onmouseout attributes to trigger your animation.
const container = document.getElementById("container");
//instead of colors you'd use source urls
const colors = ["blue","red","green","orange","pink","gold","purple","brown","yellow"];
for (let i = 0; i < 9; i++) {
const div = document.createElement("div");
//instead of color you'd add src attribute
div.style.backgroundColor = colors.shift();
div.classList.add("square");
if(i === 0) div.classList.add("active");
container.append(div);
}
let interval;
function animation() {
let i = 2;
container.children[0].classList.toggle("active")
container.children[1].classList.toggle("active");
interval = setInterval(()=>{
if(container.children[i]) {
container.children[i - 1].classList.toggle("active")
container.children[i].classList.toggle("active");
i++
} else {
container.children[0].classList.toggle("active")
container.children[i - 1].classList.toggle("active")
i = 1;
}
},300)
}
function reset() {
clearInterval(interval);
for(let i = 0; i < container.children.length; i ++){
const child = container.children[i];
if(child.classList.contains("active")) child.classList.toggle("active");
if(i === 0)child.classList.toggle("active");
}
}
#container {
width: 300px;
height: 150px;
display: flex;
flex-wrap: wrap;
cursor: pointer;
}
.square {
width: 100px;
height: 50px;
opacity: 0;
pointer-events: none;
}
.active {
opacity: 1;
}
<div id="container" onmouseover="animation()" onmouseout="reset(this)"></div>
I have an alert box that I want to use sessionStorage so that it only appears once. When the user clicks to close the alert, I want the box to disappear (display:none) but fade-out.
I read that you have to use two different functions - one that is activated when clicked and starts the transition and another the adds the 'display' style once transitioned. However, I can't get that to work:
<style>
.ddAlert {
padding: 20px;
box-sizing: border-box;
background-color: #f0ad4e;
color: #fff;
opacity: 1;
transition: opacity 1s;
}
.hide {
opacity: 0;
display: none;
}
</style>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
let dismissed = sessionStorage.getItem("dismissed");
let alertDiv = document.getElementById("alert");
let dismissButton = document.getElementById("dismiss");
if (!dismissed) {
alertDiv.classList.remove("hide");
}
alertDiv.addEventListener("click", function() {
this.style.display = "block";
}.bind(alertDiv));
alertDiv.addEventListener("transitionend", function() {
if (this.className == "hide") {
this.style.display = "none";
}
sessionStorage.setItem("dismissed", true);
}.bind(alertDiv));
});
</script>
<div class="ddAlert hide" id="alert">
SOME ANNOYING ALERT HERE!
<button type="button" id="dismiss">X</button>
</div>
You are on the right track. Instead of listening on click on the alert, use the button as I assume it is there for that reason. When clicking the button the .hide class should be added to the alert. This will start the transition from opacity: 1; to opacity: 0;.
I suggest that instead of using inline-styles, that you stick to classes. Inline styles are hard to overwrite and prevents you from utilizing the full power of CSS. So I've added some classes in there to help you out.
Try out the example below.
<div class="ddAlert hidden" id="alert">
SOME ANNOYING ALERT HERE!
<button type="button" id="dismiss">X</button>
</div>
.ddAlert {
display: block;
transition: opacity 1s;
}
.hide {
opacity: 0;
}
.hidden {
display: none;
}
document.addEventListener("DOMContentLoaded", function() {
let dismissed = sessionStorage.getItem("dismissed");
let alertDiv = document.getElementById("alert");
let dismissButton = document.getElementById("dismiss");
if (!dismissed) {
alertDiv.classList.remove("hidden");
}
dismissButton.addEventListener("click", function() {
alertDiv.classList.add("hide");
});
alertDiv.addEventListener("transitionend", function({ target }) {
if (target.classList.contains("hide")) {
target.classList.add("hidden");
}
sessionStorage.setItem("dismissed", true);
});
});
This answer greatly lends from this SO question titled CSS3 Transition - Fade out effect which notes
When showing the element (by switching to the visible class), we want
the visibility:visible to kick in instantly, so it’s ok to transition
only the opacity property. And when hiding the element (by switching
to the hidden class), we want to delay the visibility:hidden
declaration, so that we can see the fade-out transition first. We’re
doing this by declaring a transition on the visibility property, with
a 0s duration and a delay.
I chose not to mark this question as a duplicate because it also involves the transitionend event. Additionally, I've focused only on the essence of the transition, with a minimal illustration.
The crucial element is the .dismissed-saved class.
let alertDiv = document.getElementById("alert");
let dismissButton = document.getElementById("dismiss");
dismissButton.addEventListener("click", function() {
// kick in the transition
alertDiv.classList.add("dismissed-saved");
// *this is where state should be committed
});
alertDiv.addEventListener("transitionend", function({
target
}) {
if (target === alertDiv) {
// clean up and show a nifty text message illustrating the event handler.
target.classList.add("hidden");
target.classList.remove("dismissed-saved");
document.getElementById("dismissed").classList.remove('hidden');
}
});
.ddAlert {
padding: 20px;
box-sizing: border-box;
background-color: #f0ad4e;
color: #fff;
opacity: 1;
}
.hidden {
display: none;
}
.dismissed-saved {
visibility: hidden;
opacity: 0;
transition: visibility 0s 2s, opacity 2s linear;
}
<div class="ddAlert" id="alert">
SOME ANNOYING ALERT HERE!
<button type="button" id="dismiss">X</button>
</div>
<div id="dismissed" class="hidden">
Dismissed!
</div>
Good luck!
trying to make a button like this: https://gyazo.com/9afbd559c15bb707a2d1b24ac790cf7a. The problem with the code right now is that it works as it is supposed to on the first time; but after that, instead of going from left to right as intented, it goes from right to left to right.
HTML
<div class="btn-slide block relative mx-auto" style="overflow: hidden; width: 12rem;">
<span class="z-10">View Pricing</span>
<span class="slide-bg block absolute transition" style="background-color: rgba(0,0,0,.1); z-index: -1; top: 0; left:-10rem; width: 10rem; height: 3rem;"></span>
</div>
Javascript
const btns = document.querySelectorAll(".btn-slide");
const slide = document.getElementsByClassName('slide-bg');
btns.forEach(function(btn) {
btn.addEventListener('mouseout', function () {
slide[0].style.transform = 'translateX(230%)';
slide[0].style.transform = 'none';
})
btn.addEventListener('mouseover', function() {
slide[0].style.transform = 'translateX(80%)';
}, true)
})
Unless you have to compute a value in JavaScript (like the height of an element).
Use CSS classes as modifiers (is-hidden, is-folded, is-collapsed, ...).
Using JavaScript, only add/remove/toggle the class
yourElement.addEventListener(
"mouseenter",
function (event)
{
yourElement.classList.remove("is-collapsed");
}
);
yourElement.addEventListener(
"mouseleave",
function (event)
{
yourElement.classList.add("is-collapsed");
}
);
is-collapsed is only an exemple, name it according to your class naming standard.
You're probably going to need a bit more code than what you're showing, as you have two mutually exclusive CSS things you want to do: transition that background across the "button" on mouseenter/mouseout, which is animated, and then reset the background to its start position, which should absolutely not be animated. So you need to not just toggle the background, you also need to toggle whether or not to animation those changes.
function setupAnimation(container) {
const fg = container.querySelector('.label');
const bg = container.querySelector('.slide-bg');
const stop = evt => evt.stopPropagation();
// step one: make label text inert. This is critical.
fg.addEventListener('mouseenter', stop);
fg.addEventListener('mouseout', stop);
// mouse enter: start the slide in animation
container.addEventListener('mouseenter', evt => {
bg.classList.add('animate');
bg.classList.add('slide-in');
});
// mouse out: start the slide-out animation
container.addEventListener('mouseout', evt => {
bg.classList.remove('slide-in');
bg.classList.add('slide-out');
});
// when the slide-out transition is done,
// reset the CSS with animations _turned off_
bg.addEventListener('transitionend', evt => {
if (bg.classList.contains('slide-out')) {
bg.classList.remove('animate');
bg.classList.remove('slide-out');
}
});
}
setupAnimation(document.querySelector('.slide'));
.slide {
position: relative;
overflow: hidden;
width: 12rem;
height: 1.25rem;
cursor: pointer;
border: 1px solid black;
text-align: center;
}
.slide span {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.slide-bg {
background-color: rgba(0,0,0,.1);
transform: translate(-100%, 0);
transition: none;
z-index: 0;
}
.slide-bg.animate {
transition: transform 0.5s ease-in-out;
}
.slide-bg.slide-in {
transform: translate(0%, 0);
}
.slide-bg.slide-out {
transform: translate(100%, 0);
}
<div class="slide">
<span class="label">View Pricing</span>
<span class="slide-bg"></span>
</div>
And thanks to browsers being finicky with rapid succession mouseenter/mouseout events, depending on how fast you move the cursor this may not even be enough: you might very well still need a "step" tracker so that your JS knows which part of your total animation is currently active, and not trigger the mouseout code if, by the time the slide-in transition ends, the cursor is in fact (still) over the top container (or, again).
I advice you use the .on event listener
$('').on("mouseentre","elem",function(){$('').toggleclass('.classname')})
$('').on("mouseleave","elem",function(){$('').toggleclass('.classname')})
Then you can toggle css classes to your element in the function
toggle class adds the css of a class to your jquery selection, you can do it multiple times and have keyframes for animation in the css class
Keyframes are great way to implement animation and are supported on every browers
First post, so hopefully it is clear enough.
I have been tasked to create a modal object that overlays a multi-column/-row grid layout on a page. The modal should appear on hover of a particular grid item. When the modal appears, the background of the grid area only should dim. I was asked not to use any additionally libraries (e.g., jQuery).
To complete this task, I added two modal objects, one for the actual modal window and the other for the dimmer object. I could not get the CSS hover to work for both objects on the hover of the item in question, so I used JavaScript to add the CSS changes.
The transition effect works for the transition in but not the transition out. I assume I am overthinking this task so appreciate any suggestions.
<style type="text/css">
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 10px;
margin: 0;
padding: 0;
}
.column {
background-color: hsl(0,80%,70%);
}
#modal_maker {
font-size: 5vw;
height: 100%;
width:100%;
display:flex;
align-items: center;
justify-content: center;
}
#modal_maker, #modal {
z-index: 2;
}
#modal {
visibility: hidden;
background-color: hsl(200,50%,70%);
width: 80%;
height: 80%;
position: absolute;
margin: auto;
top: 0; left: 0; bottom: 0; right: 0;
opacity: 0;
transition: opacity 1s;
}
#background-dimmer {
visibility: hidden;
background-color: black;
width: 100%;
height: 100%;
position: absolute;
z-index: 1;
opacity: 0;
transition: opacity 0.5s;
}
</style>
<body>
<div class="container">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column" id="modal_maker">Hover Here</div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div id="modal"></div>
<div id="background-dimmer"></div>
</div>
<script type="text/javascript">
document.querySelector(".container").addEventListener("mouseover", function(el) {
if (el.target.id=="modal_maker" || el.target.id=="modal") {
document.getElementById("modal").style.cssText = "visibility:visible; opacity: 1;"
document.getElementById("background-dimmer").style.cssText = "visibility:visible; opacity: 0.75;"
} else {
document.querySelectorAll("#modal, #background-dimmer").forEach(x => x.style.cssText="opacity: 0; visibility:hidden;")
}
})
</script>
</body>
Its all because of visibility:hidden
in js
...
} else {
document.querySelectorAll("#modal, #background-dimmer").forEach(x => x.style.cssText="opacity: 0; visibility:hidden;")
}
...
in instant way you change opacity to 0 but also visibility:hidden so there is no time for transition, right away when code fires element is hiding.
You use cssText to change properties of element so visibility:visible won't be there when you move mouse on the other element, instead there will be visibility:hidden from the css(so you need to delete that also).
I know that it casues #modal to capture mouseover event then... thats the problem to figure out
I don't know if this solution is on purpose to hide modal when you mouseover other element only, what if I will leave mouse entirely from the table, the modal will stay... just wanted to mention maybe its not relevent.
I made fiddle based on your code: https://jsfiddle.net/svh6dpfk/1/
One idea to fix this #modal capturing event is adding proper visibility as a callback(there is transitionend event which will capture moment when animation is done, so something like this would help:
document.querySelector("#modal, #background-dimmer").addEventListener("transitionend", function(el) {
if(parseFloat(el.target.style.opacity) > 0){
el.target.style.cssText = "visibility:visible;opacity:1";
alert("animation end visible");
}else{
el.target.style.cssText = "visibility:hidden;opacity:0";
alert("animation end unvisible");
}
});
Update
it does work right now for me...
its a bit tricky, your css needs to have visibility:hidden for modal and background-dimmer(like your code has)
this seems to work for me:
document.querySelector(".container").addEventListener("mouseover", function(el) {
if (el.target.id=="modal_maker" || el.target.id=="modal") {
document.getElementById("modal").style.cssText = "visibility:visible;opacity: 1;"
document.getElementById("background-dimmer").style.cssText = "visibility:visible;opacity: 0.75;"
} else {
if(document.getElementById("modal").style.opacity == "1"){
document.querySelectorAll("#modal, #background-dimmer").forEach(x => x.style.cssText="visibility:visible;opacity: 0; ")
}
/* alert("should be on leave") */;
}
})
this part .forEach(x => x.style.cssText="visibility:visible;opacity: 0; ") changes because your css has always visibility:hidden, so you need to perform transition always on visible.
full example:
https://jsfiddle.net/Loary65w/1/
you need to remember to have cross browser support you need to cover all those events
webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend
Hope it helps. Maybe there is better solution much simpler and I overcomplicated that one :F