I'm trying to make a box shadow property only visible during scrolling. I'm using HTML, CSS and JS.
I want the shadow to appear with a small transition when scrolling then disappear when stopped.
So far I have been using this code:
<head>
<title>website</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<div id="mySidenav" class="sidenav" onscroll="scrollShadow()"></div>
css
.sidenav {
height: 100%;
width: 280px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: skyblue;
overflow-x: hidden;
transition: 0.5s;
padding-top: 10px;
}
js
function scrollShadow() {
document.getElementsByClassName("sidenav").style.boxShadow = "3px 0px 10px black";
}
Would love any help!
Instead of setting the style attribute, which is harder to manage (especially if you have more than one element you want to affect), you could set a class on body and style the elements with CSS.
(function iife() {
var body = document.body;
var timer;
window.addEventListener('scroll', function onScroll() {
clearTimeout(timer);
body.classList.add('scrolling');
timer = setTimeout(function removeClass() {
body.classList.remove('scrolling');
}, 150);
}, false);
})();
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#container {
width: 100vw;
height: 5000px;
background: lightgrey;
transition: background 5s;
}
.scrolling #container {
background: red;
}
#fix {
position: fixed;
top: 50px;
left: 50px;
height: 120px;
width: 20px;
background: white;
transition: all 300ms ease 0s;
}
.scrolling #fix {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.35);
transform: translateY(-3px);
}
<div id="container">
<div id="fix"></div>
</div>
u can use jquery scroll method as
<script>
$(function(){
$(window).scroll(function(){
if($(window).scrollTop()>=40){
/*do something */
scrollShadow();
}
});
});
function scrollShadow() {
document.getElementsByClassName("sidenav").style.boxShadow = "3px 0px 10px black";
}
</script>
I would first ensure that you refrain from adding CSS inside JS, it just shouldn't live there. You can achieve what you want by adding a class to the body which is then targeted inside your CSS. Finally, there's no native way of knowing if the user has stopped scrolling. The only way is to define a timeout which will remove the class unless the user scrolls, whereby the original timeout is cancelled and a new timeout is defined. It's also best to make sure that the window is completely loaded else you'll be targeting elements that aren't there yet. This example below should be what you need:
window.addEventListener('load', function(){
var timeout = null;
var body = document.querySelector('body');
var scrollClass = 'scrolled';
window.addEventListener('scroll', function(){
clearTimeout(timeout);
body.classList.add(scrollClass);
timeout = setTimeout(function(){
body.classList.remove(scrollClass);
}, 250);
});
});
body {
height: 2000px;
}
.sidenav {
height: 100%;
width: 280px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: skyblue;
overflow-x: hidden;
padding-top: 10px;
transition: box-shadow 500ms ease-in-out;
}
.scrolled .sidenav{
box-shadow: 3px 0px 10px #000;
}
<div class="sidenav"></div>
This should achieve what you want.
Tom
Related
I'm new to the web development world and wanted to know if there is a way to disable background scrolling.
I've tried z-index for the pop-up to display above all the elements, but some background content was getting overlapped with the pop-up.
I'm not much familiar with JS but was not able to get any help.
Below please find my code
body {
height: 200vh;
}
.bg-noscroll {
}
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
transform: translateY(-60px);
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 30%;
position: relative;
transition: all 5s ease-in-out;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.content {
height: 250px;
}
.popup .content {
overflow-y: scroll;
}
#media screen and (max-width: 700px){
.popup{
width: 70%;
}
<body class="bg-noscroll bg-scroll">
<span><a class="popupBG-Disable" href="#popup">Full Recipe</a></span>
<div id="popup" class="overlay">
<div class="popup">
<h3>Foxtail Millet Porridge:</h3>
<a class="close" href="#">×</a>
<div class="content">
<span>Ingredients:<br>here are some things that you'd use to make this<br> isn't this amazing?<br>Yes, it is!<br>
this is getting loooooong<br>this will take me a while!<br>oh... yes it will<br>we're getting close<br>and we should be there <br>or not...<br>Im losing hope<br>and patience<br>with how long this is taking<br>I could really cry<br>
but we'll get there soon<br>safe and sound<br>free as pie<br>I dont know what I meant by that<br>
this is taking long mannnn<br>
</span>
Thank you for your help!
I have a live codepen with your original code so you can just copy and paste if you wish.
Using Jquery, we can enable and disable overflow using some simple code:
const modal = document.querySelector("#btn");
const body = document.querySelector("body");
const showModal = function (e) {
modal.classList.toggle("hidden");
if (!modal.classList.contains("hidden")) {
body.style.overflow = "hidden";
} else {
body.style.overflow = "hidden";
}
}; // just reversed for re-enabling scroll, as seen in the codepen
Currently, you have to make use of javascript and add or remove the scrollbar-properties or css-class using a hashchange event-listener for example:
window.addEventListener("hashchange", event => {
const newHash = new URL(event.newURL).hash,
el = document.getElementById(newHash.substr(1));
if (el && el.classList && el.classList.contains("overlay")) {
document.body.style.overflow = "hidden";
// or document.body.classList.add("bg-noscroll");
} else {
document.body.style.overflow = "";
// or document.body.classList.remove("bg-noscroll");
}
});
Starting from chromium 101 the support for the :has()-selector has been implemented (experimental flag only) and the current chromium 105 dev channel brings the :has()-selector enabled by default.
With the has()-selector it will be possible using:
body:has(.overlay:target) {
overflow: hidden;
}
Keep also mind, it may take some more time for other browsers to implement the has()-selector. Therefor the best would be to stick with the javascript method for a while.
What I'm trying to achieve here is that when I scroll on a particular div here .ball, it should scale up to 1.5.
but when I'm not scrolling on that ball div it should shrink down to it's original height and width.
Here I'm using window method to do this trick and as soon as I scroll ball scale up which isn't what I'm trying to do. What can I use instead of window method and is there any other approach to do achieve this?
const ball = document.querySelector('.ball');
window.addEventListener('scroll', ()=> {
if (scroll) {
ball.classList.add('active');
} else {
ball.classList.remove('active');
}
});
.ball {
height: 200px;
width: 200px;
border-radius: 100%;
background-color: orange;
}
.ball.active {
transform: scale(1.5);
position: fixed;
}
body {
height: 150vh;
}
<div class="ball"></div>
I would use a setTimeout function to remove the class after a short period after the scroll. Do not forget to clear the timeout otherwise it will lead to weird behaviour. (as suggested by Lakshya when I was answering to the question).
To make the ball smoothly transition, I would add a css transition as shown bellow.
const ball = document.querySelector('.ball');
const container = document.querySelector('.container')
let scrollTimeout;
container.addEventListener('scroll', ()=> {
ball.classList.add('active');
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(()=> ball.classList.remove('active'), 100);
});
.ball {
height: 200px;
width: 200px;
border-radius: 100%;
background-color: orange;
transition: transform 0.3s ease;
position: fixed;
top: 50px;
left: 50px;
}
.ball.active {
transform: scale(1.5);
}
.container{
width: 100%;
background: red;
overflow: scroll;
height: 500px;
}
.inside_container{
position: relative;
width: 100%;
height: 2000px;
}
<div class="container">
<div class="inside_container">
<div class="ball"></div>
</div>
</div>
One of the approaches could be delaying the removal of .active class on ball by 200ms such that each time you try to scroll again, the timer is cleared and a new one starts to do the same. A debounce approach in a nutshell.
const ball = document.querySelector('.ball');
let scrollTimeout;
window.addEventListener('scroll', ()=> {
ball.classList.add('active');
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(()=> ball.classList.remove('active'),200);
});
.ball {
height: 200px;
width: 200px;
border-radius: 100%;
background-color: orange;
}
.ball.active {
transform: scale(1.5);
position: fixed;
}
body {
height: 150vh;
}
<div class="ball"></div>
Hello StackOverFlowers!
I found this really awesome animation on jsfiddle.net and would really love to use it in my project.
I'f you follow the link the author, 'internoma', states that it can be used as a page transition if a little Ajax is added.
My question is: What Ajax code do I add in order to make this work?!
I'm extremely lost, any suggestions will be greatly appreciated.
If you happen to know how to make this working using Barba.js or smoothState.js that would be awesome also since those are to plugins I'd like to dive deeper in learning.
Thanks in advance!
Link: Material Design Ripple Transition
JavaScript:
$(document).ready(function() {var ripple_wrap = $('.ripple-wrap'),
rippler = $('.ripple'),
finish = false,
monitor = function(el) {
var computed = window.getComputedStyle(el, null),
borderwidth = parseFloat(computed.getPropertyValue('border-left-width'));
if (!finish && borderwidth >= 1500) {
el.style.WebkitAnimationPlayState = "paused";
el.style.animationPlayState = "paused";
swapContent();
}
if (finish) {
el.style.WebkitAnimationPlayState = "running";
el.style.animationPlayState = "running";
return;
} else {
window.requestAnimationFrame(function() {monitor(el)});
}
};
storedcontent = $('#content-2').html();
$('#content-2').remove();
rippler.bind("webkitAnimationEnd oAnimationEnd msAnimationEnd
mozAnimationEnd animationend", function(e){
ripple_wrap.removeClass('goripple');
});
$('body').on('click', 'a', function(e) {
rippler.css('left', e.clientX + 'px');
rippler.css('top', e.clientY + 'px');
e.preventDefault();
finish = false;
ripple_wrap.addClass('goripple');
window.requestAnimationFrame(function() {monitor(rippler[0])});
});
function swapContent() {
var newcontent = $('#content-area').html();
$('#content-area').html(storedcontent);
storedcontent = newcontent;
// do some Ajax, put it in the DOM and then set this to true
setTimeout(function() {
finish = true;
},10);
}
});
CSS
.ripple-wrap {
display: none;
overflow: hidden;
position: fixed;
font-size: 0;
z-index: 1000;
top: 0; left: 0; right: 0; bottom: 0;
}
#-webkit-keyframes RIPPLER {
0% { border-width: 0; }
40% {
height: 0;
width: 0;
border-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
41% {
height: 0;
width: 0;
border-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
100% {
border-width: 1500px;
height: 2000px;
width: 2000px;
margin-top: -2500px;
margin-left:-2500px;
border-color: #009688;
}
}
#keyframes RIPPLER {
0% { border-width: 0; }
40% {
height: 0;
width: 0;
order-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
41% {
height: 0;
width: 0;
border-width: 1500px;
margin-top: -1500px;
margin-left:-1500px;
border-color: #009688;
}
100% {
border-width: 1500px;
height: 2000px;
width: 2000px;
margin-top: -2500px;
margin-left:-2500px;
border-color: #009688;
}
}
.ripple {
display: block;
height: 0;
width: 0;
border-width: 0px;
border-style: solid;
border-color: #00796b;
border-radius: 100%;
position: absolute;
top: 300px;
left: 300px;
-webkit-animation: none;
animation: none;
}
.ripple-wrap.goripple {
display: block;
}
.ripple-wrap.goripple .ripple {
-webkit-animation-name: RIPPLER;
-webkit-animation-duration: 1.5s;
-webkit-animation-fill-mode: forwards;
animation-name: RIPPLER;
animation-duration: 1.5s;
animation-fill-mode: forwards;
}
HTML
<div class="wrap" id="content-area">
<h1>Material Design Ripple Transition</h1>
<p>Just playing around to see if I can recreate the Material Design
ripple as a page transition in CSS. Click any link in
this block of text to load another set of text. The links don't go anywhere yet. They are just hooks to allow you to click somewhere</p>
<p>The style and animation is entirely CSS so it is smooth. JavaScript
is used to add classes at the right time. It also pauses to wait for the
content to be replaced, and calculates where to centre the hole. There
are two stages to the animation. When a link is clicked
the border-width grows very large.</p>
<p>That's enough reading on this slide. Click a link to
load the second slide</p>
</div>
<div id="content-2" style="display:none">
<h2>Slide Two</h2>
<p>This is the second slide. If you want you can <a href="#">go back to
the first slide</a>. The second part of the animation is increasing the
size of the element itself in order to create a hole.</p>
<p>This transition could be used for presentation slides. Using
pushState then this could be used as a transition between webpages.</p>
</div>
<div class="ripple-wrap"><div class="ripple"></div></div>
I have a div that is set to:
{
height: 100vh;
width: 100%;
background-color: black;
opacity: 0;
position: absolute;
z-index: 2;
}
This div is also at the top of the page.
I want to make it so that as I scroll down (and away from the div), it slowly fades in, and when I scroll back up it fades out.
How would I do this?
You may refer following code snippet. The point I am trying to make is in the script tag at the bottom just added the window scroll function which sets the opacity to your entire window of desired height in your css class ".top". So when you try to scroll in and out it will dynamically add an animation effect to your window.
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<style>
body {
margin: 0;
height: 1000px;
}
.top {
margin: 0;
position: relative;
width: 100%;
background-color: #aaa;
height: 300px;
opacity: 1;
text-align: center;
font-family: 'helvetica';
font-size: 80px;
font-weight: 100;
color: #fff;
}
.title {
position: absolute;
top: 60%;
left: 100px;
}
</style>
</head>
<body>
<div class="top">
<div class="title">Fade Away</div>
</div>
</body>
</html>
<script>
$(window).scroll(function() {
$(".top").css("opacity", 1 - $(window).scrollTop() / 250);
});
</script>
document.body.addEventListener('wheel', (e) => {
let faceLayer = document.getElementById('your_id');
faceLayer.style.opacity = Math.abs(faceLayer.getBoundingClientRect().top / faceLayer.clientHeight).
})
I am working an a project which requires a custom progress bar using only html, css, and javascript. I want to be able to set an initial condition on the progress bar and have it start at the proper place.
Example: I have a timestamp for when something started and I know when it should complete. I want the progress bar to start at the proportionally correct place and then transition the width to 100% completion over the proper time.
I am having trouble setting up the code so that this is possible. I have not yet been able to get a css transition to start at a programmatically set width.
This example shows my approach so far...
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: "Avenir Next", sans-serif;
font-size: 1em;
text-align: center;
}
html, body, div {
width: 100%;
height: 100%;
background-color: white;
}
#spacer {
height: 40%;
}
#container {
height: 20%;
background-color: gray;
}
#progressBar {
background-color: green;
float: left;
}
</style>
</head>
<body onload="startProgressBar()">
<div id="spacer"></div>
<div id="container">
<div id="progressBar"></div>
</div>
<div id="spacer"></div>
</body>
<script type="text/javascript">
function startProgressBar() {
bar = document.getElementById("progressBar");
// assume that the bar should start at 50%
bar.style.transitionDuration = "0s";
bar.style.width = "50%";
// assume that bar should complete final 50% in 10s
bar.style.transition = "width 10s linear";
bar.style.width = "100%";
}
</script>
</html>
I am new to javascript. It seems that the when I set bar.style the lines are not executed serially. I may just misunderstand something about how javascript works.
It is because of the way you are setting the transition properties. You need to apply the animation in either a timeout or requestAnimationFrame like so:
function startProgressBar() {
bar = document.getElementById("progressBar");
// assume that the bar should start at 50%
bar.style.width = "50%";
requestAnimationFrame(function(){
// assume that bar should complete final 50% in 10s
bar.style.transition = "width 10s linear";
bar.style.width = "100%";
});
}
Also you don't need the first set transitionDuration since you aren't transitioning to 50%, you want to start there.
Working Plunkr: http://plnkr.co/edit/3CeNFFO4JWFhB679GyAV
A mere setTimeout should do:
function startProgressBar(){
bar=document.getElementById('progressBar');
bar.style.width='50%';
setTimeout(function(){
bar.style.transitionDuration='2s';
bar.style.width='100%';
},1);
}
startProgressBar();
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family:"Avenir Next", sans-serif;
font-size: 1em;
text-align: center;
}
html, body, div {
width: 100%;
height: 100%;
background-color: white;
}
#spacer {
height: 40%;
}
#container {
height: 20%;
background-color: gray;
}
#progressBar {
background-color: green;
float: left;
}
<div id="spacer"></div>
<div id="container"><div id="progressBar"></div></div>
<div id="spacer"></div>
Update: Whoops! didn't realize #KevinF had already posted a good solution.
Or just simply give #progressBar a width value in css.
#progressBar {
background-color: green;
float: left;
width: 50%;
}
http://plnkr.co/edit/igS0ySjiygIQVGp1OIKz