HTML/CSS feature detection for PWA - javascript

MDN defines 'progressive' in progressive web apps as -
Modern web apps can be developed to provide a super cool experience to
fully capable browsers, and an acceptable (although not quite as
shiny) experience to less capable browsers. We've been doing this for
years with best practices such as progressive enhancement, so let's
keep up the good work.
I understand that in terms of javascript features, we can use if-else conditions to check for existence of feature and handle it appropriately.
But what are best ways to do this for HTML/CSS ?
The google / MDN documentation lay strong emphasis on checking for JS features, but have no documentation for html/css.
My use case is to build a web app that has modern features, but still works on all kinds of browsers (including proxy browsers like Opera Mini and UC Browser).

By using a script library called Modernizr you can add checks for different HTML5/CSS3 features into your pages with a minimal amount of code,
To generate a production script, the site provides a custom script generation tool rather than providing a single script that has everything for HTML5/CSS3 feature detection. Using the script generation tool you can pick the specific test functionality that you need and ignore everything that you don’t need.
Here is great article on how to use Modernizr
If you want to go beyond modernizr, you can start using new CSS rule #supports for feature detection. This rule is part of the CSS3 Conditional Rules Module. Thanks to this rule, you can selectively apply CSS styles only when browser supports them. Otherwise, the browser will ignore these styles. It’s syntax is very similar to CSS media queries.

In case you need to check the availability of CSS features for expample backdrop-filter within Javascript you can use:
CSS.supports("backdrop-filter", "blur(10px)")
In a condition:
if (CSS.supports("backdrop-filter", "blur(10px)")) {
// some code when supported
} else {
// some code when not supported
}
This works not for Internet Explorer so if there is a fallback it's better.

Related

Is Modernizr really needed if you're not using the feature detection?

I keep jumping into projects where Modernizr is located in the head, but it isn't being used (at least for feature detection). Now, I love Modernizr, I use it frequently for feature detection and fallbacks on projects that require it; however, the last three projects I've come into it's been sitting in the head without any of the feature detection classes being called. These projects are using vanilla javascript and/or do not require jQuery polyfills at all. 1 That being said... if you're not using the feature detection and really don't need to load a jQuery library 2, is Modernizr really doing anything aside from making an addition HTTP request and resource to load?
I'm not strong enough with jQuery/javascript to understand if it's affecting anything else under the hood.
Edit
1 & 2 — Modernizr is javascript and doesn't require the jQuery library (which makes me wonder why the jQuery library is being loaded also, at least in these cases).
Modernizr.min with only #-shiv-cssclasses-load is 7.57 KB whereas html5shiv.min is only 3 KB.
Generally speaking, Modernizr does three things.
It adds classes indicating feature support, allowing you to apply different styling to elements depending on what features they support.
It allows you to run feature detection to decide whether to run a script/run a polyfill or not.
It injects html5shiv, which allows old browsers to understand HTML5 elements.
If you don't use any of these features, then there's no point in including Modernizr at all. If you only use it for the html5shiv then you could probably just include that instead to save a few bytes, although I doubt there's a relevant size difference at all.
That said, you should never include feature detects in a modernizr build that you don't use. That's nothing but a waste.
Modernizr also include shims which save you from defining them yourself or including another library.
The main goal of Modernizr is to use detection via classes. so you can do something like this:
Example, where you want to change behaviour depending on whether the client support flash:
.flash #flashdiv
{
display:block;
}
.no-flash #flashdiv
{
display:none;
}
It really helps you to dynamically deal with the abilities different client browsers.
Also, you can use Modernizr to detect HTML5 features and provide fallbacks (polyfills).
Eg:
<script>
if (Modernizr.canvas) {
alert("This browser supports HTML5 canvas!"); //you can load js here. or use yepnope)
}
</script>

Test CSS property value for (x) to see if specific media query is active for conditional loading of JS, etc...

Wondering what issues people may see with doing this. Here's what's going on that seems to work in a simple POC:
Some media query for all your appropriate styles:
#media screen and (max-device-width : 640px) {
body:after {
display: none;
content: 'mobile';
}
etc ...
}
Then test:
var isMobile = window.getComputedStyle(document.body, ':after').content === 'mobile' ? true : false;
and then from there obviously:
if ( isMobile ) doMobileAndLoadStuff();
To me this seems cleaner than a bunch of JS to detect screen size or user agent string whatever. I know IE8 does not support getComputedStyle but that can be solved easily. Does anyone think this is good or bad? Are there gotchas I don't see? Is there a cleaner simpler solution?
This is exactly what Modernizr is for.
What is Modernizr?
Modernizr is a small JavaScript library that detects the availability
of native implementations for next-generation web technologies, i.e.
features that stem from the HTML5 and CSS3 specifications. Many of
these features are already implemented in at least one major browser
(most of them in two or more), and what Modernizr does is, very
simply, tell you whether the current browser has this feature natively
implemented or not.
Unlike with the traditional—but highly unreliable—method of doing “UA
sniffing,” which is detecting a browser by its (user-configurable)
navigator.userAgent property, Modernizr does actual feature detection
to reliably discern what the various browsers can and cannot do. After
all, the same rendering engine may not necessarily support the same
things, and some users change their userAgent string to get around
poorly developed websites that don’t let them through otherwise.
Modernizr aims to bring an end to the UA sniffing practice. Using
feature detection is a more reliable mechanic to establish what you
can and cannot do in the current browser, and Modernizr makes it
convenient for you in a variety of ways:
It tests for over 40 next-generation features, all in a matter of milliseconds
It creates a JavaScript object (named Modernizr) that contains the results of these tests as boolean properties
It adds classes to the html element that explain precisely what features are and are not natively supported
It provides a script loader so you can pull in polyfills to backfill functionality in old browsers
With this knowledge that Modernizr gives you, you can take advantage
of these new features in the browsers that can render or utilize them,
and still have easy and reliable means of controlling the situation
for the browsers that cannot.
Why use Modernizr?
Taking advantage of cool new web technologies is
great fun, until you have to support browsers that lag behind.
Modernizr makes it easy for you to write conditional JavaScript and
CSS to handle each situation, whether a browser supports a feature or
not. It’s perfect for doing progressive enhancement easily.
How it works
For a lot of the tests, Modernizr does its “magic” by creating an
element, setting a specific style instruction on that element and then
immediately retrieving it. Browsers that understand the instruction
will return something sensible; browsers that don’t understand it will
return nothing or “undefined”.
Many tests in the documentation come with a small code sample to
illustrate how you could use that specific test in your web
development workflow. Actual use cases come in many more varieties,
though. The possible uses of Modernizr are limited only by your
imagination.
If you’re really interested in the details of how Modernizr works,
look at the source code of modernizr.js and the various feature
detects, and dig into the project on GitHub.
Supported browsers
We support IE6+, Firefox 3.5+, Opera 9.6+, Safari 2+, Chrome. On
mobile, we support iOS's mobile Safari, Android's WebKit browser,
Opera Mobile, Firefox Mobile and whilst we’re still doing more testing
we believe we support Blackberry 6+.
Check out the full list of features that Modernizr detects, or learn more about conditional resource loading with Modernizr.

How do you use HTML5 tags while supporting Progressive Enhancement for no-script clients that don't natively recognize unknown elements?

As I understand Progressive Enhancement, one of the basic tenets is the web site should be functional for everyone, regardless of browser version or settings.
The suggested breakdown I've seen is:
HTML content layer using semantic markup
CSS Presentation layer
Enhancement layer (typically through JavaScript or a JS library like JQuery)
I'm a bit confused over the proper way to handle the HTML content layer, however. In particular, the semantic markup.
I keep seeing that HTML5 tags such as nav, article, footer etc. are the ideal method of maintaining this semantic markup for PE. However, many older browsers do not support HTML5 tags. The easy way to get around this is to use CSS to set default stylings to { display: block; } for the HTML5 tags, but this only works with some browsers. The dreaded IE6, for example, does not recognize HTML5 elements.
The typical workaround for this is to use javascript to dynamically create the missing elements directly into the DOM (such as through an HTML5 shiv).
However... if the client is running an environment that doesn't recognize HTML5 elements, and they do not, for whatever reason, accept javascript, how do you incorporate HTML5 semantic tags in support of Progressive Enhancement, without failing to render properly for scriptless browsers that don't recognize the tags? Is this possible, or do you have to leave those browsers out of your design consideration (which seems counter to the PE ideals)?
If you are hyper-paranoid about supporting GhettoIE, without JS, in this fashion, this might be the time to use if ie comments in the HTML, directing people to get Chrome Frame, or get a better browser, or to click a link to take them to an oldschool, fugly-but-functional version of the page, which adheres to CSS2.1 (just core features) and HTML4.01 strict markup.
The point of Progressive Enhancement IS to provide separation of concerns, and offer features as they're supported... ...but there ARE baseline requirements, here.
You can't expect Mosaic and IE3 to run this stuff, either.
IE6 with JS, or non-IE, modern standard browser, without is sort of the de-facto, here.
According to Yahoo's internal traffic analysis, nearly all users with JavaScript disabled are using HTML5 compliant browsers. Don't worry about not supporting the rare IE8 user with JavaScript disabled.
Your company won't lose any business by not supporting those users. The only real reason to offer this level of support would be as an academic exercise to prove it can be done. There's no bang for your buck.

Is there a JS library to add HTML 5 features to browsers, which don't support them?

I'd like to use autofocus="autofocus" in my code, but since some browsers don't support this yet, I was thinking of adding some JS code, which would search for an element with such a tag, and focus it with JS. But since this seems to be a common requirement, I wonder if there are any ready libraries, which can take care of at least some HTML5 annoyances with older browsers?
I believe the correct answer would be not quite. Modernizr 2.0 (including html5shim) gives us semantic elements of html5 (actually the html5shim does that) and great feature detection which you can use for graceful js fallback.
In you case It would be using jQuery .focus() with something like:
if (!Modernizr.autofocus){
$('input[autofocus=""]').focus();
}
more examples here
If older browsers don't support certain advanced features, then I would say follow progressive enhancement and don't worry about it. So long as the core functionality of your site—ordering products, or whatever—works across the board, then don't be afraid to add in shiny html5 features for the benefit of your users with good browsers.
Putting in clunky/third-party code to force IE6 and 7 to behave in a civilized manner will potentially be a lot of work for you, will be prone to bugs, and won't even give you too much of a payoff since the folks using IE6 probably won't be looking over the shoulders of Chrome users to see a nicer version of your site there.
Here are the slides (from a jQuery conference) that really drove this home for me.
The role of Modernizr (previously mentioned) is to do feature detection, to determine what HTML 5 features are available. Modernizr doesn't automatically make unavailable HTML 5 features available, but it does make it possible for you to conditionally load scripts (commonly referred to as polyfills) to add those features. In the case of autofocus, the html5support library should provide what you need, and you can use Modernizr's conditional loading to only load it if needed.
Users of libraries like jQuery say that they implement such a features.
I don’t recommend it anyway, try to code the minimum functions you need by yourself.
Take also a look at http://www.modernizr.com/.

Is it possible to write a JavaScript library that makes all browsers standards compliant?

I'm not a JavaScript wiz, but is it possible to create a single embeddable JavaScript file that makes all browsers standards compliant? Like a collection of all known JavaScript hacks that force each browser to interpret the code properly?
For example, IE6 does not recognize the :hover pseudo-class in CSS for anything except links, but there exists a JavaScript file that finds all references to :hover and applies a hack that forces IE6 to do it right, allowing me to use the hover command as I should.
There is an unbelievable amount of time (and thus money) that every webmaster has to spend on learning all these hacks. Imagine if there was an open source project where all one has to do is add one line to the header embedding the code and then they'd be free to code their site per accepted web standards (XHTML Strict, CSS3).
Plus, this would give an incentive for web browsers to follow the standards or be stuck with a slower browser due to all the JavaScript code being executed.
So, is this possible?
Plus, this would give an incentive for web browsers to follow the standards or be stuck with a slower browser due to all the JavaScript code being executed.
Well... That's kind of the issue. Not every incompatibility can be smoothed out using JS tricks, and others will become too slow to be usable, or retain subtle incompatibilities. A classic example are the many scripts to fake support for translucency in PNG files on IE6: they worked for simple situations, but fell apart or became prohibitively slow for pages that used such images creatively and extensively.
There's no free lunch.
Others have pointed out specific situations where you can use a script to fake features that aren't supported, or a library to abstract away differences. My advice is to approach this problem piecemeal: write your code for a decent browser, restricting yourself as much as possible to the common set of supported functionality for critical features. Then bring in the hacks to patch up the browsers that fail, allowing yourself to drop functionality or degrade gracefully when possible on older / lesser browsers.
Don't expect it to be too easy. If it was that simple, you wouldn't be getting paid for it... ;-)
Check out jQuery it does a good job of standardizing browser javascript
Along those same lines explorercanvas brings support for the HTML5 canvas tag to IE browsers.
You can't get full standards compliance, but you can use a framework that smooths over some of the worst breaches. You can also use something called a reset style sheet.
There's a library for IE to make it act more like a standards-compliant browser: Dean Edwards' IE7.
Like a collection of all known
javascript hacks that force each
browser to interpret the code properly
You have two choices: read browser compatibility tables and learn each exception a browser has and create one yourself, or use avaiable libraries.
If you want a javascript correction abstraction, you can use jQuery.
If you want a css correction abstraction, you can check /IE7/.
I usually don't like to use css corrections made by javascript. It's another complexity to my code, another library that can insert bugs to already bugged browsers. I prefer creating conditional statements to ie6, ie7 and such and create separate stylesheets for each of them. This approach works and doesn't generate a lot of overhead.
EDIT: (I know that we have problems in other browsers, but since IE is the major browser out there and usually we need really strange hacks to make it work, css conditional statements is a good approach IMO).
Actually you can,there are lots of libraries to handle this issue. From the start of the time, javascript compliance issue always was a problem for developers and thanks to innovative ones who developed libraries to get over this problem...
One of them and my favorite is JQuery.
Before JavaScript 1.4 there was no global arguments Array, and it is impossible to implement the arguments array yourself without a highly advanced source filter. This means it is going to be impossible for the language to maintain backwards-compatibility with Netscape 4.0 and Internet Explorer 4.0. So right out I can say that no, you cannot make all browser standards compliant.
Post-netscape, you can implement nearly all of the features in the core of the language in JavaScript itself. For example, I coded all methods of the Array object in 100% JavaScript code.
http://openjsan.org/doc/j/jh/jhuni/StandardLibrary/1.81/index.html
You can see my implementation of Array here if you go to the link and then go down to Array and then "source."
What most of you are probably referring to is implementing the DOM objects yourself, which is much more problematic. Using VML you can implement the Canvas tag across all the modern browsers, however, you will get a buggy/barely-working performance in Internet Explorer because VML is markup which is not a good format for implementing the Canvas tag...
http://code.google.com/p/explorercanvas/
Flash/Silverlight: Using either of these you can implement the Canvas tag and it will work quite well, you can also implement sound. However, if the user doesn't have any browser plugins there is nothing you can do.
http://www.schillmania.com/projects/soundmanager2/
DOM Abstractions: On the issue of the DOM, you can abstract away from the DOM by implementing your own Event object such as in the case of QEvent, or even implementing your own Node object like in the case of YAHOO.util.Element, however, these usually have some subtle changes to the standard API, so people are usually just abstracting away from the standard, and there is hundreds of cases of libraries that abstract away.
http://code.google.com/p/qevent/
This is probably the best answer to your question. It makes browsers as standards-compliant as possible.
http://dean.edwards.name/weblog/2007/03/yet-another/

Categories

Resources