Button fixed to page when scrolling in mobile view with Javascript - javascript

hoping to get some JS/CSS help here. I need to have the checkout button on a page of mine go to the top of the page and become fixed if the user can no longer see it scrolling down the page in mobile view. I'm hoping someone can help! The one thing messing me up is that I can't use jQuery
![function checkoutScroll() {
var button = document.querySelector('.cartSidebar__checkoutButton');
window.addEventListener('scroll', function () {
var distanceFromTop = document.body.scrollTop;
if (distanceFromTop === 0) {
button.style.position = 'static';
button.style.top = 'auto';
}
if (distanceFromTop > 0) {
button.style.position = 'fixed';
button.style.top = '0px';
}
});
}

What you are trying to achieve can be done through CSS which would make more sense as it's a visual / UI task. I would add top margin equivalent to the css height of your button and leave it as fixed top. As a benefit, you would be able to take advantage of the media queries to limit the CSS rules to the mobile view.
#media screen and (max-width: 960px) {
.container{
margin: 3em;
}
.checkout_button{
display:block;
position:fixed;
top:0;
left:0;
width:100%;
}
}
something very simple like https://jsfiddle.net/f19Lus43/
If you want to stay in javascript for some obscure reasons ( I can't say compatibility because of document.querySelector is working only on evolved browser ) it's up to you but having an example of your code would help us respond :)

So I take it you want the function to only run on smaller screens/browser viewports? Is that what you mean by "mobile view"? I've been using this for a while. Not sure if its better than Glen's solution but it's worked for me without fault. First we define our functions:
function updateViewportDimensions() {
var w=window,d=document,e=d.documentElement,g=d.getElementsByTagName('body')[0],x=w.innerWidth||e.clientWidth||g.clientWidth,y=w.innerHeight||e.clientHeight||g.clientHeight;
return { width:x,height:y };
}
// setting the viewport width
var viewport = updateViewportDimensions();
function detectMob() {
viewport = updateViewportDimensions();
if (viewport.width <= 768) {
return true;
} else {
return false;
}
}
Then every time you need to check if the size of the viewport is less than 768 pixels wide you do:
if (detectMob){
//your code here
}

Related

Disabling/ Enabling javascript based on viewport width

I've created a navigation bar which requires javascript at 400px but below 400px I have no need for it.
As the page is loaded larger than 400px then resized below that the javascript remains which results in an undesired effect. (The same goes for loading the page smaller than 400px then resizing it to be larger than). https://jsfiddle.net/abp1rwhp/4/
I am using
if(screen.width < 400)
which as I explained does the job until the user resizes the window. Does anyone know of a way I could fix my issue?
This should do the trick where .nav is the css selector for your nav
var showHideMyNav = function () {
if (window.outerWidth < 400) {
var nav = document.querySelector(".nav");
nav.style.visibility = "hidden"; // $('#nav-bar').hide();
} else {
nav.style.visibility = "visible"; // $('#nav-bar').show();
}
};
window.addEventListener('resize', showHideMyNav); // $(window).on("resize, ...);

Manipulating the DOM using jQuery .resize()

I want to change the order of elements in the DOM based on different browser sizes.
I've looked into using intention.js but feel that it might be overkill for what I need (it depends on underscore.js).
So, i'm considering using jQuery's .resize(), but want to know if you think something like the following would be acceptable, and in line with best practices...
var layout = 'desktop';
$( window ).resize(function() {
var ww = $( window ).width();
if(ww<=767 && layout !== 'mobile'){
layout = 'mobile';
// Do something here
}else if((ww>767 && ww<=1023) && layout !== 'tablet'){
layout = 'tablet';
// Do something here
}else if(ww>1023 && layout !== 'desktop'){
layout = 'desktop';
// Do something here
}
}).trigger('resize');
I'm storing the current layout in the layout variable so as to only trigger the functions when the window enters the next breakpoint.
Media queries are generally preferred. However, if I am in a situation where I am in a single page application that has a lot of manipulation during runtime, I will use onresize() instead. Javascript gives you a bit more freedom to work with dynamically setting breakpoints (especially if you are moving elements around inside the DOM tree with stuff like append()). The setup you have is pretty close to the one I use:
function setWidthBreakpoints(windowWidth) {
if (windowWidth >= 1200) {
newWinWidth = 'lg';
} else if (windowWidth >= 992) {
newWinWidth = 'md';
} else if (windowWidth >= 768) {
newWinWidth = 'sm';
} else {
newWinWidth = 'xs';
}
}
window.onresize = function () {
setWidthBreakpoints($(this).width());
if (newWinWidth !== winWidth) {
onSizeChange();
winWidth = newWinWidth;
}
};
function onSizeChange() {
// do some size changing events here.
}
The one thing that you have not included that is considered best practice is a debouncing function, such as the one below provided by Paul Irish, which prevents repeated firing of the resize event in a browser window:
(function($,sr){
// debouncing function from John Hann
// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function(fn){ return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };
})(jQuery,'smartresize');
// usage:
$(window).smartresize(function(){
// code that takes it easy...
});
So incorporate a debouncer into your resize function and you should be golden.
In the practice is better to use Media Queries
Try this, I'm in a hurry atm and will refactor later.
SCSS:
body, html, .wrapper { width: 100%; height: 100% }
.sidebar { width: 20%; height: 500px; float: left;
&.mobile { display: none } }
.content { float: right; width: 80% }
.red { background-color: red }
.blue { background-color: blue }
.green { background-color: green }
#media all and (max-width: 700px) {
.content { width: 100%; float: left }
.sidebar { display: none
&.mobile { display: block; width: 100% }
}
}
HAML
.wrapper
.sidebar.blue
.content.red
.content.green
.sidebar.mobile.blue
On 700 px page breaks, sidebar disappears and mobile sidebar appears.
This can be much more elegant but you get the picture.
Only possible downside to this approach is duplication of sidebar.
That's it, no JS.
Ok, the reason for my original question was because I couldn't find a way to move a left sidebar (which appears first in the HTML) to appear after the content on mobiles.
Despite the comments, I still can't see how using media queries and position or display alone would reliably solve the problem (perhaps someone can give an example?).
But, it did lead me to investigate the flexbox model - display: flex, and so I have ended up using that, and specifically flex's order property to re-arrange the order of the sidebars and content area.
Good guide here - https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Position displacement when toggling several overflow-y Elements

I have a problem which I don't know how to solve, hopefully someone here can shed some light into it.
I have a very simple layout (JSBin) with a horizontally centered header, some content to experience vertical scrolling, a sticky footer and an off-canvas navigation menu. I want to prevent the user from scrolling the page when the sidebar is opened, I'm doing that by toggling a class on the <html> tag:
$('button').click(function () {
$('html').toggleClass('sidebar');
});
The .sidebar class will transition the sidebar into view and disable scrolling on the content:
html {
overflow-y: scroll; /* default state, always shows scrollbar */
}
html.sidebar {
overflow-y: hidden; /* hides scrollbar when .sidebar is on canvas */
}
html.sidebar aside {
-webkit-transform: translate3d(-100%, 0, 0); /* places .sidebar on canvas */
}
The problem is, it displaces every element in the page by whatever width the <html> scrollbar had.
Is there any way to prevent this shift in position (preferably without resorting to Javascript)?
Here's the JSBin editor in case you need to peek at the code.
Update: Seems that Javascript isn't an option, the scroll width calculation is not reliable at all.
You can toggle the margin-right of .container to compensate for the change in width
$(function () {
$('button').click(function () {
var marginR = $(".container").css("margin-right") == sWidth+"px" ? "auto" : sWidth;
$(".container").css("margin-right", marginR);
$('html').toggleClass('sidebar');
});
});
function getScrollbarWidth() {
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
// force scrollbars
outer.style.overflow = "scroll";
// add innerdiv
var inner = document.createElement("div");
inner.style.width = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
// remove divs
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
}
var sWidth = getScrollbarWidth();
Demo
Scrollbar width calculation taken from this answer
I can't find a CSS solution that works reliably. However, I'm having success with the following Javascript:
window.onload=function(){
document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
document.body.onclick=function(){
document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
}
}
I haven't analyzed yet what the processing impact is for running this code each and every time somebody clicks on my site (it's probably ugly), but it works.

Using JavaScript to change CSS style based on page width

I'm working on an assignment for a class where I have to make an external JavaScript file that checks a page's current width and changes the linked CSS style based on it, and have that occur whenever the page loads or is resized. Normally, we are given an example to base our assignment off of, but that was not the case this time around.
Essentially we are to use an if...then statement to change the style. I have no clue what the appropriate statements would be for the function. I've looked around and the potential solutions are either too advanced for the class or don't go over what I need. As far as I know I cannot use jQuery or CSS queries.
If someone could give me an example of how I would write this out, I would be very appreciative.
Try this code
html is
<div id="resize" style="background:red; height: 100px; width: 100px;"></div>
javascript is
var resize = document.getElementById('resize');
window.onresize=function(){
if(window.innerWidth <= 500) {
resize.style = "background:blue; height: 100px; width: 100px;";
}
else {
resize.style = "background:red; height: 100px; width: 100px;";
}
};
i have create a sample for you look at here TESTRESIZE
try resizing your browser and let me know if it is what you are looking for.
//Use This//
function adjustStyle() {
var width = 0;
// get the width.. more cross-browser issues
if (window.innerHeight) {
width = window.innerWidth;
} else if (document.documentElement && document.documentElement.clientHeight) {
width = document.documentElement.clientWidth;
} else if (document.body) {
width = document.body.clientWidth;
}
// now we should have it
if (width < 799) {
document.getElementById("CSS").setAttribute("href", "http://carrasquilla.faculty.asu.edu/GIT237/smallStyle.css");
} else {
document.getElementById("CSS").setAttribute("href", "http://carrasquilla.faculty.asu.edu/GIT237/largeStyle.css");
}
}
// now call it when the window is resized.
window.onresize = function () {
adjustStyle();
};
window.onload = function () {
adjustStyle();
};
Use CSS and media queries. It's bad idea to change style by js.

Auto-detect a screen resolution and change browser zoom with Javascript?

How do I auto-detect a screen resolution and change browser zoom with Javascript?
I was thinking of something more like this:
I've got the following code:
#warp with width: 3300% and a mask with width: 100%; and then, each .item has width: 3.030303% — with overflow hidden, otherwise it couldn't work as I want.
My point is: I've done this for at least 1280px wide screens.
What I want is if someone can write code that I could use toswitch the CSS file once viewed on a <1280px screen — them, I could do something like:
.item img { width: 80%; } and then, the result would be the same as "browser zoom out".
If you mean change the native browser zoom triggered by CTRL +/- then this isn't possible. You can adjust CSS properties/apply stylesheets but you cannot affect native browser controls. There are in fact CSS only options here depending on your target audience (and their browser choice) through the use of media queries, a couple of examples here and here. If these are not suitable then you can do various things with JavaScript to detect screen width/height and adjust accordingly.
Auto-detect a screen resolution
See this SO question
change browser zoom with javascript
This is not possible. See this SO question.
This will help to detect browser zoom tested on all browser
<script>
window.utility = function(utility){
utility.screen = {
rtime : new Date(1, 1, 2000, 12,00,00),
timeout : false,
delta : 200
};
utility.getBrowser = function(){
var $b = $.browser;
$.extend(utility.screen,$.browser);
utility.screen.isZoomed = false;
var screen = utility.screen;
screen.zoomf = screen.zoom = 1;
screen.width = window.screen.width;
screen.height = window.screen.height;
if($b.mozilla){ //FOR MOZILLA
screen.isZoomed = window.matchMedia('(max--moz-device-pixel-ratio:0.99), (min--moz-device-pixel-ratio:1.01)').matches;
} else {
if($b.chrome){ //FOR CHROME
screen.zoom = (window.outerWidth - 8) / window.innerWidth;
screen.isZoomed = (screen.zoom < .98 || screen.zoom > 1.02)
} else if($b.msie){//FOR IE7,IE8,IE9
var _screen = document.frames.screen;
screen.zoom = ((((_screen.deviceXDPI / _screen.systemXDPI) * 100 + 0.9).toFixed())/100);
screen.isZoomed = (screen.zoom < .98 || screen.zoom > 1.02);
if(screen.isZoomed) screen.zoomf = screen.zoom;
screen.width = window.screen.width*screen.zoomf;
screen.height = window.screen.height*screen.zoomf;
}
}
return utility.screen;
};
window.onresize = function(e){
utility.screen.rtime = new Date();
if (utility.screen.timeout === false) {
utility.screen.timeout = true;
setTimeout(window.resizeend, utility.screen.delta);
}
};
window.resizeend = function() {
if (new Date() - utility.screen.rtime < utility.screen.delta) {
setTimeout(window.resizeend, utility.screen.delta);
} else {
utility.screen.timeout = false;
utility.screen = utility.getBrowser();
if(window.onresizeend) window.onresizeend (utility.screen);
if(utility.onResize) utility.onResize(utility.screen);
}
};
window.onresizeend = function(screen){
if(screen.isZoomed)
$('body').text('zoom is not 100%');
else{
$('body').text('zoom is 100% & browser resolution is'+[screen.width+'X'+screen.height]);
}
};
$(document).ready(function(){
window.onresize();
});
return utility;
}({});
</script>
Demo
RE: Auto-detect a screen resolution and change browser zoom with Javascript?
The question is perfectly possible and is in effect at our website here:
www.noteswithwings.com
JS detects the screen width and zooms out or in a little to fit the content on to the screen.
Further, if the user resizes the window the zoom is triggered.
This actually helps fit content on to tablet sized screens and screens as small as the iphone without adding extra stylesheets or having to detect an OS/ Browser..
var oldZoom = $(window).width();
var windowWidth = $(window).width();
check_window_size(windowWidth,1,bsr,bsr_ver);
$(window).resize(function() {
var windowWidthnow = $(window).width();
check_window_size(windowWidthnow,2,bsr,bsr_ver);
});
function check_window_size(size,init_var,bsr,bsr_ver)
{
/* Develop for resizing page to avoid grey border!
Page layout 1265px wide.
On page resize shift layout to keep central, zoom BG-img to fill screen
Zoom content down for smaller screens by 5% to keep content flow!
*/
//change this var for screen width to work with, in this case our site is built at 1265
var wdth = 1265;
//Change this variable for minimum screen;
var smallest_width=1120;
var varZoom= $(window).width()/wdth;
var s_size = $(window).width();
var scale_smaller;
var center = (s_size-wdth)/2;
var its_ie=false;
if(size<=smallest_width)
{
$("#old_browser").css("width","50%").css({"height":"40px","left": center+"px"});
if(!check_for_object(false,"moved_pages"))
{
if(center<-110)//margin width!
{
if(!its_ie)
$("#scroller").css("zoom",0.95);
$("#footer").css("zoom",0.9).css("left",120+"px");
$(".colmask").css("left",-110+"px");
if(check_for_object(false,"move_menu_loggedin"))
$("#move_menu_loggedin").css("right","110px");
if(check_for_object(false,"login_div"))
$("#login_div").css("left","-80px");
return;
}
$("#move_menu_loggedin").css("left","-"+center+"px");
$("#scroll").css("zoom","normal");
$(".colmask").css("left",center+"px");
}
else
{
/*Only pages that you do not want to move the colmask for!*/
$("#scroller").css("zoom",0.90);//.css("left","-50px");;
$("#footer").css("zoom","normal");
}
}
else
{
if(size>wdth)
$("#background").css("zoom",varZoom);
$("#scroller").css("zoom","normal");
$("#footer").css({"zoom":"normal","left":0});
if(!check_for_object(false,"moved_pages"))
{
$(".colmask").css("left",center+"px");
$(".colmask").css("zoom","normal");
var movelog = -center;
if(check_for_object(false,"move_menu_loggedin"))
$("#move_menu_loggedin").css("right",movelog +"px");
if(check_for_object(false,"login_div"))
$("#login_div").css("left","80px");
}
else
{
$(".colmask").css("zoom","normal");
}
}
}
-- check_window_size(windowWidth,1,bsr,bsr_ver); bsr & bsr_ver are detected using a php class.
-- #old_browser is a div containing information if you have an old web browser.
-- #background is a fixed image 100x100% of the screen.
As you can see we also move a few items which were not in the containing div scope.
Colmask is the containing div for most of the pages content (For us that sits underneath the header which is why we move some items manually)
Hope the code snippet can help someone else achieve this.

Categories