title: Cutting the Mustard Revisited
url: http://sixtwothree.org/posts/cutting-the-mustard-revisited
hash_url: 2d8045c2482f4bdee26d3d89557aaccf

<p>Three years ago, the team working on the redesigned BBC News website posted “<a href="http://responsivenews.co.uk/post/18948466399/cutting-the-mustard">Cutting the Mustard</a>,” outlining their method for bucketing browsers based on capability. While JavaScript feature detection isn’t new, the BBC News team’s approach is a novel rethinking of the technique.</p>

<p>With the following lines of code, browsers are categorized as being either “HTML4” or “HTML5” capable.</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="k">if</span> <span class="p">(</span><span class="s1">'querySelector'</span> <span class="k">in</span> <span class="nb">document</span>
    <span class="o">&amp;&amp;</span> <span class="s1">'localStorage'</span> <span class="k">in</span> <span class="nb">window</span>
    <span class="o">&amp;&amp;</span> <span class="s1">'addEventListener'</span> <span class="k">in</span> <span class="nb">window</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Bootstrap the JavaScript application…</span>
<span class="p">}</span>
</code></pre></div>
<p><em>If</em> a browser supports <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector"><code>querySelector</code></a>, <em>if</em> it supports <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage"><code>localStorage</code></a>, and <em>if</em> it also understands <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener"><code>addEventListener</code></a>, then that browser is capable enough to execute the website’s JavaScript. There’s no mention of browsers and no fiddling about with <a href="http://useragentstring.com/pages/useragentstring.php">the nightmare hellscape that is user agent strings</a>. This is <a href="/posts/designing-with-progressive-enhancement">designing with progressive enhancement</a> in mind: build a functional core experience using HTML and CSS and then, as browser capabilities allow, <em>enhance!</em></p>

<p>The combination of feature detections in the code example above covers the majority of browsers released in the last six or so years. Oh, and Internet Explorer 9 (released in 2011) and newer. It’s possible this combination will work for you, but you’ll want to gather some analytics on this before making any decisions.</p>

<h2>New Mustard</h2>

<p>In the three years since the original mustard cut, browsers have progressed at a fantastic clip. Most significantly, in March of this year, Microsoft retired Internet Explorer in favor of the more-frequently updated Edge. With <a href="http://caniuse.com/usage-table">global usage</a> of <em>all versions of Internet Explorer prior to 11</em> sitting comfortably around 3% and the rapid adoption of current versions of other major browsers, it seems the time is right to spice up our mustard.</p>

<p><em>(I promise that’s the last food pun…)</em></p>

<h3>Detecting with <code>visibilityState</code></h3>

<p>Google developer <a href="https://jakearchibald.com/">Jake Archibald</a> gave us the following gem <a href="https://twitter.com/jaffathecake/status/570872103227953153">in a tweet</a>:</p>

<blockquote>
<p>if (!(‘visibilityState’ in document)) return;</p>

<p>A nice way to prevent your JS running in IE&lt;10 and Android WebKit <a href="http://caniuse.com/#feat=pagevisibility">http://caniuse.com/#feat=pagevisibility</a></p>
</blockquote>

<p><code>visibilityState</code> is part of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API">Page Visibility API</a> and, as Jake points out, can be used to serve JavaScript to modern browsers (excluding IE less than 10 and older versions of Android’s default WebKit-based Browser app).</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="k">if</span> <span class="p">(</span><span class="s1">'visibilityState'</span> <span class="k">in</span> <span class="nb">document</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Bootstrap the JavaScript application…</span>
<span class="p">}</span>
</code></pre></div>
<p><em>Much</em> shorter, a touch more obscure, and only slightly more exclusive than the BBC News team’s original technique.</p>

<h3>Detecting with <code>devicePixelRatio</code></h3>

<p>You may find, while evaluating your website’s usage statistics, that you want to raise the bar just a little bit higher. In that case, you may consider using <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio"><code>devicePixelRatio</code></a>:</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="k">if</span> <span class="p">(</span><span class="s1">'devicePixelRatio'</span> <span class="k">in</span> <span class="nb">window</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Bootstrap the JavaScript application…</span>
<span class="p">}</span>
</code></pre></div>
<p>According to <a href="http://caniuse.com/#search=devicepixelratio">Can I use…</a>, <code>devicePixelRatio</code> is well-supported and first appeared in Internet Explorer in version 11. For testing and verification purposes, I put together <a href="http://codepen.io/jgarber/pen/PZowBG">this quick demo on CodePen</a>. It’s nice and short and works as you’d imagine. Since we can use pixel density in HTML on <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img">an <code>&lt;img&gt;</code> with the <code>srcset</code> attribute</a> and in CSS with <a href="http://www.w3.org/TR/css3-mediaqueries/#resolution">resolution media queries</a>, using the <code>devicePixelRatio</code> feature detection may be a little more obvious to you and your teammates.</p>

<h2>Your Mileage May Vary</h2>

<p>I suggested earlier in this post that you look at your website’s analytics. I can’t stress this enough. The techniques outlined above are useful, but may not be the most appropriate choice for your website. Dive into the data you have at your disposal and make the best choice for your particular use case.</p>
