What is a proper way to detect the support of css flex-box and flex-wrap?
how we can detect the support of css flex-box and flex-wrap by
JavaScript.
Create an element and check the style property. If it is supported, it will return nothing i.e. ''
else it will return undefined
.
For example, if you run the below snippet in Chrome you will get undefined
for columns
and ''
for flex-wrap
.
Snippet:
console.log('flex = ' + document.createElement("p").style.flex);console.log('columns = ' + document.createElement("p").style.columns);console.log('flex-wrap = ' + document.createElement("p").style.flexWrap);
@supports (-webkit-flex-wrap: wrap) doesn't return true when Safari does support it
Sorry to disappoint, but Safari does not presently support the CSS @supports
rule. According to caniuse.com and MDN, it is only supported in Firefox 22+, Chrome 28+, and Opera 12.1+. You still have to use JavaScript-based feature detection for Internet Explorer and Safari.
Here is an example feature-detection script that adds a supports-webkit-flex-wrap
to the root element in the DOM.
if ('webkitFlexWrap' in document.documentElement.style) {
document.documentElement.classList.add('supports-webkit-flex-wrap');
}
Then you can apply styles using that class name.
.supports-webkit-flex-wrap {
}
How to detect if CSS code is activated or not
As far as I remember css flex
or order
property is animatable, so you can trigger a class on an element with visibility hidden to turn on flex
property. Then attach an eventListener for the transitionend
event, and check if the property is from flex by checking event.propertyName
, if this event is fired, it means it is supported. Here is a fiddle to illustrate, a class called active is turned on a div with #mock
id and listened for transition:
https://jsfiddle.net/ibowankenobi/yLv39dsm/1/
document.getElementById("mock")
.addEventListener("transitionend",function(e){if(e.propertyName.match(/flex/gi)){alert("flex is supported")}});
setTimeout(function(){document.getElementById("mock").classList.add("active");},1000);
Apart from above, this question can help:
Detecting flex-wrap support in browsers
Also there seems to be an approach that seems to work:
https://gist.github.com/davidhund/b995353fdf9ce387b8a2
And of course, Modernizr probably has this already.
detecting flex wrap/content overflow in react
For anyone wondering I was able to isolate the code to be reused in any given container:
import useResizeObserver from '@react-hook/resize-observer'
//we need ResizerObserver
const useSize = (target) => {
const [size, setSize] = React.useState()
React.useLayoutEffect(() => {
setSize(target.current && target.current.getBoundingClientRect())
}, [target])
// Where the magic happens
useResizeObserver(target, (entry) => setSize((entry as any).contentRect))
return size
}
//this part goes in the component
//we need one ref to the container and some states to track the size of the individual items
const menuRef = React.useRef(null)
const menuRefSizes = useSize(menuRef)
const [navLinkIsHidden, setNavLinkIsHidden] = React.useState(false)
const [neededContainerWidth, setNeededContainerWidth] = React.useState(null)
const [navMenuIsHidden, setNavMenuIsHidden] = React.useState(false)
const [neededNavMenuContainerWidth, setNeededNavMenuContainerWidth] = React.useState(null)
React.useLayoutEffect(()=>{
CheckResponsive(
setNeededContainerWidth,setNavLinkIsHidden,neededContainerWidth, 'nav-links')
CheckResponsive(
setNeededNavMenuContainerWidth,setNavMenuIsHidden,neededNavMenuContainerWidth,'nav-menu-buttons')
return () => {
// no cleanup
};
}, [menuRefSizes])
//and the function we use applies to all items we are tracking.
//I am using direct dom references here, I am sure this can be simplified further but this is the more general I could done.
const CheckResponsive = (setContainer, setHide, neededContainerWidth, contId) => {
const navLinkNode = window.document.getElementById(contId)
const menuContainer = window.document.getElementById('menu')
const scrollWidth = navLinkNode ? navLinkNode.scrollWidth : 0
const offsetWidth = navLinkNode ? navLinkNode.offsetWidth : 0
const NavLinkIsOverflown = navLinkNode ? scrollWidth !== offsetWidth : false
const DoesNavLinkFitInContainer = menuContainer.scrollWidth >= neededContainerWidth
const navLinkWillBeHidden = NavLinkIsOverflown || !DoesNavLinkFitInContainer
navLinkWillBeHidden?setHide(true):setHide(false)
if (navLinkNode && navLinkWillBeHidden) {
setContainer(menuContainer.scrollWidth
+ window.document.getElementById(contId).scrollWidth
- window.document.getElementById(contId).offsetWidth)
}
return () => {
// no cleanup
};
}
the result is that all items that I am tracking wont be rendered when they overflow, when the container then have enough space again the items will be rendered.
Related Topics
How to Get File Name When User Select a File via <Input Type="File" />
Jquery Parallax Scrolling Effect - Multi Directional
Why Does Reflow Need to Be Triggered for CSS Transitions
What Is the Most Efficient Way to Parse a CSS Color in JavaScript
Transforms Are Added...Endlessly
D3.Js Drawing Geojson Incorrectly
Add Property to an Array of Objects
Correct Path for Img on React.Js
How to Find If an Array Contains a Specific String in JavaScript/Jquery
Trying to Validate Url Using JavaScript
Html5 Drag & Drop Change Icon/Cursor While Dragging
Dynamically Add CSS to Page via JavaScript
Changing Background Color of Div on Scroll
Differencebetween Angular-Route and Angular-Ui-Router