How to center container on resize using onWindowResize - javascript

I'm using a script that is resizing my .container when my window is resized. This is my page: http://cjehost.com/qt/nipt/page6.php
If you resize the browser window, you'll see the container resize but not stay centered. Is there a way to center my container? Here is my script:
// Resize the map to fit within the boundaries provided
function resize(maxWidth, maxHeight) {
var image = $('img'),
imgWidth = image.width(),
imgHeight = image.height(),
newWidth = 0,
newHeight = 0;
if (imgWidth / maxWidth > imgHeight / maxHeight) {
newWidth = maxWidth;
} else {
newHeight = maxHeight;
}
image.mapster('resize', newWidth, newHeight, resizeTime);
}
// Track window resizing events, but only actually call the map resize when the
// window isn't being resized any more
function onWindowResize() {
var curWidth = $(window).width(),
curHeight = $(window).height(),
checking = false;
if (checking) {
return;
}
checking = true;
window.setTimeout(function() {
var newWidth = $(window).width(),
newHeight = $(window).height();
if (newWidth === curWidth &&
newHeight === curHeight) {
resize(newWidth, newHeight);
}
checking = false;
}, resizeDelay);
}
$(window).bind('resize', onWindowResize);
My css:
.container {margin:0 auto;}

I would recommend really a CSS approach instead of JavaScript approach for this one. Responsive CSS with #media queries are there for this. Don't use DOM Manipulations with JavaScripts, that are really costly in the terms of performance.
CSS Centering
.parent {
position: relative;
}
.child {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
#media Queries
#media screen and (max-width: 380px) {
// Styles for Mobiles
}
#media screen and (min-width: 381px) and (max-width: 760px) {
// Styles for Tablets
}
#media screen and (min-width: 761px) {
// Styles for Desktops
}
You can find an exhaustive list online.

I managed to make this work by replacing window with .container (my container div). It's still a bit clunky - i.e. when I switch to full screen from smaller resolutions the container doesn't always resize. Here is my working code:
// Track window resizing events, but only actually call the map resize when the
// window isn't being resized any more
function onWindowResize() {
var curWidth = $('.container').width(),
curHeight = $('.container').height(),
checking = false;
if (checking) {
return;
}
checking = true;
window.setTimeout(function() {
var newWidth = $('.container').width(),
newHeight = $('.container').height();
if (newWidth === curWidth &&
newHeight === curHeight) {
resize(newWidth, newHeight);
}
checking = false;
}, resizeDelay);
}
$(window).bind('resize', onWindowResize);
$(window).resize(onWindowResize);
});
Here is a working fiddle: enter link description here
I found reference to this approach and fiddle here: enter link description here
Thanks to #LBF

Related

Incremental CSS Media Queries

Consider a stylesheet that resizes the page as the height diminishes using media queries and transform:
#media (max-height: 620px) {
body {
transform: scale(0.95);
}
}
#media (max-height: 590px) {
body {
transform: scale(0.90);
}
}
#media (max-height: 560px) {
body {
transform: scale(0.85);
}
}
// and so on ...
The page "zooms out" as the window height diminishes, allowing the full content to be displayed on smaller screens.
If I want to support screens smaller than 560px height, I need to add more media queries.
Notice that for each 30px lost in height, we call scale with 0.05 less in the input.
Question: Is it there a way to define incremental media queries using only css?
Follow Up: If a pure css solution is not available, what would be the simplest way of accomplishing such effect in vanilla JS?
Edit: Thank you all for posting different solutions to this problem. I appreciate your help. Your answers helped me learn how to improve my code.
This is not possible using CSS alone. You can do this using JS by adding a window.onresize function to watch for resizing and scaling the body of the document. This solution also scales dynamically so you do not need to worry about breakpoints or #media queries.
function updateScale() {
let viewScale = window.innerHeight / document.documentElement.scrollHeight;
document.body.style = 'transform:scale(' + viewScale + ')';
document.documentElement.scrollHeight = window.innerHeight;
}
window.onresize = function() {
updateScale();
}
updateScale();
body {
transform-origin: 0 0;
margin: 0;
padding: 0;
overflow: hidden;
}
#block {
background-color: black;
width: 300px;
height: 4000px;
}
<div id='block'></div>
#NathanFries is correct, this isn't something that is possible with native CSS.
CSS includes viewport units for percentage-based values for your width and height, but you can't pass that onto the scale() function.
You'd then need to tie this to some resize event listener.
Here is a quick example that might accomplish what you're looking to do:
// #see https://github.com/WICG/EventListenerOptions/blob/9dcca95/explainer.md#feature-detection
// #example `elem.addEventListener('touchstart', fn, supportsPassive ? { passive: true } : false);`
var checkSupportPassiveEvents = function() {
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
},
});
window.addEventListener('testPassive', null, opts);
window.removeEventListener('testPassive', null, opts);
} catch (e) {}
return supportsPassive;
};
var supportsPassive = checkSupportPassiveEvents();
var mapRange = function(fn, inStart, inEnd, outStart, outEnd) {
if (outStart === void 0) {
outStart = inStart;
outEnd = inEnd;
inStart = 0;
inEnd = 1;
}
var inRange = inEnd - inStart,
outRange = outEnd - outStart;
return function(val) {
var original = fn((val - inStart) / inRange);
return outStart + outRange * original;
};
};
var linear = function(x) {
return x;
};
var minHeight = 320;
var maxHeight = 620;
var minScale = 0.45;
var maxScale = 1;
var screenHeightToScaleFactorInner = mapRange(linear, minHeight, maxHeight, minScale, maxScale);
var screenHeightToScaleFactor = function(height) {
if (height <= minHeight) {
return minScale;
} else if (height > maxHeight) {
return maxScale;
} else {
return screenHeightToScaleFactorInner(height);
}
};
window.addEventListener(
'resize',
function(e) {
var height = this.innerHeight;
this.document.body.style.transform = 'scale(' + screenHeightToScaleFactor(height) + ')';
},
supportsPassive ? { passive: true } : false
);
You may have to use vanilla JavaScript in this case.
So, each 30px is 0.05, or each 6px is 0.01 from 650px down.
It means an amount of 600px is 1 in scale and that each pixel is 0.01/6.
With all that information in mind, we can use resize event to calculate this:
window.addEventListener('resize', changeTransform); // when resize, call changeTransform
var bodyEl = document.querySelector('body');
function changeTransform() {
var scale = 1; // default scale
if (window.innerHeight < 650) { // if window height < 650px, do magic
scale = -0.83 + (0.05/30)*window.innerHeight;
}
bodyEl.style.transform = "scale(" + scale + ")"; // apply scale (1 or the calculated one)
}
Hope it can help you somehow.
For a CSS solution you can consider vh and vw unit but it won't be possible with scale since this one need a unitless value.
A different approach would be to use translateZ() and some perspective to simulate a scale animation.
Here is a basic example. The result isn't accurate as I simply want to demonstrate the trick. Run the snippet full page and adjust the window height and you will see the element scaling.
.box {
width:100px;
height:100px;
background:red;
transform:perspective(180px) translateZ(15vh);
transform-origin:top left;
}
<div class="box">
some text here
</div>
You simply need to find the correct calculation for the different values.

How to make a RadWindow responsive based on screen / viewport size using JavaScript and CSS Grid

I've been looking for a solution to make a Telerik RadWindow work responsively. There are two things that need to be responsive, the contents in the RadWindow, and the RadWindow itself.
Problem:
Per Telerik: "RadWindow does not support responsive size change and it does not change size automatically according to the viewport, because the behavior in such a scenario cannot be strictly defined"
Solution: (The contents inside the RadWindow need to be responsive, as does the RadWindow itself)
RadWindow Contents:
I used CSS Grid to make the contents of the RadWindow responsive in this example.
.sectionSearch {
display: grid;
grid-gap: 3px;
grid-template-columns: repeat(auto-fit, 200px);
align-items: end;
max-width: 809px;
}
RadWindow Responsiveness:
The viewport can be set to a percentage of the screen, per this article. You can then use JavaScript media queries to adjust the percentages of the height and width of the viewport, depending on the size of the screen.
Using a combination and modification of a few posts, including this one, the following sample solution worked for my needs of making a RadWindow responsive.
var $ = $telerik.$;
var radwindow;
function pageLoad() {
radwindow = $find("<%= radwindow.ClientID%>");
}
$(window).resize(function () {
if (radwindow.isVisible()) {
setWindowsize();
}
});
function setWindowsize() {
//var viewportWidth = $(window).width();
//var viewportHeight = $(window).height();
/* ==================================================== */
// media query event handler
if (matchMedia) {
var mqls = [ // array of media queries
window.matchMedia("(min-width: 0px) and (max-width: 399px)"),
window.matchMedia("(min-width: 400px) and (max-width: 600px)"),
window.matchMedia("(min-width: 600px) and (max-width: 800px)"),
window.matchMedia("(min-width: 800px) and (max-width: 1000px)"),
window.matchMedia("(min-width: 1000px) and (max-width: 4000px)")
]
for (i = 0; i < mqls.length; i++) { // loop though media queries
mqls[i].addListener(WidthChange); // listen for queries
WidthChange(mqls[i]); // call handler func at runtime
}
}
// media query change
function WidthChange(mql) {
if (mqls[0].matches) {
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
radwindow.setSize(Math.ceil(viewportWidth * 90 / 100), Math.ceil(viewportHeight * 90 / 100));
} else if (mqls[1].matches) {
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
radwindow.setSize(Math.ceil(viewportWidth * 90 / 100), Math.ceil(viewportHeight * 60 / 100));
} else if (mqls[2].matches) {
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
radwindow.setSize(Math.ceil(viewportWidth * 90 / 100), Math.ceil(viewportHeight * 40 / 100));
} else if (mqls[3].matches) {
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
radwindow.setSize(Math.ceil(viewportWidth * 90 / 100), Math.ceil(viewportHeight * 40 / 100));
} else if (mqls[4].matches) {
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
radwindow.setSize(Math.ceil(viewportWidth * 70 / 100), Math.ceil(viewportHeight * 45 / 100));
}
}
radwindow.center();
}

Jquery add CSS class after 'X' amount of viewport height scrolled

So I have this jQuery function that adds / removes a CSS class to an element after 600px of the viewport height has been scrolled.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 600) {
$(".cta_box").addClass('fadeout');
} else {
$(".cta_box").removeClass('fadeout');
}
});
I'd like to tweak it so instead of working based off a pixel value, it works off of the view height css measurement "VH", but the equivalent results are what matter in this case.
It can be done by getting the window height using $(window).height().
For instance suppose you have to scroll half the screen more (height is 150vh) and you have to detect when 40% has been scrolled:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 0.4 * $(window).height()) {
$(".cta_box").addClass('fadeout');
} else {
$(".cta_box").removeClass('fadeout');
}
});
body{
margin: 0;
height: 150vh;
}
.cta_box {
height: 100%;
background: green;
}
.cta_box.fadeout {
background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="cta_box"></div>
Use a percentage of the window height to compare
$(window).scroll(function() {
var height = $(window).height(),
scroll = $(window).scrollTop()
limit = 0.6; //implies 60 vh or 60% of viewport height
if (scroll >= height*limit) {
$(".clearHeader").addClass("darkHeader");
} else {
$(".clearHeader").removeClass("darkHeader");
}
});
and even better would be to update some variable only when the window is resized to avoid computations all the time
var limit = 0.6, //implies 60 vh or 60% of viewport height
scrollLimit = 0;
$(window).resize(function(){
scrollLimit = $(window).height() * limit;
}).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= scrollLimit ) {
$(".clearHeader").addClass("darkHeader");
} else {
$(".clearHeader").removeClass("darkHeader");
}
}).trigger('resize').trigger('scroll'); // trigger both events on start to force initial setup
Try something like this
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
$(".clearHeader").addClass("darkHeader");
} else {
$(".clearHeader").removeClass("darkHeader");
}
});
For retrieveing the viewport Height, you could use $(window).innerHeight():
$(window).scroll(function() {
var scroll = $(window).innerHeight();
if (scroll >= 600) {
$(".cta_box").addClass('fadeout');
} else {
$(".cta_box").removeClass('fadeout');
}
});
Hope this helps.
Leo.

If statement works on resize, not ready?

I am trying to accomplish two things:
The main content div will be dynamically sized to fit the exact height of the window. I accomplish that goal with this function:
$(document).on( 'ready', function() {
panelsResize();
$(window).on( 'resize', panelsResize );
});
function panelsResize() {
var screenHeight = $(window).height();
var screenWidth = $(window).width();
if (screenWidth > 768) {
$( ".panels" ).css( "height", screenHeight );
}
};
The class .panels is applied to the main content area.
This works swell.
I am trying to fill the .panels with the images in.large. These images need to retain aspect ratio while being scalable. I have based my code on this answer.
This works, but not on ready. I have to resize the screen, dropping below the media query that switches the display for .large to none. When I resize to the higher media query, switching display to block, the functionality works perfect.
Any ideas?
Here's the function (and markup):
$(document).on( 'ready', function() {
bgResize();
$(window).on( 'resize', bgResize );
});
function bgResize(){
$( '.large' ).each(function() {
var th = $(window).height(),//box height
tw = $(window).width(),//box width
im = $(this).children('img'),//image
ih = im.height(),//inital image height
iw = im.width();//initial image width
if ( iw < tw ) {
im.css( { "width" : "100%", "height" : "auto" } );
}
else if ( ih < th ) {
im.css( { "height" : "100%", "width" : "auto" } );
}
var nh = im.height(),//new image height
nw = im.width(),//new image width
hd = (nh-th)/2,//half dif img/box height
wd = (nw-tw)/2;//half dif img/box width
if (nh<nw) {
im.css({marginLeft: '-'+wd+'px', marginTop: 0});//offset left
} else {
im.css({marginTop: '-'+hd+'px', marginLeft: 0});//offset top
}
});
};
This is the HTML:
<ul id="homePanels">
<li id="cat1" class="panels">
<div class="large">
<img src="#" alt="" />
</div>
<div class="small">
<img src="#" alt="" />
</div>
</li>
</ul>
The CSS:
#homePanels {
list-style: none;
margin:0;
padding:0;
overflow: hidden;
}
.large {
width:100%;
height:100%;
}
#media (min-width: 768px) {
.large{display: block;}
.small{display:none}
}
#media (max-width: 768px) {
.small {display:block;}
.large {display:none;}
}
i think it will work if you use jQuery ready() function.
$(document).ready(function() {
bgResize();
$(window).on('resize', bgResize );
});
You just need to change
$(document).on( 'ready', function()
for
$(document).ready( function()
Thanks! I made the change to the ready event.
I realized that using the image's width and height were causing the issue, since I was grabbing, basically, two 0s. So, since I knew the aspect ratio of the images, I used that to scale the images on screen resize.
var screenHeight = $(window).height(),
screenWidth = $(window).width(),
aspectRatio = 0.57066014669927,
screenAspectRatio = screenHeight / screenWidth;
if ( screenAspectRatio < aspectRatio ){
$("img").css({"width" : "100%" , "height" : "auto"});
} else if ( screenAspectRatio > aspectRatio ){
$("img").css({"width" : "auto" , "height" : "100%"});
}
But it's solved now. Thanks for your help!

Resizing a web page dynamically

I am developing a bunch of small web applications that have an unknown window size as target. To solve this problem, I am developing very large layouts and scaling them according to the window size.
My solution however has an inconvenience. When I resize everything, things get a little bit out of place (mainly when scaling text) and it is noticeable. My code is very simple, everything in my page is absolutely positioned so I just get the scaling factor and apply it to all the positions and width / height of every div/img/span/input in the page. The code is as follows:
function resize()
{
var wh = $(window).height();
var h = maxHeight;
var ww = $(window).width();
var w = maxWidth;
var wProp = ww / w;
var hProp = wh / h;
if (wProp < hProp) prop = wProp;
else prop = hProp;
if (prop > 1) prop = 1;
console.log(prop);
$("div").each (applyNewSize);
$("img").each (applyNewSize);
$("span").each (applyNewSize);
$("input").each (applyNewSize);
}
//this is run when the page is loaded
function initializeSize (i)
{
this.oX = $(this).position().left;
this.oY = $(this).position().top;
this.oW = $(this).width();
this.oH = $(this).height();
if ($(this).css("font-size") != undefined)
{
this.oFS = Number($(this).css("font-size").split("px")[0]);
}
}
function applyNewSize (i)
{
if (this.oFS != undefined) $(this).css("font-size", Math.round(this.oFS * prop) + "px");
$(this).css("left", Math.round(this.oX * prop) + "px");
$(this).css("top", Math.round(this.oY * prop) + "px");
$(this).width(Math.round(this.oW * prop));
$(this).height(Math.round(this.oH * prop));
}
This problem has been tormenting me for the past week. Do you have any workaround or solution for this?
I recommend you to read about Responsive Web design.
It works putting % instead the exact pixels :
<div class="container">
<section>
THIS IS THE SECTION
</section>
</div>
CSS::
.container{
width: 80%; // 80% instead pixels
background: gainsboro;
border: 3px inset darkgrey;
height: 200px;
margin:auto;
text-align:center;
}
section{
width: 80%; // 80% instead pixels
height: 80%; // 80% instead pixels
background: darkgrey;
margin:auto;
}
Then you can use media queries as well, to reallocate the blocks or applying different styles on different widths :
example tutorial : http://css-tricks.com/css-media-queries/

Categories