<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>MarchBox (Articles)</title>
  <subtitle>Articles from marchbox.com</subtitle><link href="https://marchbox.com/articles/feed" rel="self"/>
  <link href="https://marchbox.com/"/>
  <icon>https://marchbox.com/favicon.png</icon>
  <updated>2023-08-07T00:00:00-07:00</updated>
  <id>https://marchbox.com/</id>
  <author>
    <name>Zacky Ma</name>
    <email>zacky@marchbox.com</email>
  </author><entry>
    <title>Regina Spektor</title>
    <link href="https://marchbox.com/articles/2023-08/regina-spektor/"/>
    <updated>2023-08-07T00:00:00-07:00</updated>
    <id>https://marchbox.com/articles/2023-08/regina-spektor/</id>
    <content type="html">&lt;p&gt;Last Saturday, we went to our 2nd &lt;a href=&quot;https://reginaspektor.com/&quot;&gt;Regina Spektor&lt;/a&gt; concert this year. We went to see her at Walt Disney Concert Hall in LA back in March, and had a really great time. After we came back home, I saw she was coming to Woodinville, WA, about 3 miles from our house.&lt;/p&gt;
&lt;p&gt;I’ve been liking her since college, when I was still living in Beijing, China. She wasn’t one of my top favorite artists back then. I started to appreciate her a lot more a few years ago, when my husband, who is a music fanatic and can tell you the billboard ranking every year in the past a few decades, started to talk about how she is a storyteller. I normally pay way more attention to the rhythms than the lyrics of a song, especially when the lyrics aren’t even in my mother tongue (Mandarin). So I started to read her lyrics while listening, there’s so much whimsy and wisdom.&lt;/p&gt;
&lt;p&gt;However, her live performance is on a different level. This is her first tour I’ve been to, and usually I go to concerts because of being forced by my husband, I just don’t enjoy having loud sound blast into my ear (hence I always wear AirPods Pro with transparency mode on) and surrounded by overly passionate people (like the person who forces me into this situation). Although, at Walt Disney Concert Hall, because of the amazing acoustics, I didn’t put on my AirPods.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://marchbox.com/articles/2023-08/regina-spektor/disney-concert-hall.jpg&quot; alt=&quot;The Walt Disney Concert Hall from a balcony seat. The seats are in aligned in curves. On the sage, there is a pinao and an electronic keyboard.&quot; /&gt;
  &lt;figcaption&gt;The Walt Disney Concert Hall&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;She was on stage alone, no band, she sometimes sang with no instruments, most time while playing piano, at one time she was singing, playing an electronic keyboard, drumming, and stumping at the same time. She also played one song with a tap dancer and that was so much fun.&lt;/p&gt;
&lt;p&gt;The song &lt;cite&gt;Becoming All Alone&lt;/cite&gt; really touched me,  because the reason we went to LA was to stay with a friend for a week, who lost his husband last year. The 3 of us when to the concert together (and Disneyland After Dark Princess Nite), the lyrics has “I’m becoming all alone again” in its chorus, and I couldn’t help but put myself in the friend’s position (and I think he was crying during that song). But that’s not the only time I was really touched. There are usually 2 things that could bring me tears instantly, acceptance and craftsmanship, and boy did she show her craftsmanship.&lt;/p&gt;
&lt;p&gt;Throughout the show, other than her amazing vocal and piano skills, she was so confident, relaxed, whimsical, playful, interactive, conversational, and just having a good time with herself and with the audience. If she made a mistake, there was no panicking or pretending, just made a quick joke and moved on, like how a friend would sing to you. Everything felt so effortless. She also utilized the Concert Hall’s acoustic, it felt like she was singing to you and telling you all her stories in a small and cozy room with woods burning inside the fireplace (*crack crack crack*).&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://marchbox.com/articles/2023-08/regina-spektor/regina-wa.jpg&quot; alt=&quot;Regina Spektor on stage playing piano. In the background, 8 purple light beams made up 4 “X” shapes.&quot; /&gt;
  &lt;figcaption&gt;Regina Spektor at her Woodinville concert&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Last week the Seattle area had a warm and sunny week, but on Saturday morning, it started to drizzle. First thing she said was Seattle brought the rain, she expected nothing less. But it was a good rain, the concert was at our favorite winery, we were surrounded by grasses and trees, and of course wines. The whole evening felt like an intimate camping trip, with a close friend who’s so good at singing and telling stories.&lt;/p&gt;
&lt;p&gt;I often wish she was a bit more productive, so that I didn’t have to wait for so many years to enjoy another album. But on the other side, that’s her way, the way that brought everything I love about her. I can’t wait to listen to more stories she has to tell. Until then, her songs will keep being my go-to repeating playlist (and my husband just has to deal with that).&lt;/p&gt;
</content>
  </entry><entry>
    <title>Gradient background with transparent borders</title>
    <link href="https://marchbox.com/articles/2023-03/background-origin/"/>
    <updated>2023-03-17T00:00:00-07:00</updated>
    <id>https://marchbox.com/articles/2023-03/background-origin/</id>
    <content type="html">&lt;p&gt;Everybody is asking about how to create gradient borders with transparent backgrounds. But I just had to solve an issue that’s in the opposite situation and learned about &lt;code&gt;background-origin&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;The issue&lt;/h2&gt;
&lt;p&gt;I have an element that has a CSS gradient as a background, adding transparent borders would create something like this:&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://marchbox.com/articles/2023-03/background-origin/example-border-width-2px.jpg&quot; width=&quot;143&quot; height=&quot;67&quot; alt=&quot;A square box with “Hello world” inside. The box has a red-to-blue gradient in the background, but its top and bottom borders also have similar gradients, and its left border is seemingly blue, and the right one is seemingly red.&quot; /&gt;
  &lt;figcaption&gt;
    Example with 2px borders. View details on &lt;a href=&quot;https://codepen.io/marchbox/professor/gOdjpbJ&quot;&gt;CodePen&lt;/a&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Notice the different colors on the borders? Here is the CSS code:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;45deg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; blue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2px solid transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s a bit hard to understand what’s going on. So I bumped up the &lt;code&gt;border-width&lt;/code&gt; to &lt;code&gt;20px&lt;/code&gt;. And now it looks like this:&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://marchbox.com/articles/2023-03/background-origin/example-border-width-20px.jpg&quot; width=&quot;179&quot; height=&quot;103&quot; alt=&quot;A square box with “Hello world” inside. The box’s padding area has a red to blue gradient, its 4 borders (which are 20px thick) and the 4 corners all have similar gradients.&quot; /&gt;
  &lt;figcaption&gt;
    Example with 20px borders. View details on &lt;a href=&quot;https://codepen.io/marchbox/professor/gOdjpbJ&quot;&gt;CodePen&lt;/a&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Now it’s clear, it appears that the gradient background, which is technically a &lt;code&gt;background-image&lt;/code&gt;, is repeating itself. If the borders had colors, they’ll cover up the extra repeats, so normally I wouldn’t notice this. But now I set border colors to be &lt;code&gt;transparent&lt;/code&gt;, I can see the repeats now.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://marchbox.com/articles/2023-03/background-origin/background-repeat.jpg&quot; width=&quot;417&quot; height=&quot;189&quot; alt=&quot;A nine grid, the center box is the original square box that has “Hello world” inside, the other 8 boxes are illustrations of how the background is repeating into the border areas. Sorry, this image is hard to describe with words.&quot; /&gt;
  &lt;figcaption&gt;How the background repeats itself within the border box.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Why this is happening? Now introducing &lt;code&gt;background-origin&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;background-origin&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The CSS &lt;a href=&quot;http://developer.mozilla.org/en-US/docs/Web/CSS/background-origin&quot;&gt;&lt;code&gt;background-origin&lt;/code&gt;&lt;/a&gt; property sets where the background’s top left corner should start. Its value is one of the following keywords (other than the global values like &lt;code&gt;inherit&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;border-box&lt;/code&gt;: Align the background’s top left corner with the border box.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;padding-box&lt;/code&gt;: Align the background’s top left corner with the padding box. This is the default value, which makes sense, because why would you want to hide part of the background behind the borders?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;content-box&lt;/code&gt;: Align the background’s top left corner with the content box, which means the padding areas won’t get any background.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a CSS property I knew of before but never paid much attention to, until now. After I added &lt;code&gt;background-origin: border-box&lt;/code&gt;, the problem was solved!&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;45deg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; blue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; border-box&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2px solid transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://marchbox.com/articles/2023-03/background-origin/background-origin-border-box.jpg&quot; width=&quot;178&quot; height=&quot;103&quot; alt=&quot;A square box with “Hello world” inside. The box has a red-to-blue gradient in the background, and no more strange gradients on borders, or any visible borders at all.&quot; /&gt;
  &lt;figcaption&gt;Issue fixed, the background gradient run throughout the padding box now.&lt;/figcaption&gt;
&lt;/figure&gt;
</content>
  </entry><entry>
    <title>Using DOMTokenList</title>
    <link href="https://marchbox.com/articles/2023-01/using-domtokenlist/"/>
    <updated>2023-01-04T00:00:00-07:00</updated>
    <id>https://marchbox.com/articles/2023-01/using-domtokenlist/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList&quot;&gt;&lt;code&gt;DOMTokenList&lt;/code&gt;&lt;/a&gt; is a built-in DOM interface that represents a set of string tokens. If you are familiar with &lt;code&gt;classList&lt;/code&gt;, you are already familiar with it. In a recent project, I wanted to make a custom element property as a &lt;code&gt;DOMTokenList&lt;/code&gt;, here’s what I learned.&lt;/p&gt;
&lt;h2&gt;Why use &lt;code&gt;DOMTokenList&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;Take the &lt;code&gt;class&lt;/code&gt; attribute as an example, its value is a list of space-separated strings. If you want to add new classes, it’s relatively easy, but don’t forget to check if the new class already exists. And if you were to remove a class or replace one with another, it’ll involve more string manipulation or even regular expressions. But with the &lt;code&gt;classList&lt;/code&gt; property, which is a reflection of the &lt;code&gt;class&lt;/code&gt; attribute’s value, it’s much easier to change the class list, you can use methods like &lt;code&gt;add()&lt;/code&gt;, &lt;code&gt;remove()&lt;/code&gt;, &lt;code&gt;replace()&lt;/code&gt;, &lt;code&gt;toggle()&lt;/code&gt;, etc, you can also access individual classes with &lt;code&gt;item()&lt;/code&gt; method or the bracket notation (e.g., &lt;code&gt;classList[0]&lt;/code&gt;). In summary, a &lt;code&gt;DOMTokenList&lt;/code&gt; takes a list of space-separated strings and makes it structural, and any updates on the structure will be reflected in the original list of strings.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/marchbox/intl-elements&quot;&gt;&lt;code&gt;intl-elements&lt;/code&gt;&lt;/a&gt; is the project I’ve been working on, I won’t go into details of the project, that’ll be articles for other days. But in short, it’s a collection of custom elements that makes it easy to use the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl&quot;&gt;&lt;code&gt;Intl&lt;/code&gt; API&lt;/a&gt; declaratively. One of the key features of this library is for component users to pass in a list of locales to the custom elements, so that they can use these locales with &lt;code&gt;Intl&lt;/code&gt; APIs to format strings. The attribute to pass in the locale list is &lt;code&gt;locales&lt;/code&gt;, and I thought it would be nice to create a &lt;code&gt;localeList&lt;/code&gt; property as a &lt;code&gt;DOMTokenList&lt;/code&gt; so that authors can easily change the locale list, just like how &lt;code&gt;class&lt;/code&gt; attribute and &lt;code&gt;classList&lt;/code&gt; property work.&lt;/p&gt;
&lt;h2&gt;Implementing &lt;code&gt;DOMTokenList&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;If you type “DOMTokenList” in a browser developer console, you can see the interface is exposed in the global context. But if you try to call it or create an instance with the &lt;code&gt;new&lt;/code&gt; operator, browsers will throw &lt;code&gt;TypeError: Illegal constructor&lt;/code&gt;. This is similar to the &lt;code&gt;CustomElementRegistry&lt;/code&gt; interface. Because both are interfaces, not classes, you can’t instantiate them. However, browsers exposes &lt;code&gt;window.customElements&lt;/code&gt; as an implementation of the &lt;code&gt;CustomElementRegistry&lt;/code&gt; interface, so that developers can use it directly, e.g. &lt;code&gt;customElements.define()&lt;/code&gt;. For &lt;code&gt;DOMTokenList&lt;/code&gt;, there’s no such existing implementation in the global context. So I thought I could just implement one myself since it doesn’t seem to be very complicated. If you are interested in the implementation, here is the &lt;a href=&quot;https://github.com/marchbox/intl-elements/blob/12e85bebdc6bec2a7a87d7fba64b92b8437f75f6/src/utils/locale-list.ts&quot;&gt;source code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the most part, the implementation was straightforward, I created a private property &lt;code&gt;#list&lt;/code&gt; to store the actual locale list as an &lt;code&gt;Array&lt;/code&gt;, and did some string parsing and manipulation to implement methods like &lt;code&gt;add()&lt;/code&gt;, &lt;code&gt;remove()&lt;/code&gt;, &lt;code&gt;replace()&lt;/code&gt;, &lt;code&gt;toggle()&lt;/code&gt;, &lt;code&gt;entries()&lt;/code&gt;, &lt;code&gt;item()&lt;/code&gt;, &lt;code&gt;values()&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;To inform the custom elements that the list has been updated, I added a method, &lt;code&gt;onChange()&lt;/code&gt;, so custom elements can call it and pass in callback functions, similar to how &lt;code&gt;addEventListener()&lt;/code&gt; works. Any list-changing methods will execute all the callback functions so that the custom elements can update their internal states.&lt;/p&gt;
&lt;p&gt;So far it’s all good, until I was stuck on how to allow accessing list items via the bracket notation, e.g. &lt;code&gt;myElement.localeList[1]&lt;/code&gt;. I ended up looping through the private property, &lt;code&gt;#list&lt;/code&gt;, and adding indexed getters (accessing list items is read-only):&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;#list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;el&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defineProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;configurable&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; el&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And inside list changing methods like &lt;code&gt;add()&lt;/code&gt;, I had to first clear out all these getters and set them again, the clearing looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;#list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defineProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This implementation worked, but it didn’t feel right. It felt like over-engineered and fragile, and when I was trying to print out an element’s &lt;code&gt;localeList&lt;/code&gt; in a browser developer console, the output looked messy, not as clean as a &lt;code&gt;classList&lt;/code&gt; would. That’s when I found &lt;a href=&quot;https://stackoverflow.com/a/29656169&quot;&gt;this StackOverflow answer&lt;/a&gt;, suggesting to just using a &lt;code&gt;classList&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Using &lt;code&gt;classList&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;On the high level, the idea is to create an HTML element without connecting it to &lt;code&gt;document&lt;/code&gt;, and use its &lt;code&gt;classList&lt;/code&gt; as the &lt;code&gt;localeList&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First, I created a function for creating the &lt;code&gt;localeList&lt;/code&gt; in custom elements:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLocaleList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;initialValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hostingElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;div&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; localeList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hostingElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  localeList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; initialValue &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; observer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; onChange &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;function&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    observer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MutationObserver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    observer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;observe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hostingElement&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;attributeFilter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;class&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; localeList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In a custom element definition, I could call this function like so:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyElement&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTMLElement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  #localeList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;localeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;#localeList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;connectedCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;#localeList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLocaleList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;locales&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;#localeList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// And maybe re-render the element’s content&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// based on the new locales.&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since I created a &lt;code&gt;MutationObserver&lt;/code&gt; during the &lt;code&gt;localeList&lt;/code&gt; creation, it would be a good idea to disconnect the observer when the custom element is disconnected (removed) from the DOM. So I added a &lt;code&gt;__destroy__()&lt;/code&gt; method, the underlines are just to mark the method as special since it’s only intended to be used inside the custom elements, not by custom element users.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLocaleList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;initialValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defineProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;localeList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;__destroy__&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      observer&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;disconnect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then I can call it in the custom element’s &lt;code&gt;disconnectedCallback()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyElement&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTMLElement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;disconnectedCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;#localeList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;__destroy__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Last but not least, since the items of a locale list should be valid language tags, I should implement &lt;code&gt;DOMTokenList&lt;/code&gt;’s &lt;code&gt;supports()&lt;/code&gt; method. A &lt;code&gt;localeList&lt;/code&gt; belongs to a custom element, which is designed for a particular &lt;code&gt;Intl&lt;/code&gt; API, and each &lt;code&gt;Intl&lt;/code&gt; API has a &lt;code&gt;supportedLocalesOf()&lt;/code&gt; method to check support. Hence, I need to know which &lt;code&gt;Intl&lt;/code&gt; API when creating the locale list.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLocaleList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;intl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; initialValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defineProperties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&#39;supports&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function-variable function&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;supportedLocalesOf&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; intl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; intl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;supportedLocalesOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;locale&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&#39;__destroy__&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now custom element users can check if a locale is supported by the custom element’s internal &lt;code&gt;Intl&lt;/code&gt; object:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;localeList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;supports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;es-JP&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  myElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;localeList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;es-JP&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  myElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;localeList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;es&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that I could also use other &lt;code&gt;DOMTokenList&lt;/code&gt;, like &lt;code&gt;part&lt;/code&gt;. But &lt;code&gt;classList&lt;/code&gt; has much better cross-browser support. Also, unlike &lt;code&gt;relList&lt;/code&gt;, it doesn’t define the &lt;code&gt;supports()&lt;/code&gt; method, so I don’t have to override any built-in functionality to add &lt;code&gt;supports()&lt;/code&gt; to &lt;code&gt;localeList&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you are interested in the new implementation, &lt;a href=&quot;https://github.com/marchbox/intl-elements/blob/697a56cdb4b70995e8357ee237d83a7029b455e3/src/utils/locale-list.ts&quot;&gt;here is the source code&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I think &lt;code&gt;DOMTokenList&lt;/code&gt; is a very useful interface, especially for custom elements. When developers use our custom elements, they should feel familiar with the APIs like writing HTML code, and making some custom element properties as &lt;code&gt;DOMTokenList&lt;/code&gt; would help with that. I wish we could get a better way to create &lt;code&gt;DOMTokenList&lt;/code&gt;s in the future, maybe something like &lt;code&gt;element.createDOMTokenList()&lt;/code&gt;?&lt;/p&gt;
</content>
  </entry><entry>
    <title>Generate letter-based default avatars in JavaScript</title>
    <link href="https://marchbox.com/articles/2022-07/letter-based-avatars-in-js/"/>
    <updated>2022-07-23T00:00:00-07:00</updated>
    <id>https://marchbox.com/articles/2022-07/letter-based-avatars-in-js/</id>
    <content type="html">&lt;p&gt;Many websites take the first letters from a user’s names to generate their default avatar. It is similar to &lt;a href=&quot;https://en.wikipedia.org/wiki/Monogram&quot;&gt;monograms&lt;/a&gt;. If you have to achieve this in JavaScript, I found using Unicode property escapes Regular Expressions is the easiest.&lt;/p&gt;
&lt;p&gt;I recently worked on a React and GraphQL based project. In our project, we asked users to set their display names, but they don’t have to use their real names, it’s a single text field with a limit of 30 characters.&lt;/p&gt;
&lt;p&gt;Based on the product specification, a user’s default avatar, if they haven’t uploaded an image, should be the first character of their display name contained in a circle with a background color.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://marchbox.com/articles/2022-07/letter-based-avatars-in-js/avatar-example.png&quot; alt=&quot;A circle with a light to darker blue gradient background, and a letter “A” in the center.&quot; width=&quot;96&quot; height=&quot;96&quot; /&gt;
  &lt;figcaption&gt;An example avatar.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The chosen character must be one that is commonly used as a “letter” in any given language. For example, a Latin letter like “A”, a Chinese character like “&lt;span lang=&quot;“zh-Hans”&quot;&gt;赵&lt;/span&gt;”. But it shouldn’t be an emoji, a symbol, or punctuation. For example, if your display name is “🍣~Sushi Lover~”, your default avatar should display a letter “S”.&lt;/p&gt;
&lt;p&gt;Because this is about text processing, I thought I should explore my options with Regular Expression first. And luckily, I found &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes&quot;&gt;Unicode property escapes&lt;/a&gt;. Here is my code:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;genAvatar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Match General_Category=Letter&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; match &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&#92;p{L}&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;u&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;match &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; match&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It has &lt;a href=&quot;https://caniuse.com/mdn-javascript_builtins_regexp_property_escapes&quot;&gt;great browser support&lt;/a&gt;. Here are a few things worth noting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Because it’s an escape, you do need that &lt;code&gt;&#92;p{..}&lt;/code&gt;. You can also use &lt;code&gt;&#92;P{..}&lt;/code&gt; for negation.&lt;/li&gt;
&lt;li&gt;The Regular Expression in my code is a shorthand of &lt;code&gt;/&#92;p{General_Category=Letter}/&lt;/code&gt;, because you don’t need property name (&lt;code&gt;General_Category&lt;/code&gt;) for General categories, and &lt;code&gt;Letter&lt;/code&gt; can be shortened to &lt;code&gt;L&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You need that &lt;code&gt;u&lt;/code&gt; flag to tell JavaScript that you are trying to match based on Unicode code points.&lt;/li&gt;
&lt;li&gt;Based on my reading and testing, this Regular Expression seems to cover all cases. I tested in Latin script (with and without accent), Simplified Chinese, Japanese (Hiragana), Arabic, Hebrew, and Korean (Hangul). I may have missed some cases, I’ll update the article if I found any.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can do so much more with it. It’s particularly useful when you need to handle non-Latin cases. Since this is all new to me, I’m gonna stop here before I spread any misinformation. But I recommend to dig into the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes&quot;&gt;MDN article&lt;/a&gt; and those linked standard pages if you want to do more research.&lt;/p&gt;
</content>
  </entry><entry>
    <title>HTML isn’t GUI</title>
    <link href="https://marchbox.com/articles/2022-06/html-isnt-gui/"/>
    <updated>2022-06-04T00:00:00-07:00</updated>
    <id>https://marchbox.com/articles/2022-06/html-isnt-gui/</id>
    <content type="html">&lt;p&gt;Many web developers take design mockups a bit too literally–thinking the rendered webpages should visually match the mockups. While it’s crucial to carry the visual design over to the coded webpages, there’s much more to our works than just making visual copies of mockups. We develop user interfaces that can be understood and interacted with by different people with different tools.&lt;/p&gt;
&lt;p&gt;The web democratized information access and publishing. As web developers, we should hold the responsibility to maintain this openness, and make our webpages as inclusive, understandable, and usable by as many people in the world as possible.&lt;/p&gt;
&lt;p&gt;Webpages are often accessed by using graphical web browsers like Safari and Chrome. But there are also screen readers like Jaws and VoiceOver for visually impaired users, and they interpret the webpages into audio instead of visuals. Therefore, when developing a webpage, we shouldn’t just focus on its graphical user interface (GUI) but also on the more abstract and content-focused user interface. The content-focused interface is output agnostic, users can consume the content visually, audibly, or even kinesthetically.&lt;/p&gt;
&lt;h2&gt;Mockup to content structure&lt;/h2&gt;
&lt;p&gt;When we develop a website, we typically think about the site structure first: How many pages? What’s the content hierarchy? How does the navigation work? What content is shared across all pages? And so on. We should also do the same for individual webpages.&lt;/p&gt;
&lt;p&gt;When I’m handed over a wireframe or a visual design mockup, the first thing I do is to figure out the content structure: What’s the title of the page (&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;)? What are the sections and their headings (&lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;-&lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt;)? What are the relationships between different sections? Where are the header and footer content boundaries? Where is the navigation? What’s the main content of the page? And so on.&lt;/p&gt;
&lt;p&gt;After I get an overall grasp of the content structure, I’ll start writing HTML code without thinking too much about how to achieve the visual design from the mockup because that’s mainly CSS’s job at a later time. HTML is essential for all the different software that people use to understand the content on your webpages, it’s important to keep the HTML code content-focused: use semantic markups; minimize markups for decorative purposes; use proper &lt;code&gt;role&lt;/code&gt; and &lt;code&gt;aria-*&lt;/code&gt; attributes if necessary; add text-based content to visual assets like images and videos as alternative interface.&lt;/p&gt;
&lt;p&gt;When you code HTML, don’t think about the mockups, keep a tree-shape structure that represents the content in your mind. Eventually, when you form a tree in your mind instinctually, you can repeat the process of mockup to content structure to HTML to CSS for each page section, multiple times for the same page.&lt;/p&gt;
&lt;h2&gt;Separation of concerns&lt;/h2&gt;
&lt;p&gt;Many UI frameworks consider a webpage as a collection of UI elements, and to maximize their frameworks’ flexibility, many have components like &lt;code&gt;&amp;lt;Text&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Spacer&amp;gt;&lt;/code&gt; (but no &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; and GIF needed anymore, if you know what I mean):&lt;/p&gt;
&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;variant&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;h1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;semibold&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Heading 1&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Spacer&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;vertical&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;12&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Spacer&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;variant&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;body2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  Lorem ipsum &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bold&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;dolor sit&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; amet.
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code usually outputs the following HTML code:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;type-h1 type-semibold&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Heading 1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;spacer-v-12&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;type-body2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  Lorem ipsum &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;type-bold&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;dolor sit&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; amet.
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem with this mindset is that you are only developing for visual users. The code could confuse visually impaired users because &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;’s don’t have semantic meanings by default, a spacer doesn’t mean anything in the auditory context, and &lt;code&gt;&amp;lt;span class=&amp;quot;type-bold&amp;quot;&amp;gt;&lt;/code&gt; doesn’t convey any importance of the marked content. This mindset also mixes document structure with presentation, resulting in maintenance issues down the road.&lt;/p&gt;
&lt;p&gt;When we transitioned away from table layouts, the main idea was a separation of concerns: HTML handles the content structure, CSS handles the presentation, and JavaScript handles the behavior. The separation keeps HTML as a clean content-focused interface, and it makes many design changes easy to implement (by &lt;a href=&quot;http://www.csszengarden.com/&quot; title=&quot;CSS Zen Garden&quot;&gt;modifying CSS only&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Web development is all about making the design accessible to everyone. Use your technical expertise to enhance the design mockups and make them work beyond the visual context. If you haven’t, I highly recommend reading (or re-read) &lt;a href=&quot;https://alistapart.com/article/dao&quot;&gt;A Dao of Web Design&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry><entry>
    <title>Opening day</title>
    <link href="https://marchbox.com/articles/2022-04/opening-day/"/>
    <updated>2022-04-22T00:00:00-07:00</updated>
    <id>https://marchbox.com/articles/2022-04/opening-day/</id>
    <content type="html">&lt;p&gt;Welcome to my new personal website! It took me quite a while, but I finally finished building the first iteration, and I had so much fun doing it. As the site’s first article, I’ll talk about what I’m planning on posting here.&lt;/p&gt;
&lt;p&gt;The last time I had a blog was almost two decades ago. I was living in China and had just started my career as a web developer. I was eager to learn all the frontend technologies and read many O’Reilly books. So, I was blogging about what I learned, in Chinese. It’s such a shame that I didn’t persist, as I often admire people who’ve kept their blogs for decades.&lt;/p&gt;
&lt;h2&gt;Web design&lt;/h2&gt;
&lt;p&gt;But, better late than never. Two decades later, I’m still a web developer, and I’ve never been more passionate and confident about web development. So naturally, that’s what I’ll be primarily writing about. My focuses on web development are accessibility, semantic HTML, progressive enhancement, performance, maintainability, and localization. I also spend a lot of time thinking about web design, which, in my opinion, is an essential part of our job, because what we code directly impacts users’ lives, understanding and caring design makes us better developers. As a result, I regularly use “web design” and “web development” almost interchangeably – more on this in future articles.&lt;/p&gt;
&lt;h2&gt;Drawings&lt;/h2&gt;
&lt;p&gt;I’ve been doodling since I was two years old. I drew all over my textbooks, even in my notebooks for our weekly writing assignments. I’ve never had proper training. I used to think that allowed me to draw freely. But in the recent years, I hit a wall—I wanted to draw “perfectly” like a professional illustrator, but my lack of training kept dragging me down, I often relied on happy accidents to achieve what I want. Eventually, the frustration built up, I stopped drawing, for years, until last January, when I became aware of my anxiety issues and started to look for solutions. One day, I decided to start drawing something without caring about perfection and polish, I had a blast for about 2 months. You can see all drawings in that series on the &lt;a href=&quot;https://marchbox.com/drawings/&quot;&gt;Drawings page&lt;/a&gt;. I will continue posting some of my old drawings and new ones as I go.&lt;/p&gt;
&lt;h2&gt;Disney&lt;/h2&gt;
&lt;p&gt;I always think I am who I am because of 2 things: my mom and Disney. I grew up in the far west part of mainland China, and the internet wasn’t a thing until I was in high school. Disney was my window to the outside world. My love for Disney has driven me through almost all significant changes in my life. So, it would be impossible for me not to talk about Disney on my personal website.&lt;/p&gt;
&lt;h2&gt;Other things&lt;/h2&gt;
&lt;p&gt;I’ve also developed interests and hobbies in many other things, like linguistics, typography, travel, animations, and so on. I’m using this site to express my thoughts, experiences, and passions. It’s one way of dealing with my anxiety, I can build and write in the ways I want, and it helps me move my focus away from things I can’t control.&lt;/p&gt;
&lt;p&gt;Hope you enjoy the ride.&lt;/p&gt;
</content>
  </entry>
</feed>
