When working on responsive designs I make use of CSS3 media queries, including with older browsers using respond.js. There are occasions when I also need to use JavaScript/jQuery for manipulating some elements on the page. However, when using $(window).width(), that value is often different than the value used in the CSS media query due to browser chrome and/or the presence of a vertical scrollbar, meaning a CSS media query will fire at a different breakpoint than the JS media query.
I know Modernizr alleviates this issue through the use of Modernizr.mq, but that only works in browsers that support CSS media queries to begin with, generally meaning it won't work in IE8 and below. And if you use a polyfill for adding media query support to these older browsers (e.g., respond.js), then the Modernizr.mq no longer works due to a conflict/override between the two.
What I've instead done is made use of a hidden input element on the page and given it a CSS width style within each of the media queries. I then have a function that runs automatically on the page (and on resize) that gets that width value and executes the following:
if (width == "320px" ) {
//Functions
}
//481px to 600px
else if (width == "481px" ) {
//Functions
}
//601px to 768px
else if (width == "601px" ) {
//Functions
}
//769px to 960px
else if (width == "769px" ) {
//Functions
}
//769 to 1024px
else if (width == "961px" ) {
//Functions
}
//1024px+
else {
//Functions
}
This basically forces the JS to work entirely off of the CSS media query, syncing the two. This can become more specific rather than generic as I have it, instead firing based off of a specific element and a specific style that changes on that element, it depends on individual project needs.
My question then is, is there a simpler way of doing this? I've spent considerable time looking into and experimenting with this and it seems the best option thus far that takes into account older browsers as well.
PPK listed a nice way to pair the CSS & JS on his blog which sort of backs up your method:
#media all and (max-width: 900px) {
// styles
}
if (document.documentElement.clientWidth < 900) {
// scripts
}
His full post on it is here.
There's also the enquire.js plug-in.
Related
My dev site uses lots of Skrollr animation at 1024px resolutions and up. Under 1024px, I don't want the animation to show, so I hid all of the images and whatnot.
However, the javascript that gets called to make the animation work is still getting called on smaller resolutions and causing some issues.
Is there a way to basically say "If the resolution is less than 1024px, ignore these JS files"?
I tried putting them in a DIV and using my existing CSS media queries to "display: none" the DIV on smaller resolutions, but that doesn't work.
FYI, these are the files being called:
<script type="text/javascript" src="/js/skrollr.min.js"></script>
<script type="text/javascript" src="/js/homepageanimation.js"></script>
On top of the jQuery(function($) { in http://workwave.joomlatest01.mms-dev.com//js/homepageanimation.js put something like
jQuery(function($) {
if(screen.width < 1024) {
return;
}
// skrollr stuff....
}
so all the skrollr functions won't be called on screen sizes with a width below 1024px.
The easiest way is too use jQuery..
$(window).width();
plain Javascript:
var w = window.innerWidth;
var ow = window.outerWidth; //toolbars and status, etc...
if(w > 1024) {
//Skrollr
}
from there an small if to trigger the Skrollr event
I would suggest conditionally loading the script. Basically the script only gets loaded if the screen size is greater than 1024.
if(window.innerWidth >= 1024){
var file = document.createElement('script')
file.setAttribute("type","text/javascript")
file.setAttribute("src", "/js/skrollr.min.js")
}
A nice approach here would be to only call the function that initiates the Skrollr functionality at given screen sizes. A real quick Google suggests that Skrollr has a .init() function that gets things rolling.
Without seeing how the JS is set up it's hard to give any solid advice, but here's an idea:
You have a JS file for the page/site that contains a conditional that checks the width of the window before initializing the plugin after the document is ready.
$(document).ready(function() {
if ($(window).width() > 1023) {
skrollr.init();
}
});
jQuery makes this a lot easier too, so it's worth taking advantage of that.
Another option to consider instead of going via window width (which can sometimes be inconsistent with the CSS widths among different browsers) is to test against a CSS rule and whether it is true, so use one you know would be true at a size above 1024px, and this would eliminate any inconsistency.
Within this condition link the JQuery files as demonstrated in other answers.
When the screen is on a certain width, we wish to hide a button and, instead, allow the wrapper div to be clickable.
That should only happen, however, when:
#media only screen and (min-width:320px) {
While we can easily display:none; and display:block; the button, the issue arrives when we want to remove the surrounding wrapper div (on higher screen sizes), because, if we display: none; the surrounding div, all their inside content will be removed too!
Is there any javascript version of the media query above, that could be reliable cross browser, and cross OS, that one may have, in order to dynamically add and remove the element on certain screen conditions?
Yeah check this:
https://developer.mozilla.org/en-US/docs/Web/API/Window.matchMedia
Syntax
mql = window.matchMedia(mediaQueryString)
Where mediaQueryString is a string representing the media query for which to return a new MediaQueryList object.
Example
if (window.matchMedia("(min-width: 400px)").matches) {
/* the view port is at least 400 pixels wide */
} else {
/* the view port is less than 400 pixels wide */
}
And a polyfill like this:
https://github.com/paulirish/matchMedia.js/
Old IE:
https://github.com/benschwarz/matchMedia.js/tree/IE7-8
If you just care about a simple check here's how you could do it with jQuery, though it is pretty trivial to do it in plain Javascript too this is just easier because of your old IE requirements:
var timeout;
function onWindowResize() {
var width = $(window).width();
if (width <= 480) {
console.log('small');
} else if (width <= 767) {
console.log('medium');
} else if (width <= 1024) {
console.log('large');
} else {
console.log('xlarge');
}
}
$(window).resize(function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
onWindowResize();
}, 50); // Only resize every 50ms - number up to you.
});
Don't use JS to change the display property on the element directly. Modify the class names that are associated with the element instead.
You can then define display: none or otherwise using a class selector and media queries in your external stylesheet.
I have a span that needs its font-size value changed when the window is resized. I do that with the jquery code:
$(window).on('resize', function () {
y = $(window).height();
x = $(window).width();
if (y > 500) {
$('#testing').css("fontSize", "50px");
} else if (y < 500) {
$('#testing').css("fontSize", "10px");
}
});
and may also do an equivalent with the css code:
#media screen and (max-height: 500px)
{
#testing{
font-size: 10px;
}
}
which is actually more efficent? Is one solution more acceptable/common? Is there a better way to do this? And also which way is more acceptable on a mobile device? Is there a better way to do this on a mobile device?
Which is actually more efficent? Is one solution more acceptable/common?
Performance wise, CSS is way better. Using media queries will be faster than processing a function on every resize (which are called numerous times). Of course, you could insert a throttle and call it once when the window didnt resize in a said lapse of time, but even there, media queries will be faster.
Furthermore, Javascript window width may not alway be the same than the CSS media queries. Scrollbar can change value and other things may also affect the width. You have to use a function to check the real width, which consume even more juice. It look like that :
function viewport() {
//Get the current view port
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
The down side of mediaqueries is the support, it is not supported in old IE. But there is of course some libraries that solve this issue.
Is there a better way to do this?
Not really, media queries are fast and efficient.
And also which way is more acceptable on a mobile device? Is there a better way to do this on a mobile device?
Most mobile browser support media queries. You should always use media queries on mobile, it is the prime reason why they exist.
Self shaming promotion and why Javascript media queries could be usefull
There is a case where javascript could be used as media queries. It would be usefull if you want to change the font-size dynamically depend and a screen size with a ratio. Doing that with media queries would be long and painfull since you'd have to do 20~30 media queries depending on the smoothness.
I've created a plugin changing font size depending on the screen for that reason.
https://github.com/kagagnon/Responsive-Font
If you're not worry about cross browser compatibility problem since media queries is CSS3 which is not supported for old browsers such as IE7, IE8... then I'd suggest you to use CSS over javascript.
In the other hand, beside better in handling cross browser compatibility issues, if a task cannot be achieved through CSS then you should probably go with javascript instead.
In short, I'm always prefer CSS than Javascript :)
Depends, using a responsive design will allow you to do much more than just change the font size.
vw units is a good option if you can. See this article
As my opinion ,You have to prefer JQuery,because the reason is : It is a library that fully support most of devices and auto configure them self as per the environment need ! You have to not think about what the browser need only put a line of code jquery do it in its own way. And place apply your style with respect to device or browser !
I am working on some mobile web application (it my firs time) and I faced such problem: despite the use of special mobile frameworks some sizes of modal windows are not correct on small screens. For example i have an ipod and ipad:
On iPod the size of buttons is already changed for a bit. So, may be there is any way to identify screen size like category (small, normal, large or may be just get list of sizes to the array) using js may be and then based on it i would do some basic changes in the source.
use jquery to find current width of window
$(function() {
showWidth($(this).width());
$(window).resize(function() {
showWidth($(this).width());
});
});
function showWidth(wid) {
var width = parseInt(wid);
if (width < 1440) {
//use wider stylesheet
} else if ((width >= 901) && (width < 1440)) {
//use wide stylesheet
} else {
//use small stylesheet
}
}
You can get screen height width using jquery like
alert("Width :"+$(window).width()+" Height :"+$(window).height());
You does not get size specification like small,big etc.
You have write responsive code yourself using screen width and height.
I would strongly suggest to use css media-queries instead of identifying the width in js and serving stylesheets based on that.
CSS Media Queries are standradrized: http://www.w3.org/TR/css3-mediaqueries/
Also see examples and usage here: http://css-tricks.com/css-media-queries/
I'm trying to do something that I think should be pretty straightforward but I have not found a straightforward explanation of the solution.
I am building a responsive website that is mobile first (320px width as the default). At that small resolution, the site is one column and I am happy to allow each individual "box" to expand or contract to the natural height of the contents contained inside.
However, at larger resolutions where the site expands to three columns, I want to add a small Javascript function to equalize the heights of the boxes of each column. The function I am talking about would be something like this:
jQuery(document).ready(function() {
setHeight('#inner-footer .widget-area');
});
var maxHeight = 0;
function setHeight(column) {
//Get all the element with class = col
column = $(column);
//Loop all the column
column.each(function() {
//Store the highest value
if($(this).height() > maxHeight) {
maxHeight = $(this).height();;
}
});
//Set the height
column.height(maxHeight);
}
I've found different ways to do what I'm talking about.
I can use the modernizr "load" function (formally yesnope.js).
Using a custom function that incorporates Nicholas Zakas "isMedia" function as described in this link Media Specific Javascript or
a custom javascript function using the the "screenWidth" variable as in
var screenWidth = (screen.width < 768) ? true : false;
as described in Media queries in the real world
With my limited javascript knowledge, I have been unable to actually write the code to get any of these approaches to work for my script. Can anyone help me out here?
I have no particular preference for approach I just want it to work cross browser, etc. My sense is that the modernizr approach is the most robust and stable way to make this work in the greatest number of use cases but I'm not totally sure of that. I've never modified modernizr so I'm unsure of how to write and where to put the custom load function.
Anyone have thoughts and specific code for the modernizr approach or any of the other solutions (or something else)? I greatly appreciate the assistance.
Modernizr can check that media queries apply with the Modernizr.mq() function
You pass it your media query that you want it to match like this
if(Modernizr.mq('all and (min-width: 768px)')) {
// Equal height code here
}
Here once the min width is past 768px then the code inside the function would be called, so for you the equal height code.
You can try to make use of matchMedia, this will allow you to load specific js based on media queries.
https://developer.mozilla.org/en/DOM/window.matchMedia
Paul Irish has been working on some polyfills
https://github.com/paulirish/matchMedia.js/
Hope this helps
Ian