Evaluating browser support
Talking about web browser support for a given CSS or Javascript is deceptively simple. This post will explore a definition of browser support, different strategies to support a feature accross browsers, the concepts of graceful degradation and progressive enhancement, and how to handle features that can't be polyfilled. ## How to evaluate browser support When talking about browser support, we are actually asking three related questions: 1. How essential is the feature to the application? 2. Is the feature supported in all browsers? 3. Is there a way to polyfill or provide an alternative for the feature? For most CSS and Javascript features support is pretty good, but we can't rely on that alone. For example, even though a feature is in a specification, it doesn't mean that all browsers have implemented it or that they have implemented it correctly. Furthermore, there are features supported in Chromium browsers (most of these features are part of Chromium's [Capabilities Project)](https://developer.chrome.com/docs/capabilities) or Project Fugu) that are not supported in Firefox and Safari. The feature I'll use for this example is [WebUSB](Building a device for WebUSB), which allows web applications to communicate directly with USB devices. The example application is a web-based app that interacts with medical devices through USB. The app is used by doctors to monitor patients in real-time. So the answer to question 1 is that the feature is essential to the application. As discussed earlier, the feature is not available in Safari and Firefox. We can either say "Sorry, the app will only work in Chromium browsers" or we can try to provide an equivalent experience in other browsers either with a polyfill or an alternative. The hardest question to answer is the third one. There is no way to polyfill WebUSB because it interacts with hardware. It may be possible to port a [generic USB library](https://web.dev/articles/porting-libusb-to-webusb) to the web using [Emscripten](https://emscripten.org/), but that would be a significant effort that would be ongoing as you add new USB devices to the app, you also have to maintain multiple paths to accomplish the same task. Based on the answers to these three questions, we may still have an approach to support USB on the web and to still create a compelling user experience but we're aware of the additional costs involved in dealing with non-standard features. ## Strategies to support a feature across browsers If we decide that we need to support a given feature we have multiple strategies to do so. Some of these strategies are structural (like progressive enhancement and graceful degradation) and some are technical (like using multiple declarations in CSS or using feature detection in Javascript). ### Graceful degradation or progressive enhancement? One of the oldest debates in web development is whether to use [graceful degradation](https://developer.mozilla.org/en-US/docs/Glossary/Graceful_degradation) or [progressive enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). In a graceful degradation scenario, we build the full application and we let features stop working, without loosing the core functionality of the app. In a progressive enhancement scenario, we build the core functionality of the app and we add features that may not be supported in all browsers. Which strategy to approach depends on the app and what your goal is: In our medical device USB application example, we could use progressive enhancement to create the basic application and work the alternative for browsers that don't support the feature we need. ### Measuring Usage If you use analytics in your app, you can measure what browsers and versions your users are using. This can help you decide what features to implement and what fallbacks to make available. You can look at tools like [Can I Use](https://caniuse.com/) to see what features are supported in what browsers and versions. ### CSS CSS is forgiving, it will ignore declarations it doesn't understand. This will provide a basic level of support for most features. #### Using multiple declarations You can use multiple declarations to provide support for different browsers. When using multiple declarations, the browser will use the last one it understands. This means **the order of declaration matters**. For example, you can use different color spaces for different browsers. All declarations point to the same color but not all browsers . ```css .example { color: rebeccapurple; color: #663399; color: oklch(44.03% 0.1603 303.37); } ``` This means you have to write more code in your CSS, but it's a simple way to provide support for different browsers and versions. #### Using @supports