Transparent opening at bottom of fixed element on mobile scroll - javascript

It's hard for me to explain this, but I currently have a fixed item at the bottom of the page, and it disappears once the user scrolls to the bottom of the site, showing another div with a large amount of text. Once the user starts scrolling back to the top of the site, the fixed element re-appears at the bottom of the screen. The position of the fixed element is set to "bottom:0".
Unfortunately, sometimes, when the user scrolls up there is a transparent box about 20px in height below the fixed item. You can see the elements on the page that would appear underneath the fixed element, but the fixed element stays on top.
When I click on this blank space, the Google search bar appears. Is the Google search bar the thing that is causing the transparent box below the fixed element? What else could it be? This does not happen on Developer tools emulators, only on actual phones.
Here is an image below:
Here is my JS:
$(".mobile-isi-expand").click( function (){
var topMenuHeight = $('.mobile-top-menu').height();
var documentHeight = $('#pageContent').height();
var screenHeightSans = $(window).height();
console.log(topMenuHeight);
console.log(documentHeight);
var desiredExpandedHeight = topMenuHeight;
var desiredContractedHeight = "150px";
var deviceHeight = $(window).height();
var regionContent = $(".region-content").height();
if(documentHeight === null){
documentHeight = screenHeightSans;
}
else {
}
if($(this).hasClass("mobile-expanded")) {
$(this).removeClass("mobile-expanded");
$(".mobile-isi-container").animate({
"height":"150px",
"bottom":"0",
"top":deviceHeight - 150
});
}
else {
$(this).removeClass("mobile-isi-minimize");
$(".mobile-isi-expand").addClass("mobile-expanded");
$(".mobile-isi-container").animate({
"top":desiredExpandedHeight,
"height": documentHeight
});
}
});
$(function($) {
if(Modernizr.mq('(max-width: 480px)')) {
$(window).on('scroll', function() {
var is_root = location.pathname == "/";
var referenceHeight = $('.referenceArea').height();
var pageContentHeight = $("#pageContent").height();
var regionContent = $(".region-content").height();
var refAndPageHeight = referenceHeight + pageContentHeight;
if($(this).scrollTop() >= regionContent - 220) {
$('.mobile-hidden-isi').addClass("mobile-active");
$('.mobile-isi-container').css({"display":"none", "height": "150px"});
}
else {
$('.mobile-hidden-isi').removeClass("mobile-active");
$('.mobile-isi-container').css({"display":"block", "height": "150px", "bottom" : "0"});
var mobileISIheight = $('.mobile-isi-container').height();
console.log(mobileISIheight);
}
})
}
else {
}
});
CSS:
.mobile-isi-container {
position: fixed;
bottom: 0;
font-family: 'quicksandregular';
left: 0;
display: block;
background-color: #fff;
width: 100%;
height: 150px;
min-height: 150px;
z-index: 999999;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
overflow-y: scroll;
-webkit-box-shadow: 1px -1px 3px -1px rgba(64,62,64,1);
-moz-box-shadow: 1px -1px 3px -1px rgba(64,62,64,1);
box-shadow: 1px -1px 3px -1px rgba(64,62,64,1);
}

this occurred due to the address bar appearing and disappearing. It changes the calculated window.height(). All I did was add an overflow-y: visible instea of overflow-y: scroll in my css, and added a background color. This covers up the transparent area, though it does make the height of the fixed element sort of variable.

Related

jQuery code disabling links to other web pages

I have some jQuery code that allows for smoothing scrolling on my web pages.
$(document).ready(function(){
// browser window scroll position (in pixels) where the button will appear
var offset = 200,
// duration of the animation (in ms)
scroll_top_duration = 700,
// bind with the button
$back_to_top = $('.back-to-top');
// display and hide the button
$(window).scroll(function(){
( $(this).scrollTop() > offset ) ? $back_to_top.addClass('make-visible-btt') : $back_to_top.removeClass('make-visible-btt');
});
//smooth scroll to top
$back_to_top.on('click', function(event){
event.preventDefault();
$('body,html').animate({
scrollTop: 0 ,
}, scroll_top_duration
);
});
});
$(document).ready(function() {
// browser window scroll position (in pixels) where the button will appear
var offset = 200,
// duration of the animation (in ms)
scroll_top_duration = 700,
// bind with the button
$back_to_top = $('.back-to-top');
// display and hide the button
$(window).scroll(function() {
($(this).scrollTop() > offset) ? $back_to_top.addClass('make-visible-btt'): $back_to_top.removeClass('make-visible-btt');
});
//smooth scroll to top
$back_to_top.on('click', function(event) {
event.preventDefault();
$('body,html').animate({
scrollTop: 0,
}, scroll_top_duration);
});
});
.back-to-top {
position: fixed;
bottom: 20px;
right: 20px;
display: inline-block;
height: 40px;
width: 40px;
background: url(../images/back-to-top.png) no-repeat;
background-size: contain;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
border: 1px solid #aaa;
visibility: hidden;
opacity: 0;
transition: opacity .3s 0s, visibility 0s .3s;
}
.make-visible-btt {
visibility: visible;
opacity: 1;
transition: opacity 1s 0s, visibility 0s 0s;
}
.section {
border: 1px solid black;
background-color: #ededed;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
jump to last section
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section" id="last"></div>
Back to Top
The code works fine. When users click the "back to top" button on the page, they're automatically smooth scrolled to the top. All good.
The code above, however, doesn't work for in-page links.
text text text
So if a user clicks on a link like the one above, the pages instantly jumps to that section (which is the default behavior).
I added this code to fix that problem:
$(document).ready(function(){
$('a[href*="\\#"]').on('click', function(event){
var href = $(event.target).closest('a').attr('href'),
skip = false;
if (!skip) {
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
}
});
});
$(document).ready(function() {
// browser window scroll position (in pixels) where the button will appear
var offset = 200,
// duration of the animation (in ms)
scroll_top_duration = 700,
// bind with the button
$back_to_top = $('.back-to-top');
// display and hide the button
$(window).scroll(function() {
($(this).scrollTop() > offset) ? $back_to_top.addClass('make-visible-btt'): $back_to_top.removeClass('make-visible-btt');
});
//smooth scroll to top
$back_to_top.on('click', function(event) {
event.preventDefault();
$('body,html').animate({
scrollTop: 0,
}, scroll_top_duration);
});
});
$(document).ready(function(){
$('a[href*="\\#"]').on('click', function(event){
var href = $(event.target).closest('a').attr('href'),
skip = false;
if (!skip) {
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
}
});
});
.back-to-top {
position: fixed;
bottom: 20px;
right: 20px;
display: inline-block;
height: 40px;
width: 40px;
background: url(../images/back-to-top.png) no-repeat;
background-size: contain;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
border: 1px solid #aaa;
visibility: hidden;
opacity: 0;
transition: opacity .3s 0s, visibility 0s .3s;
}
.make-visible-btt {
visibility: visible;
opacity: 1;
transition: opacity 1s 0s, visibility 0s 0s;
}
.section {
border: 1px solid black;
background-color: #ededed;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
jump to last section
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section" id="last"></div>
Back to Top
So now that's fixed.
But that second code block has created two new problems:
Links with a fragment identifier (e.g., #section-of-page) no longer update in the browser address bar. For example, within a page, on click, the page does scroll smoothly to the target section (so it works), but the web address stays fixed at www.website.com/whatever, when it should update to www.website.com/whatever#section-of-page.
Links with a fragment identifier don't work across pages. In other words, /this-web-page#section-of-page works fine. But /another-web-page#section-of-page and www.another-website.com/whatever#section-of-page both fail (click does nothing).
These problems didn't exist before adding that second code block.
Looking for some guidance on how to fix these problems.
Also if you can suggest a way to integrate all functions into one block of code, that would be great.
Lastly, I know about the CSS scroll-behavior property, but it's still very rudimentary (can't adjust any settings), so I'd rather stick with JS for now.
Thanks.
You can check if the href points to an internal location by creating a URL object from it and checking its host against window.location.host. Then call event.preventDefault and perform smooth scrolling only in that case.
The callback function (third argument) to $.animate can be used to set the hash properly after the scrolling effect.
if (new URL(href, window.location).host === window.location.host) {
event.preventDefault();
$('html,body').animate({
scrollTop: $(this.hash).offset().top
}, 500, function() {
window.location.hash = new URL(href, window.location).hash;
});
}
$(document).ready(function() {
// browser window scroll position (in pixels) where the button will appear
var offset = 200,
// duration of the animation (in ms)
scroll_top_duration = 700,
// bind with the button
$back_to_top = $('.back-to-top');
// display and hide the button
$(window).scroll(function() {
($(this).scrollTop() > offset) ? $back_to_top.addClass('make-visible-btt'): $back_to_top.removeClass('make-visible-btt');
});
//smooth scroll to top
$back_to_top.on('click', function(event) {
event.preventDefault();
$('body,html').animate({
scrollTop: 0,
}, scroll_top_duration);
});
});
$(document).ready(function(){
$('a[href*="\\#"]').on('click', function(event){
var href = $(event.target).closest('a').attr('href');
if (new URL(href, window.location).host === window.location.host) {
event.preventDefault();
$('html,body').animate({
scrollTop: $(this.hash).offset().top
}, 500, function() {
window.location.hash = new URL(href, window.location).hash;
});
}
});
});
.back-to-top {
position: fixed;
bottom: 20px;
right: 20px;
display: inline-block;
height: 40px;
width: 40px;
background: url(../images/back-to-top.png) no-repeat;
background-size: contain;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
border: 1px solid #aaa;
visibility: hidden;
opacity: 0;
transition: opacity .3s 0s, visibility 0s .3s;
}
.make-visible-btt {
visibility: visible;
opacity: 1;
transition: opacity 1s 0s, visibility 0s 0s;
}
.section {
border: 1px solid black;
background-color: #ededed;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
jump to last section
External link
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section" id="last"></div>
Back to Top
for The 1st problem is because of event.preventDefault();. If you remove this line then browser url will be updated accordingly.
if you see any problems then you try setting the url again after animation completes / finishes.
for syntax refer docs
$('html,body').animate({
scrollTop: $(href).offset().top
}, 500, function () {
window.location.hash = href;
});
For 2nd problem
check wether the callback is hitting on click by putting debug point

Change different header styles at different scroll positions

I am trying to make a header for a website where the header changes to different colors at different positions on the page.
Trying to get blue color background for header if the page is scrolled down with less than 40 pixels. And then red color background for header if the page is scrolled down between 40 pixels and 100 pixels. And then when the page is moved completely up, the header background is a yellow color.
Edit 1:
In short, Trying to make a sticky header change colors at different positions of the scroll on a page.
Edit 2:
Tried a new way of putting conditions. Updated the below code with latest working sticky header.
My problem is, when the header goes to the top position, it doesn't change back to orange color
So far I have got this code.
JS Fiddle
jQuery(document).ready(function($){
var mywindow = $(window);
var transoffset = $('#stickyheaders').offset().top;
var mypos = mywindow.scrollTop();
mywindow.scroll(function() {
if (mypos > 40) {
if(mywindow.scrollTop() > mypos)
{
$('#stickyheaders').addClass('headerup');
}
else
{
if(mywindow.scrollTop() < 155) {
$('#stickyheaders').addClass('headertranspup');
} else {
//$('#stickyheaders').removeClass('headerup');
$('#stickyheaders').addClass('headerstyleup');
}
}
}
mypos = mywindow.scrollTop();
});
});
body { margin: 0; }
section {
height: 2000px;
padding-top: 100px; }
#stickyheaders{
background: orange;
-webkit-transition: transform 0.34s ease;
transition : transform 0.34s ease;
}
.headerup{
position: fixed;
top:0; left:0;
width: 100%;
background: orange !important;
//transform: translateY(-110px);
//adjust this value to the height of your header
}
.headerstyleup{
background-color: blue !important;
}
.headertranspup{
background-color: red !important;
}
.headertranpup{
background-color: yellow !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<section>
<div id="stickyheaders">This div will stick to the top</div>
</section>
The easiest solution for a problem like this is by assigning background-colour to the header directly in the element property using jquery rather than adding a new class with the same css property like background-colour in this case.
jQuery(document).ready(function($){
var mywindow = $(window);
var mypos = mywindow.scrollTop();
mywindow.scroll(function() {
if (mypos > 40) {
if(mywindow.scrollTop() > mypos)
{
$('#stickyheaders').addClass('headerup');
//$('#stickyheaders').addClass('headertranpup');
$('#stickyheaders').css("background-color","orange");
}
else
{
if(mywindow.scrollTop() < 75) {
$('#stickyheaders').removeClass('headerup');
$('#stickyheaders').css("background-color","transparent");
}
else
{
$('#stickyheaders').css("background-color","blue");
}
}
}
mypos = mywindow.scrollTop();
});
});
body { margin: 0; }
section {
height: 2000px;
padding-top: 100px; }
#stickyheaders{
-webkit-transition: transform 0.34s ease;
transition : transform 0.34s ease;
}
.headerup{
position: fixed;
top:0; left:0;
width: 100%;
adjust this value to the heigt of your header*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<section>
<div id="stickyheaders">This div will stick to the top</div>
</section>

how to change the color of the navbar after scrolling

I want my navbar to be transparent, but when the user scrolls a bit I want it to change to a solid color and I am using bootstrap for the navbar, I have done the code that is needed with javascript.
I had this javascript in my HTML file, but it doesn't seems to work and I don't really know why
<script>
var myNav = document.getElementById("mynav");
window.onscroll = function() {
use strict";
if (document.body.scrollTop >= 100) {
myNav.classList.add("scroll");
} else {
myNav.classList.remove("scroll");
}
};
</script>
and I have also added the CSS code.
.scroll {
background-color: transparent !important;
transition: all 0.5s ease-in;
}
I don't know why it doesn't work, it is not displaying any errors, I have also manually put the class and it worked so the problem is from the js code and not the CSS.
Use scrollY property of Window object.
See the Snippet below:
var myNav = document.getElementById("mynav");
window.onscroll = function() {
if (window.scrollY >= 100) {
myNav.classList.add("scroll");
} else {
myNav.classList.remove("scroll");
}
};
.scroll {
background-color: transparent !important;
transition: all 0.5s ease-in;
}
.main-container{
height: 1000px;
}
#mynav{
position: fixed;
background-color: gray;
height: 50px;
margin:0 auto;
top: 0;
bottom:0;
line-height: 50px;
padding:5px;
width: 100%;
}
<div class="main-container">
<div class="mynav" id="mynav">
Hello World! this is mynav
</div>
</div>
Try using window.scrollY instead of document.body.scrollTop.
if (window.scrollY >= 100)
You can also use document.documentElement.scrollTop. It's the html element that actually scrolls, not the body. Typically document.body.scrollTop will always be 0.

Issue with adding class when element is in the viewport

I'm using Stick-Kit to keep some images in place while scrolling, and it seems to be affecting another script that initiates a CSS animation by adding a class to a div when it enters the viewport. I assume the Sticky-Kit script is 'reseting' the other, as the animation only occurs once when Sticky-Kit is removed. The issue is visible when the animated div gets to the top of the screen. How do I ensure the animation occurs only one time (when it first appears in the viewport)?
http://codepen.io/SeanLindsay1/pen/ZBVyLZ
HTML
<div id="bg">
<h2 class="header-title"><span>HEADER</span></h2>
<div id="pic1">
1
</div>
<div id="pic2">
2
</div>
<div id="pic3">
3
</div>
</div>
CSS
/* STICKY-KIT */
#bg {
background-color: white;
width:100%;
height:1500px;
padding:0;
margin:0;
font-size:30px
}
#pic1 {
position:relative;
width:60% ;
height:500px;
background-color:blue;
}
#pic2 {
position:relative;
width:60% ;
height:500px;
background-color:green;
}
#pic3 {
position:relative;
width:60% ;
height:500px;
background-color:red;
}
/* HEADER TITLES */
.header-title span {
display: inline-block;
position: relative;
}
.change:after {
content: " ";
position: absolute;
height: 5px;
border-bottom: 1px solid #bebebe;
-webkit-animation: extend .1s 1 forwards;
animation: extend 1s 1 forwards;
margin-left: 4px;
top: 1.2em !important;
}
#-webkit-keyframes extend {
0% {
width: 0;
}
100% {
width: 200px;
}
}
#keyframes extend {
0% {
width: 0;
}
100% {
width: 200px;
}
}
jQuery
// Check to see if element is in viewport
function isElementInViewport(elem) {
var $elem = jQuery(elem);
// Get the scroll position of the page.
var scrollElem = ((navigator.userAgent.toLowerCase().indexOf('webkit') != -1) ? 'body' : 'html');
var viewportTop = jQuery(scrollElem).scrollTop();
var viewportBottom = viewportTop + jQuery(window).height();
// Get the position of the element on the page.
var elemTop = Math.round( $elem.offset().top ) + 200 ;
var elemBottom = elemTop + $elem.height();
return ((elemTop < viewportBottom) && (elemBottom > viewportTop));
}
// Check if it's time to start the animation
function extendLine() {
var $elem = jQuery('.header-title span').each(function() {
var $elem = jQuery(this);
// If the animation has already been started
if ($elem.hasClass('change')) return;
if (isElementInViewport($elem)) {
// Start the animation
$elem.addClass('change');
}
});
}
// Capture scroll events
jQuery(window).scroll(function(){
extendLine();
});
$("#bg").stick_in_parent();
$("#text").stick_in_parent({offset_top: 390});
$("#pic1").stick_in_parent();
$("#pic2").stick_in_parent();
$("#pic3").stick_in_parent();
If possible, you can use a CSS Transition instead of an Animation. It'll have better browser support, and will work. I can't really find out what's happening in your code, but if you change a couple of lines, it'll work as expected.
Here is a forked codepen: http://codepen.io/ddanielbee/pen/BQbQqj
Here are the specific lines:
.header-title span::after {
content: " ";
transition: all 1.5s ease-out;
width: 0;
}
.header-title span.change::after {
position: absolute;
height: 5px;
border-bottom: 1px solid #bebebe;
width: 200px;
margin-left: 4px;
top: 1.2em !important;
}
Removing this line of code:
$("#bg").stick_in_parent();
ensures that the header text block is not influenced by Stick-Kit and eliminates the problem of repeated execution of the animation, as shown in this codepen.
I haven't observed any ill effects caused by that change, but I cannot guarantee that there aren't any, since I don't know why this line was in the original code.

After resetting transition, div stays visible; no new transition

I'm trying to make a <div> display and then fade out, on button click.
This works so long as the user waits for the fade to complete between <button> presses.
My problem is, if the <button> is clicked while the fade is ongoing, the <div> needs to immediately reappear, and then fade out.
I've managed to get it to immediately reappear, but now it doesn't fade out again.
To get an easier idea of what I'm doing, take a look at the JSFiddle I've setup.
Can anyone help me get this to fade out if clicked whilst already fading out?
I'm only targeting webkit.
<div id="saved">Saved!</div>
<button id="save">Save</button>
function save()
{
// Little "Saved!" div
var div = document.getElementById('saved');
// If still showing from previous save
if(div.style.visibility === 'visible')
{
resetTransition();
div.style.visibility = 'visible';
//div.style.opacity = 0;
console.log('reset');
}
// On transition end
div.addEventListener('webkitTransitionEnd', resetTransition);
function resetTransition()
{
// Disable transitions
div.className = 'notransition';
// Hide the div and reset the opacity
div.style.visibility = 'hidden';
div.style.opacity = 1;
// Need time to let CSS changes (^) refresh
setTimeout(function()
{
// Re-enable transitions
div.className = '';
// Remove the event listener by way of cloning
var dolly = div.cloneNode(true);
div.parentNode.replaceChild(dolly, div);
}, 1);
}
// Show the div and fade out - on timer due to "if still showing" needing
// to process first
setTimeout(function()
{
div.style.visibility = 'visible';
div.style.opacity = 0;
}, 1);
}
document.getElementById('save').addEventListener('click', save);
div#saved
{
-webkit-transition: opacity 1.25s ease-out;
-webkit-transition-delay: 0.75s;
background-color: #FFC;
/* Courtesy of http://fatcow.com/free-icons */
background-image: url('http://i.imgur.com/JMlclKE.png');
background-position: 3px 4px;
background-repeat: no-repeat;
border: 1px solid #333;
border-radius: 6px;
left: 5px;
opacity: 1;
padding: 10px 4px 10px 52px;
position: absolute;
top: 5px;
visibility: hidden;
width: 68px;
}
.notransition
{
-webkit-transition: none !important;
-webkit-transition-delay: none !important;
}
button
{
position: absolute;
top: 100px;
}
I updated your fiddle, moving the cloning to the top and clearing the timeout.
// Little "Saved!" div
clearTimeout(save.t);
var dolly = document.getElementById('saved');
// Remove the event listener by way of cloning
var div = dolly.cloneNode(true);
dolly.parentNode.replaceChild(div, dolly);
/* etc til */
save.t = setTimeout(/* */);

Categories

Resources