I am using Modernizr v3 on my website to test for flexbox support.
Modernizr adds a "flexbox" body class for browsers that support it, and "no-flexbox" for browsers that do not. As browsers that don't support flexbox are only a minority of my audience, I have used the "no-flexbox" class to provide fall back CSS. For example:
.ad { /* Default CSS */
display: flex;
}
.no-flexbox .ad { /* Fallback CSS*/
display:table;
}
Everything works fine, except for IE10, as Modernizr adds a "no-flexbox" class to it, even though IE10 does support Flexbox, it is just using the older syntax. Therefore, on IE10 my layout is broken as it reads both the flex box and non-flexbox styles.
In this thread, it says that moderniser has a flexboxtweener style to IE10. Therefore, I thought I could rewrite my fall backs to use .no-flexboxtweaner instead of .no-flexbox.
The problem is that browsers that support the new flexbox syntax get given a no-flexboxtweaner class as well, so they read the fallback code.
How can I set it up so that only the browsers that do not support any form flexbox (regardless if it is new or old) get the "no" class.
I know I could do ".no-flexbox .ad, .no-flexboxtweaner .ad", but then that's bloating the CSS (plus running two Modernizr tests). I'd rather just have a single test/class.
I know I could do ".no-flexbox .ad, .no-flexboxtweaner .ad", but then that's bloating the CSS (plus running two Modernizr tests). I'd rather just have a single test/class.
Thats kindof silly, mate. It is a handful of bytes - almost all of which will be erased by gzipping your file. If you reallllly wanted to avoid it, you could create an additional Modernizr check that gives you any flexbox
Modernizr.addTest('anyflexbox', (Modernizr.flexbox || Modernizr.flexboxtweener))
that will create a new property called anyflexbox and you can style your css accordingly.
Detects support for the flex-wrap CSS property, part of Flexbox, which isn’t present in all Flexbox implementations (notably Firefox).
This featured in both the 'tweener' syntax (implemented by IE10) and the 'modern' syntax (implemented by others). This detect will return true for either of these implementations, as long as the flex-wrap property is supported. So to ensure the modern syntax is supported, use together with Modernizr.flexbox:
if (Modernizr.flexbox && Modernizr.flexwrap) {
// Modern Flexbox with `flex-wrap` supported
}
else {
// Either old Flexbox syntax, or `flex-wrap` not supported
}
Ref: https://modernizr.com/docs
Related
How can I reliable create a fallback for CSS grid styling for browsers that don't support the current spec, with a feature query or media query?
According to articles like this one, browsers ignore CSS that they can't parse. Therefore, I expected negative feature queries to work even on browsers that don't support it. E.g. IE11 does not support feature queries, so I expected it to ignore this line and apply the styles inside the query: #supports not (display: grid){}. However, as you can see in this test, IE11 ignores all the styles inside that query.
I found a media query for IE10+, but that one excludes other browsers that don't support grid. Of course I could first declare the fallback styles and override them with a #supports (grid-area: area) query, but I prefer a solution that does not require overrides.
According to articles like this one, browsers ignore CSS that they can't parse [...] However, as you can see in this test, IE11 ignores all the styles inside that query.
Well, yeah. Since Internet Explorer doesn't understand feature queries themselves, it's going to ignore #supports not (display: grid) and everything inside it, because it doesn't understand what that means. Just like the article says.
Overriding, i.e. making use of the cascade, is your only option. There is no clean way of doing this. The reality is that #supports was introduced too late to be useful for distinguishing browsers that don't support features that precede it, such as grid layout.
I am playing around with CSS-animated SVG elements and came across the problem that even though all technologies, which are used, are supported by some browsers the combination is not, i.e. CSS-animated DIVs work but SVG elements don't. I am wondering if there is a way to detect if a browser is capable of animating SVG elements using CSS.
Here is a jsFiddle with an example. It works in the latest versions of Chrome, Firefox and Safari. But when opening it with e.g. Firefox 5 only the div rotates while the rect doesn't.
You can add an event listener to check for the completion of an animation iteration, and within the corresponding event handler set a flag like supportsSVGKeyFramedAnimatedProps = true (if the iteration never completes then it is not animating).
elem.addEventListener('animationiteration', eventHandler, false)
This would allow you to 'fall forward' to your SVG animation, instead of providing a fallback.
I am wondering if there is a way to detect if a browser is capable of
animating SVG elements using CSS
Simple Answer: Yes you can as stated by #jhpratt.
You can detect if a browser supports CSS-Functionality with only CSS.
The #supports CSS at-rule lets you specify declarations that depend on a browser's support for one or more specific CSS features. This is called a feature query.
Example:
#supports (display: flex) {
div {
display: flex;
}
}
#supports not (display: flex) {
div {
float: right;
}
}
MDN Link: https://developer.mozilla.org/de/docs/Web/CSS/#supports
Long Answer:
You will always have some cross-browser issues.
The problem you have encountered is bothering every Webdeveloper. Still there are ways to get around with this Browser-Support-Problem:
1. You can check "can I use" for compatibility:
Link: http://caniuse.com/
It is recommend to look up any functionality which is questionable like animations.
2. Use an autoprefixer in your workflow:
With the help of an autoprefixer you don't have to worry most of the time about using CSS with a prefix like -moz-, -webkit-, etc. This tiny helper will do the trick for you, you can even tell some autoprefixers which browsers you want to support.
3. User 3rd - Party libraries:
There are many libraries out there which you can use to detect the browser and version. If you want to be sure that your animation is secure to use, you can simply use the provided animation from the libraries and of course look the compatibility up before on their respective websites.
Some Big Names:
Angular: https://angularjs.org/ (use ng-Animate)
JQuery: https://jquery.com/
Greensock: https://greensock.com/
there are many more, jsut search the world wide web.
4. Use CSS Hacks to detect specific Browsers:
It is possible to use so called CSS-Hacks. They are specific CSS calls, which only apply on certain browsers.
Some examples:
Internet Explorer/Edge 8 only: #media \0screen {}
firefox ≥ 3.6 only: #media screen and (-moz-images-in-menus:0) {}
Opera ≤ 9.27 AND Safari 2: html:first-child .selector {}
You can look up more Browserhacks here: http://browserhacks.com/
Conclusion:
It is possible to detect specific browsers, but it is not possible to detect if the brwoser is supporting the given feature with only CSS. That is why you will always have some hard times with browser support.
Hope this helps.
Regards
I believe that the SMIL animations detections in modernizr should do it. https://modernizr.com/download?smil-setclasses
I'm using it in a pretty involved set of css/SVG chart animations. Just wrap a fallback in the following tag:
.no-smil{ }
http://codepen.io/msbtterswrth/pen/greWzy
I haven't done exactly what you're looking for, but something similar (providing an animated clip-path as defined by SVG when the browser supports it and falling back when it doesn't). You can use media queries looking for pixel ratios to determine if a broswer is moz or webkit and provide the fallback animation outside the media query and provide the preferred animation in media queries that indicate a browser that will support it.
//fallback animation here
#media (-webkit-min-device-pixel-ratio: 0) {
// webkit animation here
}
As for older versions of Firefox? I don't know how to do that in CSS, but I'm not sure going back more than a few versions of Firefox or Chrome is a common use case.
I have a form marked up like: <form id="some-form">. I have always selected forms using
#some-form { /* declare my css */ }
However, one of my team members said this is not cross-browser or backwards compatible and said I needed to declare my css using syntax something like:
form [id="some=form"] { /* declare my css */ }
Can anyone elaborate on whether this is true? And which browsers / versions will be affected? And what the proper syntax to ensure cross-browser backwards-compatibility? Thanks!
What your team member is describing is the CSS attribute selector. If anything, his/her way of targeting the <form> element would be less backwards compatible as the ability to target elements based on attributes was added in CSS 2.1 while your way of doing it has been around since the beginning. Although less compatible, the market share of browsers that do not support CSS 2.1 is very minimal, and shrinking every day.
See here for more info: http://www.w3.org/TR/CSS2/selector.html#attribute-selectors
selecting elements by id using #someid has been supported since CSS1. So just about every browser that has CSS support should support it.
I want to start using some HTML5 tags, but worried how it will render on browsers that do not support HTML5. It seems like html5shiv is a solution I can use for IE browsers < 9.
However, what if the browser doesn't support HTML5 and is not IE? What then? Why is html5shiv an IE thing?
First, to be clear, html5shiv just makes it so that you can style certain HTML5 tags (section, article, etc.) correctly. It does not give the browser "HTML5 support" in any more general sense of the term.
With that in mind, note that IE <9 are the only browsers that don't allow styling of these HTML5 tags correctly, so that's why html5shiv only applies to them.
Other browsers (even very old ones like Netscape Communicator 4) will still parse the unrecognized tags correctly and allow CSS to apply to them as you would expect.
As zzzzBov notes in his answer, they might not have the correct default styles (which in most (all?) cases are either display: block or nothing), so you'd need to add those even for non-oldIE browsers. But doing so works fine in non-oldIE browsers, whereas in oldIE, adding these default styles---or any styles whatsoever---only works if you use html5shiv.
The initial value for the display property of an element is inline (ref). The built-in user-agent stylesheet changes the properties to sensible values for known elements; for example, headings and paragraphs are changed to block.
HTML5 introduces new elements such as header, footer, article and section (the HTML5 sectioning elements). Since older browsers do not know about them, they treat these elements as inline. You must therefore add CSS rules for these elements manually:
header, footer, article, section { display: block; }
But as mentioned in the Story of the HTML5 Shiv:
...Internet Explorer 6-8 pose a problem as they do not recognize
unknown elements; the new elements cannot hold children and are
unaffected by CSS
The workaround for IE 6-8 is also mentioned in that article:
Btw, if you want CSS rules to apply to unknown elements in IE, you
just have to do document.createElement(elementName). This somehow lets
the CSS engine know that elements with that name exist
Now, regarding your question: The html5shiv uses some JavaScript tricks to make the unknown elements styleable in IE 6-8. As for other browsers that do not support HTML5, the html5shiv, if necessary, adds the default styles required to render the HTML5 elements properly so that you don't have to define the CSS rules yourself (as mentioned above).
Note that html5shiv does not make the browser support HTML5. For example, it cannot make IE7 play videos embedded via HTML5 <video> tag.
Other browsers support non-standard elements simply by setting their css display property:
header,
footer,
article,
section,
...etc... {
display: block;
}
For old versions of Firefox and webkit based browsers (pre HTML5) this was all that was necessary.
htmlshiv is an 'IE' thing, because some versions of IE [still] lack many HTML5 features. What works in chrome or other webkit browsers may not work in IE, so htmlshiv TRIES to give a javascript adaptation of the missing features. Its a polyfill, to be exact as well.
Is there a list of 'good' clean CSS hacks, which are certain to be future-proof?
For example, zoom:1 is safe, as long as it's only served to IE, and you remember it's there. The very common hack of using child selectors is not safe because IE7 supports them. Using height:1% just feels dirty (but that might just be me).
I know of ie7-js, so IE6 bugs don't worry me much. Also, I'm not looking for a religious debate, just sources.
Thanks for the replies - I've selected the one with best sources as answer.
Thanks also for the suggestions to use separate CSS files, or not to worry about it. I entirely agree with you, and for me, those are givens. But when faced with a layout problem, I want a safe fix that will minimise the risk that I'll have to revisit the problem in $IE or $FF + 1. Sorry I didn't make that clearer.
For the majority of IE bugs I think you're best off using conditional comments around a link to a browser specific stylesheet. It tends to keep things pretty neat and it's quite self documenting.
This is a good place for well-documented and well-tested browser bugs and the hacks allow you to work around them:
http://www.positioniseverything.net/
I've used Peter-Paul Koch's "QuirksMode" website a lot for issues involving CSS and cross-browser compatibility. He tends to frown on browser-specific methods, but he does have a page on CSS Hacks.
Nicole Sullivan (AKA Stubbornella) who works for the Yahoo Performance team suggested in The 7 Habits for Exceptional Perf that you should use the CSS underscore hack to patch up IE6 bugs because:
Hacks should be few and far between.
If you will only have 5-6 hacks (which is already plenty) then it would not make sense placing those in an external file and thereby separating it from its context.
An extra file would lead to performance penalties (Yahoo Best Practices, Rule 1).
It should however be noted that this is not valid CSS.
There's no such thing as a good clean/acceptable [css] hack - always code to Standards, and then use browser+version specific stylesheets for any hacks required to make things work.
For example:
default.css
default.ie6-fix.css
default.ie7-fix.css
default.ff2-fix.css
etc
Then, when new version of a browser are released, copy the previous version's hacks and remove the bits that no longer apply (and add new bits, if necessary).
(Load individual stylesheets using Conditional Comments for IE, and user-agent sniffing for other browsers.)
Underscore-hack for IE6-stuff works quite well, eg.
min-height:50px;
_height:50px;
It doesn't require moving things out of context into new css-files, only IE6 gets them and they're easy to filter out if you should decide to stop supporting IE6. They're also very minimal and won't clutter your CSS that much.
Modifying your CSS for browser-specific support is never wrong - as long as you can easily contain it. As you'll notice, standards-compliant browsers, * cough * everything except MSIE, will never break with future releases. New W3C standards also don't break previous standards, they usually deprecate or extend previous standards at the most.
People have mentioned conditional comments which are great for handling IE. But you'll need a bit more for handling all browsers (mobile, gecko, webkit, opera, etc.). Usually you'll parse the incoming request headers to fetch the browser type and version from the User-Agent param. Based on that you can begin loading your CSS files.
I belive the way most of us do it is by:
First developing for one standards-compliant browser (let's take FF for example)
Once the CSS is complete you approach providig support for IE (this can be easily done with the conditional comments, as perviously mentioned)
First create a CSS file that will fine tune everything for IE6 and any other version below
Then create a CSS file that will handle everything for IE7
Lastly, create a CSS file that will handle everything for IE versions of IE8 and greater
Once IE9 comes out, make sure you set IE8+ handling to IE8 specific, and create a IE9+ CSS file with required fixes
Finally, create an additional CSS file for webkit fixes
If required, you can also create additional files to specifically target Chrome or Safari if required
Concerning browser specific CSS implementations, I usually group all of those in my main css file (you can easily do a search for those and replace them in one document if needed). So if something has to be transparent, I'd set both opacity and filters (MSIE) in the same block. Browsers just ignore implementations they don't support, so your safe. Specific implementations I'd tend to avoid are custom implementations (hey, I like the -moz box above the W3C one, but I just don't want to rely on it).
As it goes with CSS inheritance and overriding, you don't have to redefine all the CSS declarations and definitions in every CSS file. Each consecutively loaded CSS file should only contain the selector and specific definitions required for the fix, and nothing else.
What you end up with in the end is your (huge) main css file and others, containing a few lines each, for specific browser fixes - which sums up to something that's not that very hard to maintain and keep track of. It's a personal preference what browser your base css file will be based off, but usually you'll be targeting a browser that will create the least amount of issues for other browsers (so yes, developing for IE6 would be a very poor decision at that point).
As always, following good practices and being pragmatic and meticulous with selectors and specifics about each class and using frameworks will lead you down the path of goodness with seldom fixes required. Structuring your CSS files is a huge plus unless you want to end up with an unordered meaningless mess.
Centricle has a good list of CSS hacks and their compatibilities.
I don't think you'll find a list of hacks that will be future proof, as know one can tell what stupid thing will be implemented in IE next.
This article is a good summary of CSS hacks: http://www.webdevout.net/css-hacks
Here's a good list of filters that are very stable:
/* Opera */
.dude:read-only { color: green; }
/* IE6/IE7 */
#media,
{
.dude { color: silver;}
}
/* IE8 \0 */
#media all\0
{
.dude { color: brown; }
}
/* IE9 monochrome and \9 */
#media all and (monochrome: 0)
{
.dude { color: pink\9; }
}
/* Webkit */
* > /**/ .dude, x:-webkit-any-link { color:red; }
/*
* > /**/
/* hides from IE7; remove if unneeded */
/* Firefox */
#-moz-document url-prefix()
{
.dude { color: green; }
}
When defining rules, I find it good to allow natural degradation take place, for instance, in CSS3 there is support for RGBA Colour models, but there isn't in CSS2, so I find myself doing:
background-color: #FF0000;
background-color: rgba( 255,0,0, 50% );
So that when the later rule fails on older browsers which don't support it, it will degrade to the previously defined style.
I prefer the global conditional comment technique described by Hiroki Chalfant;
I find it helpful to keep my IE-targeted rules side-by-side with my standards-targeted rules in a single valid stylesheet.