Scroll to top function stuck once activated(mobile) - javascript

Hello, I'm currently practicing coding my own site, but i've ran into a problem. I added an auto fade in scroll to top button which works fine on desktop, but on mobile once it's activated the scroll gets stuck at the top. Any idea whats causing it to get stuck, here is my coding.
Sorry in advanced, im very new to this.
The Script
<script>
const scrollTop = function () {
// create HTML button element
const scrollBtn = document.createElement("button");
scrollBtn.innerHTML = "↑";
scrollBtn.setAttribute("id", "scroll-btn");
document.body.appendChild(scrollBtn);
// hide/show button based on scroll distance
const scrollBtnDisplay = function () {
window.scrollY > window.innerHeight
? scrollBtn.classList.add("show")
: scrollBtn.classList.remove("show");
};
window.addEventListener("scroll", scrollBtnDisplay);
// scroll to top when button clicked
const scrollWindow = function () {
if (window.scrollY != 0) {
setTimeout(function () {
window.scrollTo(0, window.scrollY - 50);
scrollWindow();
}, 10);
}
};
scrollBtn.addEventListener("click", scrollWindow);
};
scrollTop(); scrollTop: scrolled;
</script>
</body>
</html>
</head>
</html>
CSS
section::after {
content: "";
display: table;
clear: both;
}
#scroll-btn {
opacity: 0;
width: 60px;
height: 60px;
color: #fff;
background-color: #c066c0;
position: fixed;
bottom: 10%;
right: 10%;
border: 2px solid #fff;
border-radius: 50%;
font: bold 40px monospace;
transition: opacity 0.5s, transform 0.5s;
overflow: hidden;
}
#scroll-btn.show {
opacity: 1;
transition: opacity 1s, transform 1s;
overflow: hidden;
}
Can anyone tell what the problem is?? Thanks so much!

A simple example of scroll to top
const scrollToTop = document.querySelector(".scroll-to-top");
window.addEventListener("scroll", () => {
if (window.scrollY > 200) {
scrollToTop.classList.add("visible");
} else {
scrollToTop.classList.remove("visible");
}
});
scrollToTop.addEventListener("click", () => {
window.scroll({
top: 0,
left: 0,
behavior: "smooth"
});
});
#import "https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css";
body {
height: 200vh;
}
.scroll-to-top {
--size: 48px;
position: fixed;
border: 0;
right: 32px;
bottom: 32px;
z-index: 9999;
display: grid;
border-radius: 50%;
width: var(--size);
place-items: center;
height: var(--size);
aspect-ratio: 1/1;
transform: scale(0);
will-change: transform;
background-color: white;
transition: transform 250ms ease;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.15);
}
.scroll-to-top svg {
width: 24px;
height: 24px;
pointer-events: none;
}
.scroll-to-top.visible {
transform: scale(1);
}
<button class="scroll-to-top">
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
<path d="M448 368L256 144 64 368h384z" />
</svg>
</button>

Related

How to restart css transitions with "touchstart" and "touchend"?

I have a simple div that simulates the ripple effect of material design along with "touchstart" and "touchend" events. But I don't know how to restart the animation if the user clicks several times.
.test-ripple{
position: relative;
display: flex;
align-items: center;
width: 50px;
height: 50px;
overflow: hidden;
border-radius: 50%;
}
.test-ripple:before {
display: none;
}
.test-ripple:after {
position: absolute;
content: "";
cursor: pointer;
background-image: none;
background-color: rgba(0, 0, 0, 0);
width: 78%;
height: 78%;
border-radius: 50%;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
transform: scale(0.3);
transition: linear 350ms forwards;
}
.test-ripple.ativo:after {
background-color: rgba(0, 0, 0, 0.2);
transform: scale(1);
transition: 150ms;
}
.test-ripple.fade-out:after {
background-color: rgba(0, 0, 0, 0);
transition: 300ms;
}
<div class="test-ripple">
<i class="material-icons">add</i>
</div >
var ripple = document.querySelectorAll(".test-ripple")
ripple.forEach((item) => {
item.addEventListener("touchstart", () => {
item.classList.add("ativo");
});
item.addEventListener("touchend", () => {
setTimeout(function () {
item.classList.add("fade-out");
setTimeout(function () {
item.classList.remove("ativo");
item.classList.remove("fade-out");
}, 150);
}, 100);
});
});
How to make the transition repeat each time the user clicks?
Hmmm with what I have seen so far their no special code for that, just write your code add only one call function from the animation to start so when the user click's again it definitely will restart automatically

How can I make this transition smooth instead of it jumping up

I am trying to implement a notification system in my app without the use of a library. Here is a gif of the issue: https://imgur.com/oRc11dM
And here is the jsfiddle of the gif: https://jsfiddle.net/w9yk7n54/
When you click on new notification button, already displayed notifications jump up to make room for the new notification and new notification slides in. I was wondering how I could make it so that they all smoothly go up together.
The notifications wont all be the same dimensions so I cant set static values for height/etc.
Thank you!
let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')
let notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0
btn.onclick = () => {
let notif = document.createElement('div')
notif.classList.add('notif')
notif.innerHTML = notif_contents[current]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
current++
container.append(notif)
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid black;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding: 10px;
border: 1px solid black;
animation: notifAnim 5s forwards;
transition: all .2s;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0% {
transform: translateY( 100%)
}
20% {
transform: translateY( 0)
}
80% {
transform: translateY( 0)
}
100% {
transform: translateY( 100%)
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>
Your notif container has justify-content: flex-end. This means that whenever you add a new one, the previous ones will be pushed up with the height of the new one.
The "fix" is to give each element a negative margin-top equal to its height and integrate in your current transition getting margin-top back to 0.
Example:
let btn = document.querySelector('button'),
container = document.querySelector('.notifications-container'),
notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>",
"<code>another.test()</code>",
"<strong>another</strong> <i>test</i>"
]
btn.onclick = () => {
let notif = document.createElement('div'),
index = Math.floor(Math.random() * notif_contents.length)
notif.classList.add('notif')
notif.innerHTML = notif_contents[index]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
container.append(notif)
notif.style.marginTop = '-' + notif.offsetHeight + 'px'
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid #888;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-bottom: none;
animation: notifAnim 5s forwards;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0%,
100% {
transform: translateY( 100%)
}
20%,
80% {
transform: translateY( 0);
margin-top: 0
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>
An idea is to insert new element with a height equal to 0 and you animate the height in addition to translate. Of course, you should use max-height since height are unknown and we cannot animate to auto:
let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')
let notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0
btn.onclick = () => {
let notif = document.createElement('div')
notif.classList.add('notif')
notif.innerHTML = notif_contents[current]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
current++
container.append(notif)
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid black;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding:0 10px;
max-height:0px;
border: 1px solid black;
animation: notifAnim 5s forwards;
transition: all .2s;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0% {
transform: translateY( 100%);
max-height:0;
padding:0 10px;
}
30% {
transform: translateY( 0);
max-height:300px;
padding:10px;
}
80% {
transform: translateY( 0);
max-height:300px;
padding:10px;
}
100% {
transform: translateY( 100%);
max-height:300px;
padding:10px;
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>

Screen Shrink using Scale

I'm trying to create a particular effect but I'm getting stuck. Essentially what is supposed to happen is when the user clicks on the nav (in the snippet below, I've made it so you just click on the body) the:
main screen shrinks
an off canvas menu slides in from the left
A semi transparent overlay appears
My problem is with the scale effect. The effect I am trying to achieve is when the window shrinks, you can see the entirety of the window, just a miniature version. The closest I've been able to get is the snippet, where the window shrinks, but it's still fully scroll-able rather than the window shrinking proportionally to become a miniature version
The way I have it now, you can still scroll the entirety of the page but I'm going to take care of that with a e.preventDefault but I'd like to get the screen-shrink in order first.
Can anyone help?
$(document).ready(function() {
var pageContainer = $('.page-container');
var offCanvas = $('.off-canvas');
pageContainer.click(function() {
offCanvas.toggleClass('menuActive')
pageContainer.toggleClass('pc-active');
});
});
* {
padding: 0;
margin: 0;
}
.off-canvas {
position: absolute;
left: 0;
top: 0;
height: 100vh;
width: 300px;
background-color: blue;
transition: all .3s ease;
transform: translate3d(-300px, 0, 0);
z-index: 10;
}
.menuActive {
transform: translate3d(0, 0, 0);
}
.page-container {
border: 4px solid;
height: 100%;
width: 100%;
min-height: 1200px;
background-color: #ccc;
transform: scale3d(1, 1, 1);
transition: all .4s ease;
}
.pc-active {
transform: scale3d(.9, .9, .1)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="off-canvas"></div>
<div class="page-container"></div>
You can make use of margin-left to move the miniature to the offset of your sidenavbar on toggle, as well as scale it to your desired value by setting a minimum-height in terms of vh with transform-origin as top left.
$(document).ready(function() {
var pageContainer = $('.page-container');
var offCanvas = $('.off-canvas');
pageContainer.click(function() {
offCanvas.toggleClass('menuActive')
pageContainer.toggleClass('pc-active');
});
});
* {
padding: 0;
margin: 0;
}
.off-canvas {
position: absolute;
left: 0;
top: 0;
height: 100vh;
width: 300px;
background-color: blue;
transition: all .3s ease;
transform: translate3d(-300px, 0, 0);
z-index: 10;
}
.menuActive {
transform: translate3d(0, 0, 0);
}
.page-container {
border: 4px solid;
height: 100%;
width: 100%;
min-height: 1200px;
background-color: #ccc;
transform: scale3d(1, 1, 1);
transition: all .4s ease;
text-align:center;
}
.pc-active {
margin-left:310px;
transform-origin:left top;
min-height:90vh;
transform: scale(0.4,0.4);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="off-canvas"></div>
<div class="page-container">
<h3> Page content</h3>
Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff Random Stuff
</div>
You can set the width/height in vw/vh unit to resize it according to the window
See code snippet:
$(document).ready(function() {
var pageContainer = $('.page-container');
var offCanvas = $('.off-canvas');
pageContainer.click(function() {
offCanvas.toggleClass('menuActive')
pageContainer.toggleClass('pc-active');
});
});
* {
padding: 0;
margin: 0;
}
.off-canvas {
position: absolute;
left: 0;
top: 0;
height: 100vh;
width: 300px;
background-color: blue;
transition: all .3s ease;
transform: translate3d(-300px, 0, 0);
z-index: 10;
}
.menuActive {
transform: translate3d(0, 0, 0);
}
.page-container {
border: 4px solid;
height: 100%;
width: 100%;
min-height: 1200px;
background-color: #ccc;
transform: scale3d(1, 1, 1);
transition: all .4s ease;
}
.pc-active {
width: 90vw;
height: 90vh;
min-height: 90vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="off-canvas"></div>
<div class="page-container"></div>

JavaScript/jQuery - Delay Loading Page When Clicking Hyperlinks at Mobile Resolution

I'm using a CSS hover effect that I found on Codrops in my web portfolio's work page. At mobile resolutions, the elements' animation is activated by clicking the hyperlinked image, but the transition doesn't always have time to complete before loading the next page.
Is there a way to utilize JavaScript/jQuery to delay the loading of a page/website at mobile resolutions?
Update:
I've combined Yaseen Ahmed's solution below with a jQuery-based StackOverflow solution that I finally ran across for a perfect solution to my problems.
$(document).ready(function() {
$('.delay').click(function(e) {
if (window.innerWidth < 768) {
e.preventDefault();
var $a = $(this).addClass('clicked');
setTimeout(function() {
window.location.assign($a.attr('href'));
}, 2500);
} else {
window.location.assign($a.attr('href'));
}
});
});
section {
width: 600px;
height: 400px;
}
figure {
cursor: pointer;
}
figure.apollo {
position: relative;
float: left;
overflow: hidden;
width: 100%;
background: #c3589e;
}
figure.apollo img {
position: relative;
display: block;
height: auto;
width: 100%;
opacity: 0.8;
}
figure.apollo figcaption {
padding: 2rem;
backface-visibility: hidden;
}
figure.apollo figcaption::before,
figure.apollo figcaption::after {
pointer-events: none;
}
figure.apollo figcaption,
figure.apollo figcaption>a {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
max-width: none;
}
figure.apollo figcaption>a {
z-index: 5;
white-space: nowrap;
span {
opacity: 0;
}
}
figure.apollo img {
opacity: 0.95;
transition: opacity 0.35s, transform 0.35s;
transform: scale3d(1.1, 1.1, 1);
}
figure.apollo figcaption::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.5);
content: '';
transition: transform 0.6s;
transform: scale3d(2.2, 1.4, 1) rotate3d(0, 0, 1, 45deg) translate3d(0, -100%, 0);
}
figure.apollo figcaption p span {
margin: .25rem 0;
padding: 0 .5rem;
display: inline-block;
background-color: #ffffff;
box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.5);
}
figure.apollo:hover img {
opacity: 0.6;
transform: scale3d(1, 1, 1);
}
figure.apollo:hover figcaption::before {
transform: scale3d(2.2, 1.4, 1) rotate3d(0, 0, 1, 45deg) translate3d(0, 100%, 0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<section>
<p>Make sure you shrink your viewport width to less than 768px before testing the link delay.</p>
<figure class="apollo">
<img src="https://www.tylerfuller.me/assets/images/sakura.jpg" alt="Cherry Blossoms" />
<figcaption>
<p><span>This is a link to the</span><br />
<span>pure CSS Sakura</span><br />
<span>theme / framework.</span></p>
<a class="delay" href="https://oxal.org/projects/sakura/"></a>
</figcaption>
</figure>
</section>
</body>
All you need to create the java script function in your project see in code.
your hyper link
java script function
function loadpage() {
if (window.innerWidth < 768) {
setTimeout(function(){
location.href="your_url";
}, 1000);
} else {
location.href="your_url";
}
}
What will this function do when your screen width is less then 768 it will load url after one second and if grater then it will load url without delay.
Note : When you resize the screen width must reload the page.

the position of overlay is bottom right of page

The example in jsfiddle works fine. But on my page the overlay appears in the bottom - right, out view instead of the centre. Can anyone tell me which sections I need to change to position overlay in the centre? I've tried bootstrap overlay but this conflicts with current js version, so I thought this solution would be better, that I found on jsfiddle. I have not tested it as a responsive feature on mobile etc, but would be good if someone spots anything which might break on mobile and tablet, other os. Thanks this is the fiddle link and code below http://jsfiddle.net/istvanv/uQj7t/28/
css
a#overlaylaunch-inAbox {
display: block;
padding: 40px;
margin: 40px;
background-color: #efefef;
font-size: 1.6em;
text-decoration: none;
text-align: center;
}
#overlay-inAbox .wrapper {
text-align: center;
}
/* More important stuff */
.overlay,
#overlay-shade {
display: none;
}
#overlay-shade {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 9999;
background-color: #000;
}
.overlay {
position: absolute;
top: 500px;
left: 0;
width: 450px;
min-height: 500px;
z-index: 100;
background-color: #7D7D7D;
border: 10px solid #CFCFCF;
color: #fff;
box-shadow: 0 0 16px #000;
} .ie7 .overlay {
height: 200px;
} .overlay .wrapper {
padding: 15px 30px 30px;
}
.overlay .toolbar {
padding: 8px;
line-height: 1;
text-align: right;
overflow: hidden;
} .overlay .toolbar a.close {
display: inline-block;
*display: inline;
zoom: 1;
padding: 0 8px;
font-size: 12px;
text-decoration: none;
font-weight: bold;
line-height: 18px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-o-border-radius: 5px;
color: #999999;
background-color: #515151;
} .overlay .toolbar a.close span {
color: #818181;
} .overlay .toolbar a.close:hover,
.overlay .toolbar a.close:hover span {
background-color: #b90900;
color: #fff;
}
js
function openOverlay(olEl) {
$oLay = $(olEl);
if ($('#overlay-shade').length == 0)
$('body').prepend('<div id="overlay-shade"></div>');
$('#overlay-shade').fadeTo(300, 0.6, function() {
var props = {
oLayWidth : $oLay.width(),
scrTop : $(window).scrollTop(),
viewPortWidth : $(window).width()
};
var leftPos = (props.viewPortWidth - props.oLayWidth) / 2;
$oLay
.css({
display : 'block',
opacity : 0,
top : '-=300',
left : leftPos+'px'
})
.animate({
top : props.scrTop + 40,
opacity : 1
}, 600);
});
}
function closeOverlay() {
$('.overlay').animate({
top : '-=300',
opacity : 0
}, 400, function() {
$('#overlay-shade').fadeOut(300);
$(this).css('display','none');
});
}
$('#overlay-shade, .overlay a').live('click', function(e) {
closeOverlay();
if ($(this).attr('href') == '#') e.preventDefault();
});
// Usage
$('#overlaylaunch-inAbox').click(function(e) {
openOverlay('#overlay-inAbox');
e.preventDefault();
});
html
<div id="overlay-inAbox" class="overlay">
<div class="toolbar"><a class="close" href="#"><span>x</span> close</a></div>
<div class="wrapper">
Hello! I'm in a box.
</div>
Launch It!
You can play with transform that centers you all you want without taking care of its dimensions.
.overlay {
position: fixed;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%); /* ie9 */
-webkit-transform: translate(-50%, -50%); /* safari iOS - older androids */
transform: translate(-50%, -50%); /* all browsers */
}
And that's all. Apply it to all divs you need to center respect the parent. This box is fixed position so the parent is the body tag.
Note than you don't need javascript calculations, so you can remove them and apply only with css.
EDIT
As I said in the comments, look at this fiddle with 3 divs perfectly centered without know how are their dimensions. Note than there aren't nothing of javascript to make calculations.
http://jsfiddle.net/11oes0rf/
EDIT 2
To preserve the top animation as you have in the initial code, you must to specify in percents with the jquery. So the fiddle is this:
http://jsfiddle.net/uQj7t/1363/
And the code is this:
$oLay
.css({
display : 'block',
top : '-50%',
opacity : 0
})
.animate({
opacity : 1,
top: '50%'
}, 600);
And closer:
function closeOverlay() {
$('.overlay').animate({
top: '-50%',
opacity : 0
}, 400, function() {
$('#overlay-shade').fadeOut(300);
$(this).css('display','none');
});
}

Categories

Resources