1
\$\begingroup\$

I'm applying fallbacks to rem values only if required (you know, the whole progressive enhancement train), without conditional comments (because it's not just an IE issue) and without additional lines of CSS for fallbacks all over the place. I'm just checking for the edge cases (userAgent) and adding a stylesheet into the head only when these come into play. This stylesheet has overrides to apply px values where needed.

I'm aware modernizr.js does a great job of detection and I would only need to use .no-cssremunit (I've used it before) but I'm not using modernizr anywhere else and think it unnecessary to load a new library for only this, if I'm wrong, please correct me.

rem support issues in question

  • Samsung Note 2 (Android 4.3) doesn't support rem
  • lte IE8 doesn't support rem values
  • Opera Mini doesn't support rem values

Source, the other "issues" with rem's do not apply here.

I wrote this and it seems to be working well in IE <9 and Opera Mini (I'm unable to really test with a Note 2 with Android 4.3 at this time, will soon). BUT not being a JavaScript/jQuery developer I wanted to have another set of eyes on this to see if it is a good approach. Am I missing anything that could throw a wrench into it?

/* detect opera mini */
var isOperaMini = (navigator.userAgent.indexOf("Opera Mini") > -1);

/* userAgent detect (Samsung Note 2 -- Android 4.3) */
var isNoteTwo = (navigator.userAgent.match("Mozilla/5.0 (Linux; U; Android 4.3; de-de; SAMSUNG GT-N7105/N7105XXUENA1 Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"));

/*  <ie8 -- addEventListener not supported by IE8 or later */
var isltIE9 = (!document.addEventListener);

/* if either variable matches, import stylesheet */
if (isOperaMini || isNoteTwo || isltIE9) {
    var css = document.createElement("link");
    css.rel = "stylesheet";
    css.href = "css/rem-fallback.css";
}
\$\endgroup\$
  • \$\begingroup\$ Not really a direct answer to your question, but if you use a CSS preprocessor like SASS or LESS, you can do this pretty efficiently using mixins. \$\endgroup\$ – Alexis King Jan 6 '15 at 19:35
  • \$\begingroup\$ I've started working in SASS but I'm not comfortable enough with it to use it on live projects just yet, my output code is a little too cumbersome. But I'll definintely look into it more as time permits. Thanks. \$\endgroup\$ – darcher Jan 6 '15 at 19:42
2
\$\begingroup\$

I have tested the following code in IE8 and Safari and it works, although I cannot test on the Galaxy Note or Opera Mini. The following javascript allows you to test rem support. Since IE9 or lower throws an error when you try to set as rem, I used a try{}catch(){} - newer browsers should remove the value as soon as its set when they don't support setting the value as such. I don't know if this solves all your problems (if the Galaxy allows you to set rem but doesn't apply it, then this won't work). I have used pure javascript, so you don't need support for anything else (like jQuery).

function supports(attribute, test){

    var supports = false;

    try {
        var div     = document.createElement("div");

        div.style[attribute] = test;

        if(div.style[attribute] === test){
            supports = true;
        }
    } catch(e){}

    return supports;
}

You could then test for rem support as such:

if(supports("fontSize", "1rem")){
    /* Rem supported, don't add your stylesheet */
} else {
    /* No rem support, add another stylesheet to make up for it */
}

This is a purer and simpler, and more reusable, version of your code. Sniffing user agents is generally a bad idea as they inevitably lead to confusion, and a user agent string in the future might match what you are testing for and therefore have an unexpected outcome. It is also best practise to allow for more universal solutions. You could, for example, use this same function to see if you can set background-imageto 1rem and it would return false.

Update

I have just done some testing with browser stack (which, granted, is an emulator) and the Galaxy Note 2 does support rem. And not because my function says it, I made a page with this code:

<!DOCTYPE html>
<html style="font-size: 12px;">
<head></head>
<body>
    <div style="font-size: 5em;">5EM
        <div style="font-size: 2em; font-size: 2rem;">2(*5)EM/2REM</div>
    </div>
</body>
</html>

and the nested 2(*5)EM/2REMis smaller than the 5EM, which indicates its getting the base value from the html tag and not from the parent, indicating rem support.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Yup, This is a much better method. This is much the way modernizr actually approaches it as well. Thanks! BUT, I'm unsure you would be able to test for the Note 2 via emulation, unless you were running an android install emulating the actual OS and device. It's such an edge case I'm guessing it has something to do with the device setup itself. -- raw.githubusercontent.com/Modernizr/Modernizr/master/… \$\endgroup\$ – darcher Jan 10 '15 at 20:01
  • \$\begingroup\$ @darcher Yeah I'm unsure about the testing myself, its on browserstack (literally the Note 2) but it is an emulator on a mac environment, so it;s probably not very accurate. Would be strange if the Note II wouldn't support rem units, though. \$\endgroup\$ – somethinghere Jan 12 '15 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.