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;
Related
The result should be a hamburger menu with slides in from the right on clicking the icon.
This is the code for the main menu where I translate it to the right 100% and when I click on the icon it translates back to 0% bringing it on screen
HTML
<div id="mobilenav" class="mobile-nav">
<div class="mobile-nav-header">
</div>
<div class="hamburger">
<button (click)="closeMenu()">
<img src="../../assets/icons/close-menu.svg" alt="" />
</button>
</div>
</div>
<ul class="links">
</ul>
<div class="socials">
</div>
</div>
.mobile-nav {
height: 100vh;
top: 0;
position: absolute;
transform: translateX(100%);
right: 0;
transition: 0.5s;
background: white;
z-index: 99;
}
The JS
openMenu() {
var mobile_menu = document.getElementById('mobilenav');
mobile_menu!.style.transform = 'translateY(0px)';
// mobile_menu!.style.display = 'block';
}
closeMenu() {
var mobile_menu = document.getElementById('mobilenav');
mobile_menu!.style.transform = 'translateX(100%)';
// mobile_menu!.style.display = 'none';
}
The issue is that when closed, it is still possible for the user to scroll horizontally to the right. That should not be possible as the menu should be hidden and there should be no possibility to scroll horizontally.
The simplest way is to replace position: absolute with position: fixed. This fixes the problem but still allows the page to be horizontally scrollable if needed.
Alternatively, you could add
body {
overflow-x: hidden;
}
to remove the horizontal scrollbar.
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.
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>
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
I have the following code in my HTML.
<div class="bg"></div>
<div class="content" id="hover">
<div class="one" id="hover-over">1</div> <!--Trigger!-->
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
The CSS..
.bg {
background: yellow;
position: fixed;
top: 0;
left: 0;
z-index: 1;
}
.content {
background: red;
}
The Javascript..
var box = document.getElementById("bg");
var bgChanger = document.getElementById("hover-over");
//var body = document.getElementsByTagName("body");
function changeBackgroundUp() {
box.style.backgroundColor = "blue";
//body.style.backgroundColor = "#6fcc6f";
}
function changeBackgroundDown() {
box.style.backgroundColor = "green";
//body.style.backgroundColor = "red";
}
bgChanger.onmouseover = changeBackgroundUp; //
bgChanger.onmouseleave = changeBackgroundDown; //
A Fiddle: https://jsfiddle.net/bqnw4qyb/56/
The Problem
I wish to have the background of the project CHANGED to, for example, green - when the user hovers over one of the DIV elements inside "content". So, when the user hovers over "1", the background of the whole page will change to green. My DIV elements have the background of RED, I don't want this colour to change, only the background color, ideally I would want to change the background to an image using a
background: url('someImage');
type of system..
I have tried many existing solutions, such as using CSS hover:
.one:hover ~ .bg {
background: url('someImage')
}
At this stage I am stumped, so any help is very much appreciated.
function green() {
document.getElementsByClassName("content")[0].style.backgroundColor = "green";
}
function red() {
document.getElementsByClassName("content")[0].style.backgroundColor = "red";
}
.bg {
background-color: yellow;
position: fixed;
top: 0;
left: 0;
z-index: 1;
}
.content {
background: red;
}
<div class="bg"></div>
<div class="content" id="hover">
<div class="one" onmouseover="green()" onmouseout="red()" id="hover-over">1</div> <!--Trigger!-->
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
Please see how I implemented this, is this what you would like?
My program is using the onmouseover and the onmouseout event.
Please leave any concerns in the comments, hope it helped ;)
Check the error console!
You have no box object as you have no element with id bg only class.
Add add the id to the div with class bg as well.
<div class="bg" id="bg"></div>
Also with your current positioning, the bg div is not actually visible.
https://jsfiddle.net/bqnw4qyb/67/