Cross-browser responsive design without media queries

John Avis by | June 7, 2013 | Responsive Web Design Jquery/Javascript

...Or an alternative to media queries for responsive design I really like the concept of responsive design, and I have read a lot of the positive stuff about it, and also read a lot of the negative too.

...Or an alternative to media queries for responsive design


I really like the concept of responsive design, and I have read a lot of the positive stuff about it, and also read a lot of the negative too.

Despite the negatives, I do think that responsive design is the way of the future (and now), but it seems that it is far from easy to get right.

I'm taking my first steps in responsive design now, but one of the first issues I encountered is browser compatibility for CSS3 media queries. The Google Analytics statistics for most of the sites I maintain still show enough users with Internet Explorer 8 that I still need to consider these browsers during development.

I have looked at some of the well-known fixes but the idea of requesting my CSS files by AJAX and parsing them doesn't sound too efficient, even though it will only happen with IE8 and below.

An alternative is to use JavaScript or jQuery to handle the change of display size for all browsers, and I put something together quickly to do this. As the experimental work I have done so far has only involved using "max-width", my jQuery example presented here works only that way.

It works simply by applying classes to a specified tag (default is BODY tag). So if you have breakpoints set at 500 pixels and 300 pixels, it will apply no classes at 600 pixels, the 500 pixel class (which you specify) once the display width is less than or equal to 500 pixels, and both the 500 and 300 pixels classes when the display width is less than or equal to 300 pixels. It adjusts classes on document ready and when the browser is resized.

Here's the code and a sample (jQuery required):

<script type="text/javascript">
(function ($) {
jQuery.responsive = function (options) {
var settings = $.extend({
breakpoints: [],
container: "body"
}, options);
$(window).resize(function () {
respond();
});
respond();
function respond() {
for (var i = 0; i < settings.breakpoints.length; i++) {
if ($(window).width() <= settings.breakpoints[i][0]) {
$(settings.container).addClass(settings.breakpoints[i][1]);
}
else {
$(settings.container).removeClass(settings.breakpoints[i][1]);
}
}
};
}
})(jQuery);

//Sample usage - adds two breakpoints and applies class to BODY tag
$(function () {
$.responsive({
//array with max-width in pixels, and class to apply
breakpoints: [[980, "mw980"], [480, "mw480"]]
//optional specify container to apply classes to, default is body
//,container: "#wrapper"
});
});
</script>

I mocked up a couple of samples, one using media queries and my alternative using jQuery:

Example using media queries

Example using jQuery

They should appear and operate identically in all browsers, except IE8 and below where the media queries example will not work as designed.

Update: I have since redesigned my blog using this technique. I also added support for min-width. You can look at the source of this page to see updated code.

Update: I found that one of the disadvantages of using this technique is that the adding of classes does not happen until document ready. This means that there can be a delay in applying the classes which is visible to the user. To solve this problem I suggest adding a second script using native JavaScript to add the classes immediately after the BODY open tag (or whichever tag has the clases applied). Example (also applied to this website):

var container = "body"; //must be ID
var breakpoints = [
["max-width", 650, "max650"],
["min-width", 986, "min986"]
];
for (var i = 0; i < breakpoints.length; i++) {
if (breakpoints[i][0] == "max-width") {
if (window.innerWidth <= breakpoints[i][1]) {
document.getElementById(container).className = breakpoints[i][2];
}
}
else if (breakpoints[i][0] == "min-width") {
if (window.innerWidth >= breakpoints[i][1]) {
document.getElementById(container).className = breakpoints[i][2];
}
}
}


I've actually created some ASP.NET server controls to handle this in some of the projects I am working on. Let me know if you're interested in seeing that.

Update:

I have created a pure JavaScript version of the cross-browser responsive media query alternative code. This version should be placed immediately after the opening tag for the element that classes are to be applied. The id of that element and the breakpoints need to be adjusted to your requirements. Here's an example:

<script type="text/javascript">
function hasClass(el, cls) {
return el.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(el, cls) {
if (!this.hasClass(el, cls)) el.className += " " + cls;
}
function removeClass(el, cls) {
if (hasClass(el, cls)) {
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
el.className = el.className.replace(reg, ' ');
}
}

var addEvent = function (elem, type, eventHandle) {
if (elem == null || elem == undefined) return;
if (elem.addEventListener) {
elem.addEventListener(type, eventHandle, false);
} else if (elem.attachEvent) {
elem.attachEvent("on" + type, eventHandle);
} else {
elem["on" + type] = eventHandle;
}
};

function responsive() {
var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;

for (var i = 0; i < breakpoints.length; i++) {
if (breakpoints[i][0] == "max-width") {
if (w <= breakpoints[i][1]) {
addClass(document.getElementById(id), breakpoints[i][2]);
}
else {
removeClass(document.getElementById(id), breakpoints[i][2]);
}
}
else if (breakpoints[i][0] == "min-width") {
if (w >= breakpoints[i][1]) {
addClass(document.getElementById(id), breakpoints[i][2]);
}
else {
removeClass(document.getElementById(id), breakpoints[i][2]);
}
}
}
}

var resizeTimeoutId;

function resized() {
window.clearTimeout(resizeTimeoutId);
resizeTimeoutId = window.setTimeout('responsive();', 10);
}

var id = "body";
var breakpoints = [["max-width", 630, "max630"], ["min-width", 1890, "min1890"]];

addEvent(window, "resize", resized);

responsive();
</script>

Related Posts

Jquery/Javascript Responsive Web Design

Yet another enhancement of the simple Pinterest Style Grid Layout jQuery Plugin

by John Avis | November 16, 2017

I have made another change to the modified version of Mediademons Simple jQuery Plugin To Create Pinterest Style Grid Layout - Pinterest Grid.


Jquery/Javascript

Back to top button like Facebook app

by John Avis | September 15, 2017

The Facebook app on Windows phone has a nice and unobtrusive back to top button that only appears once you scroll past a certain point, and only when you start scrolling up the page. This code offers similar functionality using jQuery.


Jquery/Javascript Responsive Web Design

Enhanced simple Pinterest Style Grid Layout jQuery Plugin

by John Avis | April 13, 2017

In response to a request, I have made some improvements to the modified version of Mediademon's Simple jQuery Plugin To Create Pinterest Style Grid Layout - Pinterest Grid.

Comments

There are no comments yet. Be the first to leave a comment!

Leave a Comment
Tags
ASP.NET Html Forms ASP.NET MVC ASP.NET Web Forms ASP.NET Web Pages Bootstrap C# Classic ASP Cool Websites Databases eBay and PayPal Electrical Repairs General Hardware HTML/CSS Jquery/Javascript Media Center Mobile Phones Responsive Web Design SEO and Social Networking Web Design Web Development Web Security web+db Website Hosting Windows XP

About me

...mostly about web development and programming, with a little bit of anything else related to the Internet, computers and technology.

Subscribe

Get the latest posts delivered to your inbox.