On my page I have a:
<div id="id_modal_background"></div>
that is between a modal login window and a background image. It's task is to (a) blur the background image once the modal login window is shown and (b) dismantle the blur when modal login window is closed.
In order for the blur to look nice it needs transition time of 1s, which is set in CSS like this:
#id_modal_background{
z-index: 2;
display: block;
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
transition: 1s;
}
But this transition time gives me side effects on phones where change of the orientation from landscape to portrait (but not vice versa) needs 1s to redraw the blur. And it doesn't looks nice.
I am using this function to draw (id_modal_background_visibility(1)) or dismantle (id_modal_background_visibility(0)) the blur:
function id_modal_background_visibility(a){
let r = '';
let m = document.getElementById('id_modal_background');
switch(a){
case 0:
r = 'OFF';
// In order to reference "backdrop-filter" we camelcase it!
m.style.backdropFilter = 'blur(0px) grayscale(0)';
m.style.visibility = 'hidden';
break;
case 1:
r = 'ON';
// In order to reference "backdrop-filter" we camelcase it!
m.style.visibility = 'visible';
m.style.backdropFilter = 'blur(15px) grayscale(0.25)';
break;
default:
r = 'ERROR';
m.style.visibility = 'hidden';
break;
}
console.log('Modal background visibility: ' + r);
}
If anyone can help me to remove the transition time that happens at any kind of orientation change, but keep the transition time otherwise, I would be more than happy.
You can make use of css media queries
#media (orientation: landscape) {
}
Read more here How to set portrait and landscape media queries in css?
You can manage your code like below :
window.addEventListener("orientationchange", function() {
if(window.innerHeight > window.innerWidth){
console.log("Portrait");
} else {
console.log("Landscape");
}
}, true);
And you can apply CSS class accordingly. Also media query CSS is a possible way for your problem.
Related
I'm working on a simulation of the famous Prague astronomical clock. It's only partially done, but the work-in-progress can be seen here: https://shetline.com/orloj/
The page layout consists of an SVG image of the clock, plus a control panel for setting date, time, longitude, and latitude. The clock needs to expand to fill available space. The control panel is close to a fixed size, but can shrink a bit for smaller displays.
What I want (and I think should be MUCH easier to do) is for the contents of the web page to display nicely and neatly like this:
The tricky thing has been getting the layout to use available space well, but without needing to be scrolled, and without any components being clipped or hidden. What was especially difficult was automatically sizing things regardless of whether "chrome" (i.e. address and navigation bars) was being displayed or not.
Simple solutions only worked partially for me -- the user might have to pinch and scroll to get things right, manually hide toolbars, forcibly refresh after changing from landscape to portrait orientation, etc.
These are the difficulties I ran into:
With mobile browsers like Safari, 100vh was taller than window.innerHeight, so if I scaled using vh units, parts of what I wanted to display would be cut off until the user manually hid the toolbars. In desktop browsers, however, 100vh and window.innerHeight were always in sync.
Orientation changes weren't consistently reported. Safari didn't generate any resize events when the orientation of my phone was changed, only now-deprecated orientationchanged events. On one Android tablet I experimented with, orientation changes produced no browser events at all that I was aware of at all.
When the orientation changed, window.screen.width and window.screen.height weren't swapped as I would have expected... unless I was using the Chrome console responsive layout test.
After receiving resize or orientationchanged events, some of the values I needed to check like window.innerHeight weren't "settled" yet, so I needed to use setTimeouts to recheck if values changed over time.
When a user manually zooms into the display, the zoom state is sort of "sticky" and can keep the layout from returning to the preferred state after orientation changes.
All of this meant coming up with a bunch of ad hoc hackery to get the results I wanted. But this seems like such a basic result kind of layout effect to want to get, I can't help but wondering if I've made this much harder than it should be, and there isn't a much easier solution that I'm missing.
Here's the code I used to solve this layout:
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
:root {
--mfh: 100vh; // mobile full height
--mvh: 1vh; // mobile vh-like unit
}
html {
height: 100%;
margin: 0;
overflow: hidden;
width: 100%;
}
body {
background-color: #4d4d4d;
font: 14px sans-serif;
height: var(--mfh);
left: 0;
margin: 0;
position: absolute;
top: 0;
width: 100vw;
}
// Get scrolling, zooming, and panning back if display is very small:
#media screen and (orientation:landscape) and (max-height: 340px),
screen and (orientation:landscape) and (max-width: 630px),
screen and (orientation:portrait) and (max-width: 360px),
screen and (orientation:portrait) and (max-height: 740px)
{
html {
overflow: auto;
}
body {
position: static;
}
}
const docElem = document.documentElement;
const doResize = (): void => {
setTimeout(() => {
const height = window.innerHeight;
const disallowScroll = docElem.style.overflow === 'hidden';
docElem.style.setProperty('--mfh', height + 'px');
docElem.style.setProperty('--mvh', (height * 0.01) + 'px');
if (this.lastHeight !== height) {
this.lastHeight = height;
if (disallowScroll && (docElem.scrollTop !== 0 || docElem.scrollLeft !== 0)) {
docElem.scrollTo(0, 0);
setTimeout(doResize, 50);
}
else
this.updateGlobe();
}
});
};
let lastW = window.innerWidth;
let lastH = window.innerHeight;
const poll = (): void => {
const w = window.innerWidth;
const h = window.innerHeight;
const disallowScroll = docElem.style.overflow === 'hidden';
if (lastW !== w || lastH !== h || (disallowScroll && (docElem.scrollTop !== 0 || docElem.scrollLeft !== 0))) {
lastW = w;
lastH = h;
doResize();
}
setTimeout(poll, 100);
};
poll();
doResize();
Full code is here: https://github.com/kshetline/prague-clock
When I click on the Maximize button of the browser window, a function I wrote that will execute when the window is resized, does not work properly I think because JavaScript window resize event is running slow. It worked when I used the mouse to resize the window. Also, when I tried to change between portrait mobile to landscape mobile it is also slow.
Faced a problem with using with window.addEventListener('resize', aFunction), page gets slow. These events are generated multiple times per second, and if the event handler takes too much time, the browser won’t catch with redrawing the page.
function aFuntion() {
let div1 = document.querySelector('.div1');
let div2 = document.querySelector('.div2');
let diff = div1.clientHeight - div2.clientHeight;
div2.style.top = diff + 'px';
};
// Call the function.
// This worked!
aFuntion();
// Call the function when users resize the window.
// This worked!
window.addEventListener('resize', aFuntion);
// Users click on the Maximize button of the window.
// The function does not work properly!
// Portrait mobile to Landscape mobile.
// The function does not work properly!
.div1 {
position: relative;
}
.div2 {
position: absolute;
width: 300px;
top: 0;
transition: all 0.5s ease;
}
#media only screen and (max-width: 1024px) {
.div2 {
width: 200px;
}
}
<div class="div1">
<div class="div2"></div>
</div>
I removed transition: all 0.5s ease; and it worked for a while now it is not working again.
So, I know now it is because of window.addEventListener('resize', function) is running slow.
Try this:
var timeout = false;
window.addEventListener('resize', function() {
clearTimeout(timeout);
timeout = setTimeout(aFuntion, 200);
});
Read: https://bencentra.com/code/2015/02/27/optimizing-window-resize.html
try with document.addEventListener('resize', aFuntion);
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/
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.
Firefox now supports full screen mode on the video html5 tag. ( right click on the movie .. )
Is there any way to create a control ( html tag ) to do this like this play/pause example ( using js ) ?
<script>
function play(){
var video = document.getElementById('movie');
var play = document.getElementById('play');
play.addEventListener('click',playControl,false);
function playControl() {
if (video.paused == false) {
video.pause();
this.firstChild.nodeValue = 'Play';
pauseCount();
} else {
video.play();
this.firstChild.nodeValue = 'Pause';
startCount();
}
}
}
basically all you need is creating a function (triggered by a fullscreen button) in which you assign a position: absolute, and an higher z-index to the video wrapper
the you will assign both video and video wrapper width and height : 100% (or fixed size if you prefer)
probably the best way to achieve this behaviour is defining a class (e.g. fullscreen) and assign it to the container, something like
.fullscreen {
position : absolute;
z-index : 1000;
width : 100%;
height : 100%;
top : 0;
left : 0;
}
.fullscreen video {
width : 100%;
height : 100%;
}
so the function call (fullscreen/normal view) is a switch for the .fullscreen class.