Using Vanilla JS to add inline CSS property and fallback value - javascript

The problem I am trying to solve is basically the issue with Safari iOs and Vh calculations.
Here is the function:
function overflowHandler() {
const header = document.querySelector('.header-container').getBoundingClientRect().height;
const regionTop = document.querySelector('.region-top').getBoundingClientRect().height;
const totalHeaderHeight = header + regionTop;
if (window.innerWidth < 1080) {
flyout.style.height = 'calc(100vh - ' + totalHeaderHeight + 'px)';
}
}
But I need to be able to also pass in height: webkit-fill-available as a style as well to fix the bug on iOS where the user can't scroll completely to the bottom of the nav.
I've tried using element.style.cssText to set both height properties, but whatever is the rightmost value is what gets rendered in the browser.
Example of what I mean would be:
element.style.cssText = 'height: calc(100vh - ' + totalHeaderHeight + 'px); height: -webkit-fill-available;'
would render as height: -webkit-fill-available;
I am at a loss on any other way to make it work or how else to ensure the full height of the menu can be scrolled on iOS.

Use element.setAttribute('style', 'height: -webkit-fill-available;')

Related

Detect bottom of the page on scroll using Vanilla JS in ReactJS

I am developing a React Application and want to Detect the bottom of the page on user scroll using Vanilla JS. I googled it out and found that below check works fine for most of the scenarios -
window.innerHeight + window.scrollY) >= document.body.offsetHeight
It works fine yes when in my react application I have not set height as 100vh in my App.css and index.css. But after setting the height as 100vh in both of them it does not.
I was consoling the values of above params without height as 100vh and below was the output on Galaxy S5 device -
window.innerHeight-> 640 window.scrollY -> 0 document.body.offsetHeight-> 265
Consoling the values of above params with height as 100vh and below was the output on Galaxy S5 device -
window.innerHeight-> 640 window.scrollY -> 0 document.body.offsetHeight-> 640
Below is handleScroll code:
handleScroll = () => {
const {
totalUsersCount, users, currentPage, fetchUsersList,
} = this.props;
console.log('window.innerHeight-> ', window.innerHeight, 'window.scrollY ->', window.scrollY,
'document.body.offsetHeight-> ', document.body.offsetHeight);
if (((window.innerHeight + window.scrollY) >= document.body.offsetHeight)) {
fetchUsersList(currentPage + 1);
}
};
How can I check for the bottom of page scroll, when the height is set as 100vh in Vanilla JS as I doing it in React.
When you set body height to 100vh, scrollHeight will remain the height of your window, whatever total content length actually is. scrollHeight doesn't actually return the height of your whole content (as you'd expect), but the visible space in which it can scroll.
What you want is not height css property value but max-height.
Try changing your css to
body {
/* height: 100vh; */
max-height: 100vh;
overflow: auto;
}
Also I don't think it is good to rely on window height for this, since you might later want to wrap your scrollable area (by adding a header for example), thus you'll loss some extra weight and might get errors in your calculation. If you have a reference (wether in React or with vanilla DOM parsing) to the element that handle the scroll (the one that contains your scrollbar), you can use the following test in your scroll function :
handleScroll = () => {
//...
if (target.scrollTop >= (target.scrollHeight - target.offsetHeight)) {
//... your stuff
}
}
Since for now body is your target, you can just :
handleScroll = () => {
//...
if (document.body.scrollTop >= (document.body.scrollHeight - document.body.offsetHeight)) {
//... your stuff
}
}
You need to use document.body.scrollHeight to get the actual height.
Reference : https://javascript.info/size-and-scroll-window#width-height-of-the-document
UPDATED:
for a specific element use any of the selectors and get its scroll height.
const el = document.getElementById('#id');
const scrollHeight = el.scrollHeight;

jquery css applied but not visible for flex element

I find myself struggling to understand why my approach at recalculating width of an element on resize and seeing the result doesn't work.
Scenario:
I have a flex layout, with 3 unequally wide containers divided into 3/7, 1/7 and 3/7 of the width of the page. I use width: calc(100%/7) or width: calc(100%/7*3) to let the browser calculate the relation of these containers.
I am aware of the issue that Chrome rounds the calculated values down in case there is an inaccuracy when calculating the relation. This is visible when resizing the browser window as a subpixel-wide white stripe, where the background shines through between the containers on certain widths. Note: this problem does not happen in Firefox, they seem to round these values differently (?).
What I tried:
I used jQuery and parseFloat(document.getComputedStyle(element).width) to get the values of the containers and calculate the difference in order to "stretch" the middle container to fill in the gap:
jQuery(window).on('resize', function () {
var mainSite = document.getElementsByClassName('site-main')[0];
var leftStart = document.getElementsByClassName('page-trigger left')[0];
var middleStart = document.getElementsByClassName('page-trigger middle')[0];
var rightStart = document.getElementsByClassName('page-trigger right')[0];
var mainSiteWidth = parseFloat(window.getComputedStyle(mainSite).width);
var leftStartWidth = parseFloat(window.getComputedStyle(leftStart).width);
var middleStartWidth = parseFloat(window.getComputedStyle(middleStart).width);
var rightStartWidth = parseFloat(window.getComputedStyle(rightStart).width);
console.log(mainSiteWidth);
console.log(leftStartWidth);
console.log(middleStartWidth);
console.log(rightStartWidth);
var calculatedElementWidth = leftStartWidth + middleStartWidth + rightStartWidth
if (mainSiteWidth > calculatedElementWidth){
var diff = mainSiteWidth - calculatedElementWidth;
var newMiddleWidth = middleStartWidth + diff;
console.log("diff: " + diff);
console.log("new middle width: " + newMiddleWidth);
jQuery(middleStart).css({
flex : "0 0 " + newMiddleWidth + "px",
width: newMiddleWidth + "px",
minWidth: newMiddleWidth + "px",
maxWidth: newMiddleWidth + "px"
});
console.log(parseFloat(window.getComputedStyle(middleStart).width));
}
}).resize();
So far, the values get correctly calculated and even applied to the middleStart element, at least in the DOM inspector, however, the gap is still there, even though the css values indicate, it should have changed.
These were the css settings before the jquery modifications:
flex: 0 0 calc(100%/7); --> translates to 273.562px, Chrome shows as 273.56px
width: calc(100%/7); --> translates to 273.562px, Chrome shows as 273.56px
min-width: calc(100%/7); --> translates to 273.562px, Chrome shows as 273.56px
max-width: calc(100%/7); --> translates to 273.562px, Chrome shows as 273.56px
These are the values in the DOM inspector after that:
flex: 0 0 273.594px;
width: 273.594px;
min-width: 273.594px;
max-width: 273.594px;
I tried to create a jsfiddle but I couldn't reproduce that issue there, since my layout is more complex and has more layers.
Does anybody have an idea, why the css settings, though being applied to the element in the DOM, are not visible?
EDIT: this is what happens, try to resize the browser window horizontally (please ignore the occasional jump of the right element, I had to use float:left; to make it reproducable and it only happens in Chrome: jsfiddle

Render div content in fullhd then proportional scale

TV shows slides, that holds HTML inside. TV's resolution is FullHD (1920x1080).
When editing the slide I want to able to know, how slide will exactly be shown on TV. Although I have a FullHD monitor, I've never worked in the browser in fullscreen mode. Other people, which potentially be working with slides, want to see slides as is too.
Using another word, I need to render 1920x1080 div, then proportionally scale it to fit client's browser. How can be this done using CSS or JS, or jQuery?
Edit: I do NOT need to proportional manipulate the image. I need to see how page will look on FullHD resolution regardless of client's viewport resolution
UPDATED!! Here is the demo: https://jsfiddle.net/8jxk0atm/4/
Old resize 1920x1080 aspect ratio demo: https://jsfiddle.net/8jxk0atm/2/
You can create the div spec with 1920x1080. And put this
// screen zoom out for checking
document.body.style.zoom="40%"
on top of your js code.
It will zoom out your document so you can see what it will look on 1920x1080 div.
HTML
<div id="fullscreen"></div>
CSS
html,
body {
margin: 0;
padding: 0;
}
#fullscreen {
width: 1920px;
height: 1080px;
background: green;
color: #fff;
}
JS
// screen zoom out for checking
document.body.style.zoom="40%"
makeFullHD();
function makeFullHD() {
var value = $(window).outerWidth();
value *= 1;
var valueHeight = Math.round((value / 16) * 9);
$('#vidHeight').text(valueHeight);
$('#videoBox').css('width', value + 'px').css('height', valueHeight + 'px');
$('#videoPlayer').css('width', value + 'px');
$('#fullscreen').css({
width: value,
height: valueHeight
});
// test
$('#fullscreen').text('Width:' + value + '\n' + 'Height:' + valueHeight);
}
$(window).resize(function() {
makeFullHD();
});

Foundation 6: How to set .is-open-right translateX value with JavaScript

I am building a website with Foundation 6 using CSS instead of SCSS. I'm using the responsive off-canvas drill-down menu on small screens, and by default, the off-canvas menu width is 250px.
Problem: I would like this to be the full width of the browser window instead.
Setting the Width
I have used JavaScript to dynamically set the .off-canvas.position-right width to the width of the window, and right to the negative width of the window. I've also set the .off-canvas .drilldown max-width to the width of the window.
This works well, and here's how I did it:
function setOffCanvasWidth() {
var windowWidth = window.innerWidth,
offCanvasRight = document.querySelector( '.off-canvas.position-right' ),
isDrilldown = document.querySelector( '.off-canvas .is-drilldown' );
offCanvasRight.style.width = windowWidth + "px";
offCanvasRight.style.right = "-" + windowWidth + "px";
isDrilldown.style.maxWidth = windowWidth + "px";
}
setOffCanvasWidth();
I'm happy with this part, but it only solves half of the problem.
Moving the Off-Canvas
In addition to dealing with the width of the menu, .is-open-right is moving everything over by -250px using transform: translateX().
I tried including these lines in my function to set the transform: translateX() value to the negative width of the window:
var offCanvasWrapperInner = document.querySelector( '.off-canvas-wrapper-inner.is-off-canvas-open.is-open-right' );
offCanvasWrapperInner.style.transform = "translateX(-" + windowWidth + "px)";
But this didn't work. I think it has to do with the fact that .off-canvas-wrapper-inner doesn't have the class .is-open-right when the window loads. That class is added dynamically after clicking the hamburger toggle button, which has a class of .menu-icon. So I tried adding a click event listener, but it still doesn't work.
Here is my JS code in its entirety:
function setOffCanvasWidth() {
var windowWidth = window.innerWidth,
offCanvasRight = document.querySelector( '.off-canvas.position-right' ),
isDrilldown = document.querySelector( '.off-canvas .is-drilldown' ),
menuIcon = docuemnt.querySelector( '.menu-icon' ),
offCanvasWrapperInner = document.querySelector( '.off-canvas-wrapper-inner.is-off-canvas-open.is-open-right' );
offCanvasRight.style.width = windowWidth + "px";
offCanvasRight.style.right = "-" + windowWidth + "px";
isDrilldown.style.maxWidth = windowWidth + "px";
menuIcon.addEventListener( 'click', function() {
offCanvasWrapperInner.style.transform = "translateX(-" + windowWidth + "px)";
} );
}
setOffCanvasWidth();
Where Am I Going Wrong?
I'm not looking for anyone to code the solution for me, necessarily, but any feedback and direction on how I might set the .is-open-right translateX value would be very helpful.
Here is the entire project code: https://github.com/paulshryock/paulshryock/releases/tag/v0.0.1
Here is a live demo: https://paulshryock.github.io/paulshryock/
Use a translateX value of -100%. Percentage transformations are based on the element's dimensions, so 100% would be equal the element's width. At this point no JavaScript would be needed.
On that note, I would recommend setting the menu's left to 100% instead of setting right to the negative width.

Calculating width of scrollbar and using result in calc() css

I want to calculate the width of the scrollbar so that I use the result in a CSS calc() declaration.
At the moment, I assume that the width of the scrollbar is always 17px, like this:
body {
width:calc(100vw - 17px);
}
.container {
max-width:calc(100vw - 17px);
}
The problem with this is when you choose a different browser zoom %, the width of the scrollbar changes. So I want to use the result of the calculation to do something along these lines:
body {
width:calc(100vw - CALCULATED SCROLL-BAR WIDTH);
}
.container {
max-width:calc(100vw - CALCULATED SCROLL-BAR WIDTH);
}
EDIT: I've now solved the problem with the help of this question
The JavaScript used to calculate the scrollbar width (though, I have found you require an interval to get it to autoupdate):
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;
}
My code (which is used to embed the result of the function into a CSS calc() declaration).
$('body').css({
'width':'calc(100vw - ' + getScrollbarWidth() + 'px)'
});
$('.container').css({
'max-width':'calc(100vw - ' + getScrollbarWidth() + 'px)'
});
Actually, you can get the scrollbar width just with css and custom properties (and completely without javascript):
body {
--scrollbar-width: calc(100vw - 100%);
}
Then you can use this variable in a child element like this:
.container {
max-width: calc(100vw - var(--scrollbar-width));
}
This is because 100vw is always the inner width of the view, but the 100% of the body does not include the scrollbar.
Expanding jonas_jonas's answer, it can work but if .container must have the same width as the body.
If that's not the case, even so you can make it work with vanilla JS, defining a CSS property like this
document.body.style.setProperty(
"--scrollbar-width",
`${window.innerWidth - document.body.clientWidth}px`
);
And then you can use it in CSS
.container {
max-width: calc(100vw - var(--scrollbar-width));
}
Why you need so much code to do that?
The easy way with plain javascript it's:
$('body').css({
'width':'calc(100vw - ' + (window.innerWidth - document.body.clientWidth) + 'px)'
});

Categories

Resources