Forums

The forums ran from 2008-2020 and are now closed and viewable here as an archive.

Home Forums JavaScript Getting Media Queries working on old IE

  • This topic is empty.
Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #34702
    rjc
    Member

    Hello Everyone,

    Firstly thanks for a great site! lots of helpful advice…

    Now my problem: I am trying to get my media stylesheets to run in old versions of IE. It’s almost working except for the first page is not displaying correctly

    Roughly each page has a set of separate includes for each screen type:






    And then for IE 8 and below there was a small javascript routine:


    function ieMediaQuery() {
    //load stylesheets
    var width = document.documentElement.offsetWidth;
    var href = document.getElementById("include-directory").href;
    //XXX should somehow parse media attr directly in link..
    if (width < 481) {
    href += "layout-mobile.css";
    } else if (width < 801) {
    href += "layout-narrow.css";
    } else if (width < 1301) {
    href += "layout-medium.css";
    } else {
    href += "layout-wide.css";
    }
    for (var i = 0; i < document.styleSheets.length; i++) {
    var s = document.styleSheets;
    if (s.href != null && href.indexOf(s.href, href.length - s.href.length) !== -1) {
    if (s.media != "screen") {
    s.media = "screen";
    }
    if (s.disabled == true) {
    s.disabled = false;
    }
    } else if (s.title == "layout width" && s.disabled == false) {
    s.disabled = true;
    }
    }
    }

    document.write("");
    var script = document.getElementById("__ie_onload");
    script.onreadystatechange = function() {
    if (/^(complete|loaded)$/.test(script.readyState)) {
    ieMediaQuery();
    script.onreadystatechange = null;
    if (/^complete$/.test(script.readyState)) {
    //try to force relayout by trying to retrieve offset from known element
    var menu = document.getElementById("menu");
    //XXX commented as causes error
    //var tmp = menu.offsetTop;
    }
    }
    window.attachEvent("onresize", ieMediaQuery);
    };

    Above works – except for first time when IE never sends readystate ‘loaded’ only get ‘complete’ which seems too late to change the active stylesheets.

    In that case tried forcing it to relayout by requesting the offset of a div…but that didn’t work, just generated an error in IE for some reason.

    Any Ideas?

    Thanks in advance for any assistance.

    #88776
    jamygolden
    Member

    You should check out respond.js.

    #88786
    rjc
    Member

    Thank you for the link to respond.js, it does much more than my script fragment(supports inline @media in stylesheets).

    Looking at the source for respond, maybe i am misunderstanding but the script looks like it will re-download each of the stylesheets in that page to bypass the IE parser(which throws away any @media statements).

    I am thinking this re-downloading of each stylesheet on slow links will cause flash as page is laid out again with the @media style info included.

    The script have above just switches a stylesheet to enabled when page is loaded, implicitly assuming IE can parse it. Obviously in such a scenario inline @media won’t work but it should also be faster hopefully avoiding flashing.

    #88788
    Mottie
    Member

    Maybe you could just include all stylesheets on the page and just disable the ones you aren’t using initially (I know it’s not ideal):

    add all of the CSS stylesheets into the head of your page (include a title attribute in each one):






    Then use this script. You may get a flash of white if you don’t have a base CSS style (one link that isn’t disabled).

    $(document).ready(function(){
    adjustCSS();
    $(window).resize(function(){ adjustCSS() });
    })
    function adjustCSS(){
    var pageWidth = $(window).width();
    var sizeSelected = "blue1";
    if (pageWidth > 510) { sizeSelected = "blue2"; }
    if (pageWidth > 580) { sizeSelected = "blue3"; }
    if (pageWidth > 900) { sizeSelected = "blue4"; }
    if (pageWidth > 1010) { sizeSelected = "blue5"; }
    if (pageWidth > 1420) { sizeSelected = "blue6"; }
    var lnk = $('head').find('link[title=' + sizeSelected + ']').removeAttr('disabled');
    $('head').find('link[title]').not(lnk).attr('disabled', 'disabled');
    }
    #88855
    rjc
    Member

    Thanks Mottie! Using jquery really cleans up the code compared to plain javascript, it’s much easier to read and understand.

    Maybe a problem with the above is that it browsers that natively understand media queries are marginally slower as they now have to wait for jquery script to download and execute before styles are activated for the site. As you say i guess the key to using this is to have a base style that is close to the width dependent ones so the change is not too abrupt.

    Anyway I borrowed the regular expression to parse the min and max values from the respond.js script and reworked the script i posted from yesterday. Using the same stylesheet links before with this code now seems to work(am thinking perhaps is some kind of race condition say a page loading and onresize script running concurrently or something):


    /*
    * Workaround lack of media queries on older versions of IE
    */

    var maxwidth_re = /(max-width:[s]*([s]*[0-9]+)px[s]*)/;
    var minwidth_re = /(min-width:[s]*([s]*[0-9]+)px[s]*)/;

    var saved_stylesheet_media = [];
    var resize_timeout_id = null;

    function ieMediaQuery() {
    //enable layout stylesheet dependent on width
    var width = document.documentElement.offsetWidth;

    for (var i = 0; i < document.styleSheets.length; i++) {
    var s = document.styleSheets;
    if (s.title == "layout width") {
    if (saved_stylesheet_media
    == undefined) {
    saved_stylesheet_media
    = s.media;
    }
    var ssminwidth = (minwidth_re.test(saved_stylesheet_media
    )) ? RegExp.$1 : 0;
    var ssmaxwidth = (maxwidth_re.test(saved_stylesheet_media
    )) ? RegExp.$1 : Number.MAX_VALUE;
    s.disabled = (width < ssminwidth || width > ssmaxwidth);
    if (s.disabled == false) {
    s.media = "screen";
    }
    }
    }
    }

    document.write("");
    var script = document.getElementById("__ie_onload");
    script.onreadystatechange = function() {
    if (/^(complete|loaded)$/.test(script.readyState)) {
    script.onreadystatechange = null;
    ieMediaQuery();
    window.attachEvent("onresize", function() {
    window.clearTimeout(resize_timeout_id);
    resize_timeout_id = window.setTimeout('ieMediaQuery();', 10);
    });
    }
    };

    [Edit: Fixed bug in above code, which would lose the original media values]

    Edit 2:
    Just for people looking at this future, above script works for me now, to use
    1) Copy above into a script file say iemediaquery.js
    2) Create an empty file empty.js as a dummy target(other solutions would not work for me with ssl, got mixed content warnings)
    3) Setup your stylesheets as in first post with ‘title’ and ‘media’ attributes and then add conditional to load for IE 6-8 afterwards:



    4) Media queries should work for old IE!

Viewing 5 posts - 1 through 5 (of 5 total)
  • The forum ‘JavaScript’ is closed to new topics and replies.