Last active
May 12, 2016 09:14
-
-
Save branneman/5e4c23c8a9584f85410c to your computer and use it in GitHub Desktop.
Feature detect Flexbox support with JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define(function() { | |
var cssomPrefixes = 'Moz O ms Webkit'.split(' '); | |
var modElem = { | |
elem: document.createElement('modernizr') | |
}; | |
var mStyle = { | |
style: modElem.elem.style | |
}; | |
function cssToDOM(name) { | |
return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) { | |
return m1 + m2.toUpperCase(); | |
}).replace(/^-/, ''); | |
} | |
function domToCSS(name) { | |
return name.replace(/([A-Z])/g, function(str, m1) { | |
return '-' + m1.toLowerCase(); | |
}).replace(/^ms-/, '-ms-'); | |
} | |
function nativeTestProps(props, value) { | |
var i = props.length; | |
if ('CSS' in window && 'supports' in window.CSS) { | |
while (i--) { | |
if (window.CSS.supports(domToCSS(props[i]), value)) { | |
return true; | |
} | |
} | |
return false; | |
} else if ('CSSSupportsRule' in window) { | |
var conditionText = []; | |
while (i--) { | |
conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')'); | |
} | |
conditionText = conditionText.join(' or '); | |
var query = '@supports (' + conditionText + ') { #modernizr { position: absolute; } }'; | |
return injectElementWithStyles(query, function(node) { | |
return getComputedStyle(node, null).position == 'absolute'; | |
}); | |
} | |
return undefined; | |
} | |
function testProps(props, prefixed, value, skipValueTest) { | |
skipValueTest = typeof skipValueTest === 'undefined' ? false : skipValueTest; | |
if (typeof value !== 'undefined') { | |
var result = nativeTestProps(props, value); | |
if (typeof result !== 'undefined') { | |
return result; | |
} | |
} | |
var afterInit, i, propsLength, prop, before; | |
var elems = ['modernizr', 'tspan']; | |
while (!mStyle.style) { | |
afterInit = true; | |
mStyle.modElem = document.createElement(elems.shift()); | |
mStyle.style = mStyle.modElem.style; | |
} | |
function cleanElems() { | |
if (afterInit) { | |
delete mStyle.style; | |
delete mStyle.modElem; | |
} | |
} | |
propsLength = props.length; | |
for (i = 0; i < propsLength; i++) { | |
prop = props[i]; | |
before = mStyle.style[prop]; | |
if (!!~('' + prop).indexOf('-')) { | |
prop = cssToDOM(prop); | |
} | |
if (mStyle.style[prop] !== undefined) { | |
if (!skipValueTest && typeof value !== 'undefined') { | |
try { | |
mStyle.style[prop] = value; | |
} catch (e) {} | |
if (mStyle.style[prop] != before) { | |
cleanElems(); | |
return prefixed == 'pfx' ? prop : true; | |
} | |
} else { | |
cleanElems(); | |
return prefixed == 'pfx' ? prop : true; | |
} | |
} | |
} | |
cleanElems(); | |
return false; | |
} | |
function testAllProps(prop, prefixed, value, skipValueTest) { | |
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1); | |
var props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); | |
return testProps(props, prefixed, value, skipValueTest); | |
} | |
return { | |
flexbox: testAllProps('flexBasis', '1px'), | |
legacy: testAllProps('boxDirection', 'reverse'), | |
tweener: testAllProps('flexAlign', 'end'), | |
wrap: testAllProps('flexWrap', 'wrap') | |
}; | |
}); |
This code is broken:
injectElementWithStyles
is missing.testAllProps
takesprefixed
as the second argument, but a value is passed there instead ('1px'
,'reverse'
,'end'
,'wrap'
).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey Bran, this looks interesting, mainly because it tests all flexbox variants. I usually only test the new syntax with a very simple test like this but that obviously misses out the 'legacy' and 'tweener' versions.
However: Legacy and Tweener are probably going extinct soonish so I wonder if this is a bit much?
Also: can you tell me how these tests are different from Modernizr tests?