<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Issam Mani</title>
    <description>The latest articles on DEV Community by Issam Mani (@issammani).</description>
    <link>https://dev.to/issammani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F546090%2F231886ed-b00b-46cb-a3eb-c8a7aff3424a.png</url>
      <title>DEV Community: Issam Mani</title>
      <link>https://dev.to/issammani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/issammani"/>
    <language>en</language>
    <item>
      <title>🛑OCD ALERT🛑: GET YOUR COPYRIGHT YEAR IN ORDER</title>
      <dc:creator>Issam Mani</dc:creator>
      <pubDate>Fri, 12 Feb 2021 19:34:32 +0000</pubDate>
      <link>https://dev.to/issammani/ocd-alert-get-your-copyright-year-in-order-4g6d</link>
      <guid>https://dev.to/issammani/ocd-alert-get-your-copyright-year-in-order-4g6d</guid>
      <description>&lt;p&gt;When I visit a website the first thing I check is the copyright year in the footer. You might be surprised how many websites out there don't update the year, which might suggest that even when they did some time in the past it was done manually.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gOr06uR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/319arwsxa9vq07kktcj6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gOr06uR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/319arwsxa9vq07kktcj6.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seeing a footer with an outdated year just tells me that the website is not properly looked after, which in a way as a business can degrade the value of your product. &lt;br&gt;
As a web developer, I can't help myself but think that the person who made the website didn't care enough to add a one liner that auto generates the current year.&lt;/p&gt;

&lt;p&gt;I even wrote a &lt;a href="https://github.com/issammani/footer-year-check"&gt;crawler&lt;/a&gt; to find such websites and boy there some big names in the mix. So without further ado I present to you : &lt;br&gt;
🥁&lt;br&gt;
🥁&lt;br&gt;
🥁&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"HONEY I F***** UP THE COPYRIGHT YEAR" TOP 10 2021 Edition:&lt;/strong&gt; [Better name needed, let's make this an annual event 😝]&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://web.archive.org/web/20210212002332if_/https://music.apple.com/us/browse"&gt;Apple Music&lt;/a&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hfb4FBX0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v9p72c9vlcqe42k0qe2l.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.archive.org/web/20210212140850/https://outlook.live.com/owa/"&gt;Outlook&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OGQc1pY1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fecdac1x863cy5wor0l8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OGQc1pY1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fecdac1x863cy5wor0l8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.archive.org/web/20210212143504/https://www.deutschebahn.com/de"&gt;Deutsche Bahn (German railways)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i1hKv2ho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g1lcf8qsxk5p6cuo62l2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i1hKv2ho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g1lcf8qsxk5p6cuo62l2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.archive.org/web/20210210203444/https://www.postdirekt.de/plzserver/"&gt;Deutsche Post (German Postal Service)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--liFBZvfL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0ejq2wffk40r18hz5po4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--liFBZvfL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0ejq2wffk40r18hz5po4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
This one was a real mess. I found pages with 2017, 2019, 2020.&lt;br&gt;
&lt;a href="https://web.archive.org/web/20210203172654/https://www.deutschepost.de/sendung/simpleQuery.html"&gt;Another link&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JPVcXZ7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1sw2cen29ni8jl8c7j0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JPVcXZ7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1sw2cen29ni8jl8c7j0i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some other apple subdomains (This isn't too bad, I mean some pages are archaic)&lt;br&gt;
&lt;a href="https://web.archive.org/web/20210212190532if_/https://podcasts.apple.com/gb/podcast/the-game-football-podcast/id191105605"&gt;Apple podcast lisiting page&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6ga2xnjL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7m0ph6jz1biob9w7q2g8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6ga2xnjL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7m0ph6jz1biob9w7q2g8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://web.archive.org/web/20210212190554if_/https://apps.apple.com/de/app/dhl-paket/id329315203"&gt;Apple app listing page&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DLdLcW30--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hz597zpgj0leo0tdu1z3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DLdLcW30--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hz597zpgj0leo0tdu1z3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.archive.org/web/20210212145238/https://help.vimeo.com/hc/en-us"&gt;Vimeo help center&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--thHqeCr9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bndfu3pe7avfgw5ii6yj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--thHqeCr9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bndfu3pe7avfgw5ii6yj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ironically an &lt;a href="https://web.archive.org/web/20210129210849/https://sonet.digital/blog/general/keep-copyright-up-to-date/"&gt;article on sonet.digital&lt;/a&gt; titled "The Importance of Updating Your Copyright Dates" which in turn has an outdated copyright year.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OFMzUvgi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v5q7axnnt97y993tz0jv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OFMzUvgi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v5q7axnnt97y993tz0jv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.archive.org/web/20210212112459/https://www.githubstatus.com/"&gt;Github Status&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qucq8nRs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mthmdv1fs4rpe0xkw0k3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qucq8nRs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mthmdv1fs4rpe0xkw0k3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.archive.org/web/20210212030810/https://www.stitcher.com/"&gt;Stitcher&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tGAdG_OF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/78ya8alhzgegjs4ok9ei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tGAdG_OF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/78ya8alhzgegjs4ok9ei.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.archive.org/web/20210212165457/https://investors.atlassian.com/investors-overview/default.aspx"&gt;Atlassian investors&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3T_IpLJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f7h0c8czr4oo28xg97cb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3T_IpLJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f7h0c8czr4oo28xg97cb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you would like to test this  for yourself grab a copy of the  &lt;a href="https://github.com/issammani/footer-year-check"&gt;crawler&lt;/a&gt; and crawl away (If that's even a word).&lt;/p&gt;

&lt;p&gt;Now I am by no means a lawyer or a trusted source on legal matters, but from what I understand and what other "by every means" more qualified people stated on the web is that it is not necessary to update the year from a legal standpoint. &lt;/p&gt;

&lt;p&gt;Here is what a &lt;a href="https://www.nolo.com/legal-encyclopedia/when-do-you-need-copyright-notice-websites-and-where-do-you-place-it.html#:~:text=the%20%C2%A9%20symbol.-,Year%20of%20Publication,many%20websites%20are%20updated%20daily."&gt;nolo&lt;/a&gt; had to say about this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;... The copyright notice must also state the year the work was published. It has yet to be decided exactly when a website is "published" for copyright purposes, since many websites are updated daily. You should assume that any website that can be accessed has been "published" as soon as it launches, and include a copyright notice on it to reflect the original date.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But it also states that after substantial changes to your website the copyright year should reflect the year of publication of those changes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;However, if an update contains a substantial amount of new material, it is considered to be a separate work of authorship in its own right. The notice for such a derivative work should contain the date the new work was published.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How you quantify "substantial changes" remains a mystery, though. Some other sources claim that having the original publication date might deter infringement of your website content. &lt;/p&gt;

&lt;p&gt;Now here is my counterargument: Big companies whose products can be only described as living creatures, don't follow such conventions. Facebook, for instance, who btw. has a massive legal team and literally billions at stake has the following copyright text(as of the time of writing) :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AFpTdxf4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1xa3z7thwn8wa87rrukp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AFpTdxf4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1xa3z7thwn8wa87rrukp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This blogpost might feel like a rant (which it definitely is !), but really people this problem could be solved by a one liner in almost all languages ! On a final note: &lt;strong&gt;GET YOUR COPYRIGHT YEARS IN ORDER !&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gwrinAlf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dv778a8hymjb4lch60tx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gwrinAlf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dv778a8hymjb4lch60tx.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you enjoyed reading this like, share and/or leave a comment. Feedback is always welcome !&lt;/p&gt;

&lt;p&gt;Live long and prosper 🖖 &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>discuss</category>
      <category>writing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Polyfills - What are they ?</title>
      <dc:creator>Issam Mani</dc:creator>
      <pubDate>Fri, 12 Feb 2021 13:35:10 +0000</pubDate>
      <link>https://dev.to/issammani/polyfills-what-are-they-2ha5</link>
      <guid>https://dev.to/issammani/polyfills-what-are-they-2ha5</guid>
      <description>&lt;p&gt;The web is full of weird terminology, that can be especially daunting for newcomers. The idea behind this blog post and ( hopefully 🤞 ) upcoming blog posts is to demistify "fancy" terms. In this article we will discuss polyfills.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  In plain english
&lt;/h1&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Polyfills are &lt;strong&gt;pieces of code&lt;/strong&gt; that aim to make new features available on browsers ( or JS environments in general ) that don't or won't support said features. Two things to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not all features are polyfillable ( new syntactic features cannot be polyfilled e.g. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"&gt;spread syntax(...)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A polyfill only runs, when the feature is missing. Otherwise it should use the native implementation.&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  A brief history...
&lt;/h1&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
The word polyfill was initially introduced [ coined and popularized] by &lt;a href="https://remysharp.com/2010/10/08/what-is-a-polyfill/"&gt;Remy Sharp&lt;/a&gt; in 2009. The word itself originates from the name Polyfilla, a british product used to fill cracks and holes in walls.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Polyfilla is a UK product known as Spackling Paste in the US. With that in mind: think of the browsers as a wall with cracks in it. These polyfills help smooth out the cracks and give us a nice smooth wall of browsers to work with.&lt;/p&gt;

&lt;p&gt;-- &lt;em&gt;Remy Sharp&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Enough history. I said brief, didn't I !&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Polyfills vs Transpilers
&lt;/h1&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Before digging any deeper, let's try to make the difference between the terms &lt;strong&gt;&lt;em&gt;Polyfill&lt;/em&gt;&lt;/strong&gt; and  &lt;strong&gt;&lt;em&gt;Transpiler&lt;/em&gt;&lt;/strong&gt; clear.&lt;/p&gt;

&lt;p&gt;Remember how I said there is no way to polyfill new js syntax. Well a transpiler ( transformer + compiler ) does just that. &lt;/p&gt;

&lt;p&gt;It transforms new syntax into equivalent old syntax that is supported by old browsers. So unlike a polyfill, the code you write is transpiled into alternate code, that would eventually run in the browser.&lt;/p&gt;

&lt;p&gt;Keep in mind that a transpiler like babel will use, depending on your target browsers, underneath the hood polyfills to support new features. &lt;/p&gt;

&lt;p&gt;If you are still unsure about the difference, here is an &lt;a href="https://stackoverflow.com/a/48149493"&gt;SO&lt;/a&gt; response that goes into a bit more detail.&lt;/p&gt;
&lt;h1&gt;
  
  
  Let's write our own polyfill
&lt;/h1&gt;

&lt;p&gt;All right, let's dig in. As I mentioned before a polyfill is just a piece of code, that aims to make some functionality available across all browsers. Usually a good polyfill will check if the target feature already is supported in the browser. If so do nothing da! Otherwise use the available APIs to mimic the behavior of this new feature.&lt;/p&gt;
&lt;h2&gt;
  
  
  JS : &lt;code&gt;Element.closest(selectorList)&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href=""&gt;MDN&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;&lt;code&gt;closest()&lt;/code&gt;&lt;/strong&gt; method traverses the &lt;code&gt;Element&lt;/code&gt; and its parents (heading toward the document root) until it finds a node that matches the provided selector string. Will return itself or the matching ancestor. If no such element exists, it returns &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So basically given an HTML Element the &lt;strong&gt;&lt;code&gt;closest()&lt;/code&gt;&lt;/strong&gt; method returns the closest element in the elements tree that matches at least one of the selectors in the selectorList.&lt;/p&gt;

&lt;p&gt;Assume we have the following HTML DOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;...
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"level-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"level-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"level-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; Polyfills are awesome 🎉 &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paragraph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns &amp;lt;div class="level-1"&amp;gt;...&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-1, .level-2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns &amp;lt;div class="level-2"&amp;gt;...&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns paragrah itself&lt;/span&gt;
&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-bla&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All right ! Now that we know how this function works , we can start implementing.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
👋 &lt;strong&gt;Beginner's Tip&lt;/strong&gt;: This is a good time to open &lt;a href="https://codepen.io/pen/"&gt;codepen&lt;/a&gt; and start experimenting.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Let's think about the problem for a second (or more). We need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A way to traverse the DOM upwards.&lt;/li&gt;
&lt;li&gt;To check if element matches the selectorList.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, let's talk solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A way to traverse the DOM upwards *=&amp;gt; use a while loop and the &lt;a href=""&gt;&lt;code&gt;.parentElement&lt;/code&gt;&lt;/a&gt; prop.&lt;/li&gt;
&lt;li&gt;To check if element matches the selectorList &lt;em&gt;=&amp;gt; use the &lt;a href=""&gt;&lt;code&gt;.matches()&lt;/code&gt;&lt;/a&gt; method&lt;/em&gt;.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;closest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectorList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorList&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So in the snippet above, we are defining a function that takes two arguments: &lt;code&gt;element&lt;/code&gt; and &lt;code&gt;selectorList&lt;/code&gt;. Then we are looping until one of two things happen: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;element&lt;/code&gt; is null, and therefore we have reached the root element.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;element.matches(selectorList)&lt;/code&gt; returns true, and therefore we found the closest element that matches our &lt;code&gt;selectorList&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can check that this beahves the same way on our previous test set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paragraph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns &amp;lt;div class="level-1"&amp;gt;...&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-1, .level-2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns &amp;lt;div class="level-2"&amp;gt;...&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns paragrah itself&lt;/span&gt;
&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.level-bla&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Returns null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step is to add the function to the Element's &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes"&gt;&lt;code&gt;prototype&lt;/code&gt;&lt;/a&gt;, so that it's available to all instances of the &lt;code&gt;Element&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorList&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One last detail, is that we would rather prefer if our polyfill somehow adds this function to the prototype only if the browser doesn't support it. In other words, we would rather use the browser's native implementation if it's available. A simple if will do !&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorList&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
✨ &lt;strong&gt;NOTE:&lt;/strong&gt; This is by no means a production-ready polyfill. For simplicity I assumed a lot of things. A production-ready polyfill would also account for the fact that &lt;code&gt;.matches()&lt;/code&gt; may not exist and also check different browser vendor prefixes. A more complete version can be found &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  CSS: &lt;code&gt;:blank&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;As of the time of writing the &lt;code&gt;:blank&lt;/code&gt; pseudo-class has very &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:blank"&gt;low&lt;/a&gt; support . In this section we will try to write a rough polyfill (not complete by any means) just to demonstrate the idea of polyfilling CSS functionality.&lt;/p&gt;

&lt;p&gt;Again I will quote the MDN definition ( as one normally does ! ) : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The :blank CSS pseudo-class selects empty user input elements (e.g. &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So using the &lt;code&gt;:blank&lt;/code&gt; pseudo-class will look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:blank&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="nd"&gt;:blank&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
✨ &lt;strong&gt;NOTE1:&lt;/strong&gt; Since this is a syntactic proprety of CSS using &lt;code&gt;textarea:blank&lt;/code&gt; will be ruled out as an invalid selector by the CSS Parser. So instead we will use &lt;code&gt;textarea[blank]&lt;/code&gt;. Just keep in mind that in the rest of this post I will use &lt;code&gt;:blank&lt;/code&gt; and &lt;code&gt;[blank]&lt;/code&gt; interchangeably.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
✨ &lt;strong&gt;NOTE2:&lt;/strong&gt; This is actually what &lt;a href="https://github.com/csstools/css-blank-pseudo/blob/HEAD/README-POSTCSS.md"&gt;PostCSS&lt;/a&gt; does underneath the hood. It replaces all occurences of &lt;code&gt;:blank&lt;/code&gt; with &lt;code&gt;[blank]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Let's think about how we can achieve this. We need :&lt;br&gt;
&lt;strong&gt;1.&lt;/strong&gt; Some way to access our stylesheet(s).&lt;br&gt;
&lt;strong&gt;2.&lt;/strong&gt; Detect selectors of the form &lt;code&gt;selector[blank]&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;3.&lt;/strong&gt; Bind our the blank pseudo-class to the selected elements.&lt;br&gt;
&lt;strong&gt;4.&lt;/strong&gt; Update styles when value of input is changed.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
👋 &lt;strong&gt;Beginner's Tip&lt;/strong&gt;: This is a good time to open &lt;a href="https://codepen.io/pen/"&gt;codepen&lt;/a&gt; and start experimenting. &lt;br&gt;
&lt;/p&gt;

&lt;p&gt;These are our requirements. Let's talk about how we can tackle each and everyone:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Some way to access our stylesheet &lt;strong&gt;=&amp;gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model"&gt;&lt;code&gt;CCSOM&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;2.&lt;/strong&gt; Detect &lt;code&gt;:blank&lt;/code&gt; function &lt;strong&gt;=&amp;gt; use a regex&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;3.&lt;/strong&gt; Bind our the blank pseudo-class to the selected elements &lt;strong&gt;=&amp;gt; Add an attribute to the selected inputs&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;4.&lt;/strong&gt; Update the value of the state of the input when the the value is changed via JS &lt;strong&gt;=&amp;gt; listen for the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event"&gt;&lt;code&gt;input event&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Access our stylesheets
&lt;/h3&gt;

&lt;p&gt;First we need to access our CSS Stylesheets. We do so by using CCSOM, specifically by accessing the &lt;code&gt;styleSheets&lt;/code&gt; prop on the document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;  &lt;span class="nx"&gt;styleSheet&lt;/span&gt;  &lt;span class="k"&gt;of&lt;/span&gt;  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;  &lt;span class="nx"&gt;cssRule&lt;/span&gt;  &lt;span class="k"&gt;of&lt;/span&gt;  &lt;span class="nx"&gt;styleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cssRule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Prints each css rule in our stylesheets&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CSSRule"&gt;&lt;code&gt;CSSRule&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Locate selectors with &lt;code&gt;:blank&lt;/code&gt; pseudo-class
&lt;/h3&gt;

&lt;p&gt;Now that we have access to all the CSS rules we can check if any of them have the &lt;code&gt;:blank&lt;/code&gt; pseudo-class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blankRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)\[&lt;/span&gt;&lt;span class="sr"&gt;blank&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;  &lt;span class="nx"&gt;styleSheet&lt;/span&gt;  &lt;span class="k"&gt;of&lt;/span&gt;  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;  &lt;span class="nx"&gt;cssRule&lt;/span&gt;  &lt;span class="k"&gt;of&lt;/span&gt;  &lt;span class="nx"&gt;styleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cssRule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blankRegex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);}&lt;/span&gt; &lt;span class="c1"&gt;// Prints matched selector name i.e input, textarea without the [blank]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
🛑 Refactoring detour&lt;br&gt;
Let's try to refactor our code so that it doesn't get messy.&lt;br&gt;
Let's start by defining a function that's responsible for returning an array of selectors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extractBlankSelectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blankRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)\[&lt;/span&gt;&lt;span class="sr"&gt;blank&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;// Returns an array of of all CSSRules&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cssRules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleSheet&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;styleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="c1"&gt;// Returns an array with our desired selectors&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blankSelectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cssRule&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cssRule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorText&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blankRegex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blankRegex&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;blankSelectors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I used a functional approach instead of using for loops as before, but you can achieve the same with the nested for loops. If this looks weird or confusing to you here a nice &lt;a href="https://opensource.com/article/17/6/functional-javascript"&gt;article&lt;/a&gt; talking about this. Also feel free to ask in the comments section.&lt;/p&gt;

&lt;p&gt;🛑Refactoring detour end&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3,4. Bind our the blank pseudo-class to the selected elements and watch for change !
&lt;/h3&gt;

&lt;p&gt;Now that we have access to the the desired selectors via &lt;code&gt;extractBlankSelectors&lt;/code&gt; we can easily select and add attributes to our target elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;....&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bindBlankElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Select all elements from DOM that match our SelectorList&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractBlankSelectors&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Add blank attribute if value is empty&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Attach an input event listener&lt;/span&gt;
        &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initially we select all the elements returned from &lt;code&gt;extractBlankSelectors&lt;/code&gt;. Then for each one of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add blank attribute if the value is empty.&lt;/li&gt;
&lt;li&gt;Attach an input event listener.
On eah input the callback checks wether the input value is empty or not and applies the &lt;code&gt;blank&lt;/code&gt; attribute accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a codepen to try it out live: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/issammani/embed/yLVVWvK?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Et voilà ! We are all done ! &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you can see polyfills are a super important concept, that helped the web move forward and developers use new features without the fear of breaking compatibility. If you enjoyed reading this like, share and/or leave a comment. Feedback is always welcome !&lt;/p&gt;

&lt;p&gt;Live long and prosper 🖖&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills"&gt;A List of cross browser polyfills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://remysharp.com/2010/10/08/what-is-a-polyfill/"&gt;Remy Sharp's original post about polyfills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;A third link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
