我如何在使用javascript的伪元素之前检测CSS Transition支持?

时间:2012-10-16 20:07:16

标签: javascript css-transitions pseudo-element browser-feature-detection

我正在尝试将CSS Transitions:before选择器一起使用,目前唯一支持此功能的浏览器是Firefox。我可以创建一个没有问题的jQuery fallback,但我不确定如何使用像这样的伪元素进行特征检测。

Here's a JSBin which shows the HTML and CSS that I'm working with.

... and here's a similar SO question, but about using regular elements.

更新:哇,甚至IE10的平台预览也支持这个,那个webkit有什么用?!

IE 10 Platform preview has CSS Transition support on :before

编辑:解决方案已移至以下答案)

3 个答案:

答案 0 :(得分:1)

我知道建议说你应该使用后备而不是polyfill,但只是你和我之间,使用无条件polyfill并不是那么可怕的CSS3等前沿的东西。

如果您必须知道功能状态,可以使用Modernizr,但如果您正在使用库,那么您也可以使用Selectivizr并通过浏览器获得完整的CSS支持

啊哈! Here是来自Modernizr人们在github上的一个非常好的小提琴。基本上,它检查伪元素的计算样式值是否在短于转换持续时间的时间内从其原始值更改。当然,问题在于使用setTimeouts(同步问题)的不可靠性以及在setTimeout测试完成之前需要推迟所有内容的事实。检查控制台以查看浏览器是否具有伪元素转换。

答案 1 :(得分:0)

公平地说,即将推出的IE10确实支持生成内容的转换(在Windows 8 Enterprise试用版中自行测试)。

实际上,我确信没有必要检测这类事情。转换只是轻微的改进,而不是关键功能。因此,将转换工作在更高级的浏览器中,而不是在不太先进的浏览器中使用它是完全可以的。

但是如果您需要检测它,考虑到无法直接可靠地检测到它,您可以通过测试标准全局JS对象的存在来使用浏览器引擎检测。例如,由于我们知道IE10支持转换生成的内容,因此我们可以确保具有document.all && !window.atob条件的未来filter IE9 and older IEs。可以通过测试window.opera的存在来检测Opera,因此当Opera解决此问题时,我们可以使用window.opera && !someGlobalObjectAddedInFixedOpera条件来检测旧版本。 WebKit可能会以类似的方式被检测到。

答案 2 :(得分:0)

感谢@Asad挖掘了一些handy code,我能够提出nice solution这里的jQuery版本:

$(function() {
  var isTransitionSupported = (function (pseudo, transProp, transPropStart, transPropEnd) {
    var id = pseudo + transProp + '-' + (new Date()).valueOf(),
        prefixes = ['o', 'ms', 'moz', 'webkit'],
        prop = "transition: " + transProp + " 99s linear;",
        allprops = (function () {
          var props = "";
          for (var l = prefixes.length; l--;) {
            props += "-" + prefixes[l] + "-" + prop;
          }
          return props + prop;
        }()),
        $css = $("<style>" +
                 "#" + id + "{position:absolute;left:-999em;}" + 
                 "#" + id + ":" + pseudo + "{display:block;content:'M';" + transProp + ":" + transPropStart + ";}" + 
                 "#" + id + ".t:" + pseudo + "{" + allprops + transProp + ":" + transPropEnd + ";}" + 
                 "</style>"),
        $bct = $('<div id="' + id + '" />');

      $css.appendTo("head");
      $bct.appendTo("body");

      try {
        // get style value before any changes
        window.getComputedStyle($bct[0], ':' + pseudo).getPropertyValue(transProp);

        $bct.addClass("t");

        // test style after changes
        return (window.getComputedStyle($bct[0], ':' + pseudo).getPropertyValue(transProp) !== transPropEnd);
      } catch (e) {}
      return false;
    }("before", "width", "0px", "1000px"));
});

Here's a version that doesn't use jQuery

var isTransitionSupported = (function (pseudo, transProp, transPropStart, transPropEnd) {
    var ticks = (new Date()).valueOf(),
        id = pseudo + transProp + '-' + ticks,
        prefixes = ['o', 'ms', 'moz', 'webkit'],
        prop = "transition: " + transProp + " 99s linear;",
        allprops = (function () {
            var props = "";
            for (var l = prefixes.length; l--;) {
                props += "-" + prefixes[l] + "-" + prop;
            }
            return props + prop;
        }()),
        body = document.body || document.createElement('body'),
        node = document.createElement('div'),
        css = "<style>" +
                    "#" + id + "{position:absolute;left:-999em;}" + 
                    "#" + id + ":" + pseudo + "{display:block;content:'M';" + transProp + ":" + transPropStart + ";}" + 
                    "#" + id + ".t" + ticks + ":" + pseudo + "{" + allprops + transProp + ":" + transPropEnd + ";}" + 
                    "</style>",
        bct = document.createElement('div'),
        isSupported = false;

    bct.id = id;
    node.innerHTML += css;
    node.appendChild(bct);
    body.appendChild(node);

    try {
        // get style value before any changes
        window.getComputedStyle(bct, ':' + pseudo).getPropertyValue(transProp);

        bct.className += "t" + ticks;

        // test style after changes
        isSupported = (window.getComputedStyle(bct, ':' + pseudo).getPropertyValue(transProp) !== transPropEnd);
    } catch (e) {}

    node.parentNode.removeChild(node);

    return isSupported;
}("before", "width", "0px", "1000px"));

document.documentElement.className += ' ' + (isTransitionSupported ? '' : 'no-') + "pseudo-trans";

这是all that code in a gist on github,如果有人想分叉并改进它。