<?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: Kai Hao</title>
    <description>The latest articles on DEV Community by Kai Hao (@kevin940726).</description>
    <link>https://dev.to/kevin940726</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%2F90568%2F8ef0599c-0bca-49e9-8f7c-163e2b1f2478.jpeg</url>
      <title>DEV Community: Kai Hao</title>
      <link>https://dev.to/kevin940726</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kevin940726"/>
    <language>en</language>
    <item>
      <title>What it means to be a senior engineer</title>
      <dc:creator>Kai Hao</dc:creator>
      <pubDate>Sat, 20 Jun 2020 06:13:19 +0000</pubDate>
      <link>https://dev.to/kevin940726/what-it-means-to-be-a-senior-engineer-35ng</link>
      <guid>https://dev.to/kevin940726/what-it-means-to-be-a-senior-engineer-35ng</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally posted in &lt;a href="https://kaihao.dev/posts/What-it-means-to-be-a-senior-engineer"&gt;kaihao.dev&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The title is kind of like a clickbait, I always dislike the terms of using senior or junior to describe the job titles. I believe that comparing with each other brings more harm than good. However, I have to admit that sometimes we need some comparison to allow healthy competition, promotion, or just some sense of accomplishment.&lt;/p&gt;

&lt;p&gt;Anyway, what does seniority means? Literally, it means &lt;strong&gt;the rank that you have in a company because of the length of time you have worked there&lt;/strong&gt;, but how do we measure it? At what point should we consider ourselves senior engineers? 2 years of experience? 3 years? 4? Is there any difference between working at a big tech company or a start-up? In my own experience, I have become a senior engineer with only half a year of professional experience. I also know someone whose first-ever job title is already a senior engineer. Clearly it depends on the company policy, but obviously measuring age or years of experience isn't an objective way either.&lt;/p&gt;

&lt;p&gt;Many companies tend to measure the levels of skills of the engineers to decide their seniorities. Becoming senior engineers means that they achieve a level of skills in the industry or the technologies they use. However, every company has different standards of how skillful a senior engineer should be. Do we suddenly become junior engineers after moving to a higher standard company even though we are senior engineers in the previous company? Furthermore, how do we measure one's level of skills? Is a senior engineer guaranteed to be more skillful than a junior engineer in every single aspect? I believe that everyone can be good at something and be bad at another, being good at everything is unrealistic and nearly impossible. The same applies to seniority, personally I believe that a senior engineer shouldn't necessarily be more skillful than a junior engineer. In fact, I've seen a lot of talented junior engineers that are more skillful than some of the senior engineers I know.&lt;/p&gt;

&lt;p&gt;So, what counts? In my humble opinion, the most important trait to be a senior engineer is to &lt;strong&gt;have our own perspective&lt;/strong&gt;. Needless to say, we have to be good at what we're doing in the first place. However, being good is not enough, we also have to have our own views. We should be able to make trade-offs, make difficult decisions, and take the responsibility of the results. Having our own views also isn't enough, sharing them to the other members in the team is what make us different than the junior engineers. Convincing others is no doubt very hard, that's what make us valuable as senior engineers.&lt;/p&gt;

&lt;p&gt;On the other hand, junior engineers often just follow the &lt;em&gt;standards&lt;/em&gt; or &lt;em&gt;guidelines&lt;/em&gt; from others. We can still be very good as junior engineers, if we're following the right path, of course. However, if we want to improve ourselves to a higher level, start follow our own voices. Keep learning and we will find ourselves having our own unique opinions on all the various things we learned. Opinions could be wrong, but that's why we need to keep learning from our failure and grow to be better. Don't be afraid of failing, that's the proof that we're improving.&lt;/p&gt;

&lt;p&gt;Do you agree? What do you think it means to be a senior engineer? Tell me what you think, I would love to learn more :).&lt;/p&gt;

</description>
      <category>thoughts</category>
    </item>
    <item>
      <title>One fun trick to observe elements in realtime without MutationObserver</title>
      <dc:creator>Kai Hao</dc:creator>
      <pubDate>Sat, 14 Mar 2020 09:14:06 +0000</pubDate>
      <link>https://dev.to/kevin940726/one-fun-trick-to-observe-elements-in-realtime-without-mutationobserver-22kj</link>
      <guid>https://dev.to/kevin940726/one-fun-trick-to-observe-elements-in-realtime-without-mutationobserver-22kj</guid>
      <description>&lt;p&gt;Querying elements with selectors is quite intuitive in JavaScript. &lt;code&gt;querySelector&lt;/code&gt; and &lt;code&gt;querySelectorAll&lt;/code&gt; are fast and reliable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;queryElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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;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;selector&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="nx"&gt;callback&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Use it&lt;/span&gt;
&lt;span class="nx"&gt;queryElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-target]&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="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;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px solid red&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/ihvmy?module=%2Fsrc%2Findex.js"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pzpI10jk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codesandbox.io/static/img/play-codesandbox.svg" alt="Try it on CodeSandbox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if we want to be notified when there's a new element appears on the page? Both &lt;code&gt;querySelector&lt;/code&gt; and &lt;code&gt;querySelectorAll&lt;/code&gt; are one-off imperative commands that won't catch elements added afterward. We have to come up with another method.&lt;/p&gt;

&lt;p&gt;Give it a minute and think about how you would do it.&lt;/p&gt;

&lt;p&gt;Got it? Don't stop it there, how many methods can you come up with? What if we want to support legacy browsers like IE 9?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;MutationObserver&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The first solution that comes to our minds might be this shiny API: &lt;code&gt;MutationObserver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;MutationObserver&lt;/code&gt; to create an observer to listen to new elements added to the page is quite straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;queryElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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;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;selector&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="nx"&gt;callback&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Call it once to get all the elements already on the page&lt;/span&gt;
  &lt;span class="nx"&gt;queryElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MutationObserver&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;queryElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Listen to any kind of changes that might match the selector&lt;/span&gt;
    &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;childList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;characterData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Listen to every changes inside &amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="na"&gt;subtree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="c1"&gt;// Use it&lt;/span&gt;
&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-target]&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="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;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px solid red&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/xibvs?module=%2Fsrc%2Findex.js"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pzpI10jk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codesandbox.io/static/img/play-codesandbox.svg" alt="Try it on CodeSandbox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that this naive solution is not highly performant, and would potentially cause the callback to be fired on the same element more than once. However, it's performant enough in our case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;According to &lt;a href="https://caniuse.com/#feat=mutationobserver"&gt;Can I Use&lt;/a&gt;, &lt;code&gt;MutationObserver&lt;/code&gt; is supported since IE 11, which is enough in most cases. In fact, in practice, we should just stop here, it's good enough, work's done. But what if? What if, just for fun, we want to support IE 9? One solution would be to use a polyfill for &lt;code&gt;MutationObserver&lt;/code&gt;. That's perfect, but is there any other solution?&lt;/p&gt;

&lt;h2&gt;
  
  
  Animation
&lt;/h2&gt;

&lt;p&gt;Animation? Really? Hell yeah, really!&lt;/p&gt;

&lt;p&gt;I'll pause 3 seconds here to let you think why any of this is related to animation. 3... 2... 1, time's up!&lt;/p&gt;

&lt;p&gt;If you really think about it, you might find that &lt;code&gt;animation&lt;/code&gt; runs as soon as the elements being inserted into the DOM. If we can assign an animation to every element matching the selector, and listen to the event when the animation starts, then we can get ourselves an &lt;code&gt;observe&lt;/code&gt; function without using &lt;code&gt;MutationObserver&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;observer-animation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* We don't actually have to run any animation here, can just leave it blank */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-target&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* We just need minimal time for it to run */&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;observer-animation&lt;/span&gt; &lt;span class="m"&gt;1ms&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;That seems perfect, all we need now is to listen to the event when the animation starts. Luckily, there's an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationstart_event"&gt;&lt;code&gt;animationstart&lt;/code&gt;&lt;/a&gt; event we can listen to. What's better is that this event bubbles up, so that we can just attach our listener to &lt;code&gt;document&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&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;animationstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animationName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;observer-animation&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;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;Let's put them all together and inject the style with JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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;style&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Assign the animation to an unique id to support observing multiple selectors&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`observer-animation-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    @keyframes &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;animationName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; {}

     &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; {
       animation: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;animationName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 1ms;
     }
  `&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;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&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;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;animationstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animationName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;animationName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;span class="c1"&gt;// Use it&lt;/span&gt;
&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-target]&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="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;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px solid red&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://codesandbox.io/s/mnpfo?module=%2Fsrc%2Findex.js"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pzpI10jk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://codesandbox.io/static/img/play-codesandbox.svg" alt="Try it on CodeSandbox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright, this is fun! Right?&lt;/p&gt;

&lt;p&gt;Note that this solution is not necessarily the same as our &lt;code&gt;MutationObserver&lt;/code&gt; approach. For instance, animations will only start when the element is visible, so elements that have &lt;code&gt;display: none&lt;/code&gt; will not fire the event. On the other hand, &lt;code&gt;MutationObserver&lt;/code&gt; will call the callback no matter the element is visible or not. This might be either perfect or painful depends on what you're trying to do.&lt;/p&gt;

&lt;p&gt;You probably won't have to use the tricky animation approach ever, but it also doesn't hurt to learn this simple little trick.&lt;/p&gt;

&lt;p&gt;I want to be clear that I'm not the first one to come up with this approach, but I don't remember where I learned from either. There are already &lt;a href="https://github.com/josh/selector-observer"&gt;several&lt;/a&gt; &lt;a href="https://github.com/rkusa/selector-observer"&gt;npm&lt;/a&gt; &lt;a href="https://github.com/csuwildcat/SelectorListener"&gt;libraries&lt;/a&gt; using both of these approaches. Take a look at them to learn more about how to further optimize the performance.&lt;/p&gt;

</description>
      <category>mutationobserver</category>
      <category>javascript</category>
      <category>observeselector</category>
    </item>
  </channel>
</rss>
