8

clip-path:shape() does not seem to work in IE (no surprise) and Firefox (a bit surprised). Is there a way to test for clip-path support? I use modernizr. (By the way, I know I can get this to work using SVGs and -webkit-clip-path:url(#mySVG))

  • hahahah.... IE and Firefox are not webkit... webkit is supported only on - wait for it - webkit browsers. That is, Chrome (pre-Blink) and Safari. Other than that, I have no useful answer. *shrugs* – Phil Tune Dec 19 '14 at 17:14
  • Yes funny. I should have said "clip-path" and not webkit. Yet, I can't seem to see a way to browser test for clip-path support. –  Dec 19 '14 at 17:29
  • Googled... found http://modernizr.com/docs/#features-misc... does that help? – Phil Tune Dec 19 '14 at 17:33
  • Yeah I saw that too. That tests for SVG Clip path support, which returns true for Firefox (which is correct). However firefox does not support clip-path:circle() only clip-path:url(#mySVG). Anyway, I think my question is pointless now. I need just to test for Firefox and IE because those are the two browsers that don't support it. –  Dec 19 '14 at 18:37
  • 1
    Yeah, sucks to have to do that (lot of test-for-capabilities-not-useragent nazis out there), but you gotta do what you gotta do. – Phil Tune Dec 19 '14 at 19:09
  • Plus one for the parenthesis. –  Dec 19 '14 at 19:30

2 Answers2

17

You asked this a while ago, and to be honest, I'm not sure if Modernizr has yet to add support for this, but it's pretty easy to roll your own test in this case.

The steps are:

  1. Create, but do not append, a DOM element.
  2. Check that it supports any kind of clipPath by checking the JS style attribute of the newly created element (element.style.clipPath === '' if it can support it).
  3. Check that it supports CSS clip path shapes by making element.style.clipPath equal some valid CSS clip path shape.

Of course, it's a little more complex than that, as you have to check for vendor-specific prefixes.

Here it is all together:

var areClipPathShapesSupported = function () {

    var base = 'clipPath',
        prefixes = [ 'webkit', 'moz', 'ms', 'o' ],
        properties = [ base ],
        testElement = document.createElement( 'testelement' ),
        attribute = 'polygon(50% 0%, 0% 100%, 100% 100%)';

    // Push the prefixed properties into the array of properties.
    for ( var i = 0, l = prefixes.length; i < l; i++ ) {
        var prefixedProperty = prefixes[i] + base.charAt( 0 ).toUpperCase() + base.slice( 1 ); // remember to capitalize!
        properties.push( prefixedProperty );
    }

    // Interate over the properties and see if they pass two tests.
    for ( var i = 0, l = properties.length; i < l; i++ ) {
        var property = properties[i];

        // First, they need to even support clip-path (IE <= 11 does not)...
        if ( testElement.style[property] === '' ) {

            // Second, we need to see what happens when we try to create a CSS shape...
            testElement.style[property] = attribute;
            if ( testElement.style[property] !== '' ) {
                return true;
            }
        }
    }

    return false;
};

Here's a codepen proof-of-concept: http://codepen.io/anon/pen/YXyyMJ

worldofjr
  • 3,868
  • 8
  • 37
  • 49
jwest
  • 342
  • 3
  • 10
  • This should be added to modernizr. I tested in IE and it detected correctly that svg clip path was not supported (on HTML elements). Thanks! – Markus Sep 24 '15 at 20:35
  • 1
    Unfortunately this shows that clip-paths are supported in Edge 18 while they aren't in fact supported. – jhadenfeldt Aug 16 '19 at 21:42
  • 1
    If you change the last test from `testElement.style[property] !== ''` to `testElement.style[property].indexOf('polygon') !== -1` it works. Edge sets the property value to `'none'` instead of the empty string. I like it as smaller alternative, if you don't want to include Modernizr for a simple case. – alex3683 Dec 17 '19 at 08:28
4

You can test with Modernizr.

(function (Modernizr) {

    // Here are all the values we will test. If you want to use just one or two, comment out the lines of test you don't need.
    var tests = [{
            name: 'svg',
            value: 'url(#test)'
        }, // False positive in IE, supports SVG clip-path, but not on HTML element
        {
            name: 'inset',
            value: 'inset(10px 20px 30px 40px)'
        }, {
            name: 'circle',
            value: 'circle(60px at center)'
        }, {
            name: 'ellipse',
            value: 'ellipse(50% 50% at 50% 50%)'
        }, {
            name: 'polygon',
            value: 'polygon(50% 0%, 0% 100%, 100% 100%)'
        }
    ];

    var t = 0, name, value, prop;

    for (; t < tests.length; t++) {
        name = tests[t].name;
        value = tests[t].value;
        Modernizr.addTest('cssclippath' + name, function () {

            // Try using window.CSS.supports
            if ('CSS' in window && 'supports' in window.CSS) {
                for (var i = 0; i < Modernizr._prefixes.length; i++) {
                    prop = Modernizr._prefixes[i] + 'clip-path'

                    if (window.CSS.supports(prop, value)) {
                        return true;
                    }
                }
                return false;
            }

            // Otherwise, use Modernizr.testStyles and examine the property manually
            return Modernizr.testStyles('#modernizr { ' + Modernizr._prefixes.join('clip-path:' + value + '; ') + ' }', function (elem, rule) {
                var style = getComputedStyle(elem),
                    clip = style.clipPath;

                if (!clip || clip == "none") {
                    clip = false;

                    for (var i = 0; i < Modernizr._domPrefixes.length; i++) {
                        test = Modernizr._domPrefixes[i] + 'ClipPath';
                        if (style[test] && style[test] !== "none") {
                            clip = true;
                            break;
                        }
                    }
                }

                return Modernizr.testProp('clipPath') && clip;
            });
        });
    }

})(Modernizr);

Check this codepen to see it in action.