Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Feature detect Flexbox support with JavaScript
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')
};
});
@davidhund

This comment has been minimized.

Copy link

davidhund commented Jan 6, 2016

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?

@sompylasar

This comment has been minimized.

Copy link

sompylasar commented Apr 17, 2016

This code is broken:

  1. injectElementWithStyles is missing.
  2. testAllProps takes prefixed 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
You can’t perform that action at this time.