CINXE.COM
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="generator" content="Gatsby 5.14.1"/><meta name="theme-color" content="#f3c868"/><meta data-react-helmet="true" name="description" content="Personal blog about frontend web development, with a focus on accessibility, web components and functional reactive programming."/><meta data-react-helmet="true" property="og:url" content="https://fedknu.com"/><meta data-react-helmet="true" property="og:title" content="fedknu.com"/><meta data-react-helmet="true" name="og:description" content="Personal blog about frontend web development, with a focus on accessibility, web components and functional reactive programming."/><meta data-react-helmet="true" name="twitter:card" content="summary"/><meta data-react-helmet="true" name="twitter:creator" content="@fedknu"/><meta data-react-helmet="true" name="twitter:title" content="fedknu.com"/><meta data-react-helmet="true" name="twitter:description" content="Personal blog about frontend web development, with a focus on accessibility, web components and functional reactive programming."/><style data-href="/styles.243e1163fbfb371fd411.css" data-identity="gatsby-global-css">@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:200;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-ExtraLight.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:200;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-ExtraLightItalic.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:300;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-Light.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:300;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-LightItalic.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:400;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-Regular.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:400;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-RegularItalic.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:500;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-Medium.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:500;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-MediumItalic.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:600;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-SemiBold.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:600;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-SemiBoldItalic.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:700;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-Bold.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:700;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-BoldItalic.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:normal;font-weight:800;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-ExtraBold.woff2) format("woff2")}@font-face{font-family:Atkinson Hyperlegible Next;font-style:italic;font-weight:800;src:url(/fonts/Atkinson-Hyperlegible-Next/AtkinsonHyperlegibleNext-ExtraBoldItalic.woff2) format("woff2")}*,:after,:before{box-sizing:border-box}.dmsbls0{line-height:1.4}.dmsbls0,.dmsbls1{color:#1f2937;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.dmsbls1{font-size:22px;font-weight:300;line-height:1.75}.dmsbls2:focus{border-radius:1px;outline:3px solid #d14;outline-offset:2px}.dmsbls2:focus,.dmsbls2:focus:hover{border-bottom-style:none}.dmsbls3{border-bottom:1px solid #0572e6;color:#0572e6;padding-bottom:1px;text-decoration:none;word-break:break-word}.dmsbls3:hover{border-bottom:3px solid #0572e6}.dmsbls4{clip:rect(0,0,0,0);border-width:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.fc34ni0{margin:24px 0 60px;text-align:center}.fc34ni1{font-weight:600;margin:0 0 10px}.fc34ni2 ol,.fc34ni2 p,.fc34ni2 td,.fc34ni2 th,.fc34ni2 ul{color:#1f2937;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:22px;font-weight:300;line-height:1.75}.fc34ni2 td,.fc34ni2 th{padding:8px;text-align:center}.fc34ni2 th{background-color:#e1e1e1;font-weight:600}.fc34ni2 table{border-collapse:collapse}.fc34ni2 table,.fc34ni2 td,.fc34ni2 th{border:1px solid #526b8d}.fc34ni2 a{border-bottom:1px solid #0572e6;color:#0572e6;padding-bottom:1px;text-decoration:none;word-break:break-word}.fc34ni2 a:hover{border-bottom:3px solid #0572e6}.fc34ni2 a:focus{border-radius:1px;outline:3px solid #d14;outline-offset:2px}.fc34ni2 a:focus,.fc34ni2 a:focus:hover{border-bottom-style:none}.fc34ni2 h1,.fc34ni2 h2,.fc34ni2 h3,.fc34ni2 h4,.fc34ni2 h5,.fc34ni2 h6{color:#1f2937;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-weight:600;line-height:1.4;margin:50px 0 0}.fc34ni2 h1{font-size:32px}.fc34ni2 h2{font-size:26px}.fc34ni2 h3{font-size:22px}.fc34ni2 b,.fc34ni2 strong{font-weight:600}.fc34ni2 blockquote{background-color:#fafafa;border:1px solid #526b8d;box-shadow:8px 8px 0 1px #e1e1e1;margin:48px 96px;padding:16px 24px}.fc34ni2 blockquote p{color:#1f2937;margin:0}.fc34ni2 img{max-width:100%}.fc34ni2 a img{border-bottom-style:none}.fc34ni2 a:hover img{padding:0}.fc34ni2 iframe[src^="https://www.youtube.com"]{display:block;margin:0 auto}.fc34ni2 .gatsby-resp-image-figure,.fc34ni2 p>.gatsby-resp-image-wrapper{margin-bottom:48px;margin-top:48px}.fc34ni2 .gatsby-resp-image-figcaption{color:#1f2937;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;font-weight:300;line-height:1.75;margin-top:8px;text-align:center}.fc34ni2 code,.fc34ni2 kbd,.fc34ni2 pre,.fc34ni2 samp{font-family:SFMono-Medium,SF Mono,Segoe UI Mono,Roboto Mono,Ubuntu Mono,Menlo,Consolas,Courier,monospace}.fc34ni2 code:not([class=grvsc-code]){background-color:rgba(27,31,35,.05);border-radius:3px;color:#d14;font-size:80%;font-weight:400;margin:0;padding:3px 6px;white-space:nowrap}.fc34ni2 a code:not([class=grvsc-code]){color:inherit}.fc34ni2 pre.grvsc-container{line-height:1.75} /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}.px9xea0:not(:last-child){margin-bottom:44px}.px9xea1{font-size:22px;font-weight:400;margin:0}.px9xea2{margin:5px 0 0}._1kjbxuk0{border-radius:3px;color:#fff;display:inline-block;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:13px;line-height:1;padding:4px 5px 2px;text-transform:uppercase;white-space:nowrap}._1kjbxuk1{background-color:#526b8d}._1kjbxuk2{background-color:#0572e6}._1kjbxuk3{background-color:#3d854d}._1kjbxuk4{background-color:#d43900}._1kjbxuk5{background-color:#f9ca5e;color:#4a3712}._1kjbxuk6{background-color:#7659b6}._19o0aq30{margin:0 0 5px}._19o0aq31{color:#526b8d;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;margin-right:10px;text-transform:uppercase}.a0zrw70{align-items:center;background-color:#d14;border-radius:3px;display:inline-flex;height:50px;left:0;margin:8px;padding:0 16px;position:fixed;top:0;transform:translateY(-58px);z-index:10}.a0zrw70:has(>a:focus){transform:translateY(0)}.a0zrw71{color:#fff;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:18px;font-weight:300;outline-offset:4px}.a0zrw72{margin:0 auto;max-width:1024px;padding:36px 24px 48px}.a0zrw73{background-color:#fafafa;border-bottom:1px solid #e1e1e1}.a0zrw73:before{background-color:#f9ca5e;content:"";display:block;height:3px;width:100%}.a0zrw74{align-items:center;display:flex;font-family:Atkinson Hyperlegible Next,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Noto Sans,Ubuntu,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:18px;justify-content:space-between;line-height:1;overflow-x:scroll;padding:16px 24px}.a0zrw75{color:#344563;text-decoration:none}.a0zrw75:after{background:currentColor;content:"";display:block;height:2px;transition:width .3s;width:0}.a0zrw75:hover:after{width:100%}.a0zrw76:after{background:currentColor;content:"";display:block;height:2px;width:100%}.a0zrw77{align-items:flex-start;display:flex;margin-right:40px}.a0zrw78{height:32px;margin-right:12px}.a0zrw79{white-space:nowrap}.a0zrw7a{font-size:18px;font-weight:600}.a0zrw7b{color:#526b8d;font-size:14px;font-weight:300;margin-top:3px}.a0zrw7c{align-items:center;display:flex;justify-content:flex-end;margin:0;padding-left:0}.a0zrw7d{display:inline-block;list-style-type:none;margin-right:28px}@media screen and (min-width:768px){.a0zrw74{margin:0 auto;max-width:1024px;overflow-x:hidden}}</style><link rel="icon" href="/favicon-32x32.png?v=f062a85faff3c73910999d9a35af60c4" type="image/png"/><link rel="manifest" href="/manifest.webmanifest" crossorigin="anonymous"/><link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png?v=f062a85faff3c73910999d9a35af60c4"/><link rel="alternate" type="application/rss+xml" title="fedknu.com" href="/rss.xml"/><title data-react-helmet="true">fedknu.com</title></head><body><div id="___gatsby"><div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper"><span class="a0zrw70" data-testid="layout-skip-link-container"><a class="a0zrw71" href="#main" data-testid="layout-skip-link">Skip to main content</a></span><header class="a0zrw73"><nav class="a0zrw74"><a aria-current="page" class="a0zrw77 a0zrw75 dmsbls2" data-testid="navigation-logo" href="/"><img class="a0zrw78" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNiAzNiI+PHBhdGggZmlsbD0iIzc3QjI1NSIgZD0iTTM1IDM2di01YzAtMy4zMTQtMi42ODYtNi02LTZIMTNjLTMuMzEzIDAtNiAyLjY4Ni02IDZ2NWgyOHoiLz48cGF0aCBmaWxsPSIjRkZEQzVEIiBkPSJNMTYuNjQgMjUuMTA2YzAgLjg5NCAyLjM2IDEuOTkzIDQuMzYgMS45OTNzNC4zNTktMS4wOTkgNC4zNTktMS45OTJWMjEuMjloLTguNzJ2My44MTZ6Ii8+PHBhdGggZmlsbD0iI0Y5Q0E1NSIgZD0iTTE2LjYzMiAyMi45NzNjMS4yMTYgMS4zNzQgMi43MjQgMS43NDYgNC4zNjQgMS43NDYgMS42MzkgMCAzLjE0Ni0uMzczIDQuMzYzLTEuNzQ2di0zLjQ5MWgtOC43Mjh2My40OTF6Ii8+PHBhdGggZmlsbD0iI0ZGREM1RCIgZD0iTTE0LjQ0NCAxMi45MzZjMCAxLjQ0OC0uNzM0IDIuNjIyLTEuNjM5IDIuNjIycy0xLjYzOS0xLjE3NC0xLjYzOS0yLjYyMi43MzQtMi42MjMgMS42MzktMi42MjNjLjkwNS0uMDAxIDEuNjM5IDEuMTc0IDEuNjM5IDIuNjIzbTE2LjM4OSAwYzAgMS40NDgtLjczMyAyLjYyMi0xLjYzOSAyLjYyMi0uOTA1IDAtMS42MzktMS4xNzQtMS42MzktMi42MjJzLjczMy0yLjYyMyAxLjYzOS0yLjYyM2MuOTA2LS4wMDEgMS42MzkgMS4xNzQgMS42MzkgMi42MjMiLz48cGF0aCBmaWxsPSIjRkZEQzVEIiBkPSJNMTIuNDc3IDEzLjk2YzAtNS41ODkgMy44MTYtMTAuMTIxIDguNTIzLTEwLjEyMXM4LjUyMiA0LjUzMiA4LjUyMiAxMC4xMjFTMjUuNzA3IDI0LjA4MSAyMSAyNC4wODFjLTQuNzA2LS4wMDEtOC41MjMtNC41MzItOC41MjMtMTAuMTIxIi8+PHBhdGggZmlsbD0iI0MxNjk0RiIgZD0iTTIxIDIwLjgwMmMtMi43NTQgMC0zLjYtLjcwNS0zLjc0MS0uODQ4LS4yNTYtLjI1Ni0uMjU2LS42NzEgMC0uOTI3LjI0OC0uMjQ4LjY0Ni0uMjU1LjkwMi0uMDIzLjA1Mi4wMzcuNzIxLjQ4NyAyLjgzOS40ODcgMi4yIDAgMi44MzYtLjQ4NSAyLjg0Mi0uNDkuMjU2LS4yNTUuNjU3LS4yNDMuOTEzLjAxNS4yNTYuMjU2LjI0Mi42ODMtLjAxNC45MzgtLjE0MS4xNDMtLjk4Ny44NDgtMy43NDEuODQ4Ii8+PHBhdGggZmlsbD0iI0ZGQUMzMyIgZD0iTTIxIDBjNS42NDggMCA5LjE3OCA0LjY0OCA5LjE3OCA4LjEyMSAwIDMuNDczLS43MDYgNC44NjMtMS40MTIgMy40NzNsLTEuNDEyLTIuNzc4cy00LjIzNSAwLTUuNjQ3LTEuMzljMCAwIDIuMTE4IDQuMTY4LTIuMTE4IDAgMCAwIC43MDYgMi43NzktMy41My0uNjk0IDAgMC0yLjExOCAxLjM4OS0yLjgyNCA0Ljg2Mi0uMTk2Ljk2NC0xLjQxMiAwLTEuNDEyLTMuNDczQzExLjgyMiA0LjY0OCAxNC42NDYgMCAyMSAwIi8+PHBhdGggZmlsbD0iIzY2MjExMyIgZD0iTTE3IDE0Yy0uNTUgMC0xLS40NS0xLTF2LTFjMC0uNTUuNDUtMSAxLTFzMSAuNDUgMSAxdjFjMCAuNTUtLjQ1IDEtMSAxbTggMGMtLjU1IDAtMS0uNDUtMS0xdi0xYzAtLjU1LjQ1LTEgMS0xczEgLjQ1IDEgMXYxYzAgLjU1LS40NSAxLTEgMSIvPjxwYXRoIGZpbGw9IiNDMTY5NEYiIGQ9Ik0yMS43NSAxNi43NWgtMS41Yy0uNDEzIDAtLjc1LS4zMzctLjc1LS43NXMuMzM3LS43NS43NS0uNzVoMS41Yy40MTMgMCAuNzUuMzM3Ljc1Ljc1cy0uMzM3Ljc1LS43NS43NSIvPjxwYXRoIGZpbGw9IiNFMUU4RUQiIGQ9Ik0zMyAzNWMwIC41NTMtLjQ0NyAxLTEgMUgyMmMtLjU1MyAwLTEtLjQ0Ny0xLTEgMC0uNTUzLjQ0Ny0xIDEtMWgxMGMuNTUzIDAgMSAuNDQ3IDEgMXoiLz48cGF0aCBmaWxsPSIjRTFFOEVEIiBkPSJNMjAuMjQgMjJIMy43NTljLTEuNTI0IDAtMy40NzguNzcxLTIuNDc4IDMuNTMxbDMuMDcyIDguNDc1QzQuMzU0IDM0LjAwNiA0Ljc1IDM2IDcgMzZoMjBsLTQtMTEuMjRjLS40MzgtMS4zMjItMS4yMzUtMi43Ni0yLjc2LTIuNzZ6Ii8+PHBhdGggZmlsbD0iIzk5QUFCNSIgZD0iTTE5LjI0IDIySDIuNzU5Yy0xLjUyNCAwLTMuNDc4Ljc3MS0yLjQ3OCAzLjUzMWwzLjA3MiA4LjQ3NUMzLjM1NCAzNC4wMDYgMy43NSAzNiA2IDM2aDIwbC00LTExLjI0Yy0uNDM4LTEuMzIyLTEuMjM1LTIuNzYtMi43Ni0yLjc2eiIvPjxwYXRoIGZpbGw9IiNFMUU4RUQiIGQ9Ik0xNC4wMTkgMjkuMjgzYy41MjQgMS41NzIuMDk5IDMuMTMtLjk0OSAzLjQ3OS0xLjA0OC4zNS0yLjMyMi0uNjQxLTIuODQ2LTIuMjEzcy0uMDk5LTMuMTMuOTQ5LTMuNDc5YzEuMDQ4LS4zNDkgMi4zMjMuNjQxIDIuODQ2IDIuMjEzek0xOSAyNC43NUgzYy0uNDE0IDAtLjc1LS4zMzYtLjc1LS43NXMuMzM2LS43NS43NS0uNzVoMTZjLjQxNCAwIC43NS4zMzYuNzUuNzVzLS4zMzYuNzUtLjc1Ljc1eiIvPjwvc3ZnPg==" alt="" data-testid="navigation-logo-image"/><span class="a0zrw79" data-testid="navigation-logo-title"><div class="a0zrw7a">F. Kn眉ssel<span class="dmsbls4">: </span></div><div class="a0zrw7b">Frontend Developer</div></span></a><ul class="a0zrw7c"><li class="a0zrw7d"><a class="a0zrw75 dmsbls2" data-testid="layout-navigation-link" href="/about/">About</a></li><li class="a0zrw7d"><a aria-current="page" class="a0zrw75 dmsbls2 a0zrw76" data-testid="layout-navigation-link" href="/">Blog</a></li><li class="a0zrw7d"><a class="a0zrw75 dmsbls2" data-testid="layout-navigation-link" href="/uses/">Uses</a></li><li class="a0zrw7d"><a class="a0zrw75 dmsbls2" data-testid="layout-navigation-link" href="/now/">Now</a></li><li class="a0zrw7d"><a class="a0zrw75 dmsbls2" data-testid="layout-navigation-link" href="/colophon/">Colophon</a></li><li class="a0zrw7d"><a class="a0zrw75 dmsbls2" href="https://github.com/fed" data-testid="layout-navigation-link">GitHub</a></li><li class="a0zrw7d"><a class="a0zrw75 dmsbls2" href="/rss.xml" data-testid="layout-navigation-link">RSS</a></li></ul></nav></header><main class="a0zrw72" id="main" data-testid="layout-content"><h1 class="dmsbls4" data-testid="archive-title">Archive of published blog posts</h1><article class="px9xea0" data-postid="e7caa3e2-296b-5f8e-ad24-9d2c497318e8" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->March 05, 2024<!-- --> under the category <!-- -->Accessibility</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">March 05, 2024</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/links-vs-buttons/"><span class="">Interacting with links and buttons</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">A discussion on the purpose, semantics, states and default behaviours of buttons and links, and how choosing the wrong one can impact accessibility.</p></article><article class="px9xea0" data-postid="37a746fd-9c1e-53e4-bf10-068c191f275e" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->March 12, 2022<!-- --> under the category <!-- -->General</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">March 12, 2022</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/sublimetext-prettier-eslint/"><span class="">Configuring Sublime Text to work with Prettier and ESLint</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Instructions on how to configure Sublime Text to automatically fix errors and format files on save using ESLint and Prettier.</p></article><article class="px9xea0" data-postid="4357aed9-455f-5f5b-9b49-5f81725e9d99" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->April 21, 2020<!-- --> under the category <!-- -->General</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">April 21, 2020</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/jira-search-engine/"><span class="">Jira search engine in your browser</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Instructions on how to configure Chrome to allow searching for Jira tickets from the URL bar.</p></article><article class="px9xea0" data-postid="e5a7f23d-f0ca-5b9f-9f16-11f5cfc4e2fa" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->March 12, 2020<!-- --> under the category <!-- -->General</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">March 12, 2020</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/code-reviewing-checklist/"><span class="">Code reviewing checklist</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Thoughts on what I consider to be important to look out for when doing code reviews.</p></article><article class="px9xea0" data-postid="64be047c-9dda-5230-b3b3-a624e5a6e1a8" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->January 23, 2020<!-- --> under the category <!-- -->Automated Testing</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">January 23, 2020</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/focusing-skipping-tests/"><span class="">Focusing and skipping tests</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Some notes on how to tell your testing framework which tests to run.</p></article><article class="px9xea0" data-postid="15fc5ca9-986e-5f33-81f5-9ff7e0ff0b4a" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->October 19, 2019<!-- --> under the category <!-- -->Accessibility</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">October 19, 2019</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/focusable-elements-macos/"><span class="">Fixing keyboard navigation for MacOS browsers</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Instructions on how to manually enable tabbing through all focusable elements on a page if you are using MacOS.</p></article><article class="px9xea0" data-postid="3637b9b6-919b-54d6-baa4-1704b731663d" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->January 09, 2019<!-- --> under the category <!-- -->Automated Testing</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">January 09, 2019</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/async-testing/"><span class="">Testing asynchronous code</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">A brief intro to the different ways to set up your asynchronous tests and the reason behind it.</p></article><article class="px9xea0" data-postid="37883dc4-4c43-53eb-b003-aa20d263bcb9" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->September 06, 2017<!-- --> under the category <!-- -->DOM & Web APIs</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">September 06, 2017</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/dom-traversal-manipulation/"><span class="">DOM traversal and manipulation</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">A cheatsheet for working with the DOM in Vanilla JS.</p></article><article class="px9xea0" data-postid="308d49e8-aaa4-55b4-9d67-b2629ecd5c3f" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->September 06, 2017<!-- --> under the category <!-- -->JavaScript</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">September 06, 2017</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/getting-clever-with-array-reduce/"><span class="">Getting clever with Array#reduce</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">A handful of rather unconventional yet interesting use cases for reducing arrays.</p></article><article class="px9xea0" data-postid="53c7d789-cde4-531b-9b86-871b38d9a45d" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->August 06, 2017<!-- --> under the category <!-- -->Functional Reactive Programming</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">August 06, 2017</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/simple-observable-implementation/"><span class="">A simple Observable implementation</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Let's write our own Observable interface implementation to understand what's going on under the hood when we work with RxJS.</p></article><article class="px9xea0" data-postid="e963befe-e0c2-55ae-8719-b18e1aba494f" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->August 06, 2017<!-- --> under the category <!-- -->DOM & Web APIs</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">August 06, 2017</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/dom-bom-revisited/"><span class="">DOM & BOM revisited</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Reviewing DOM manipulation and talking to the browser with JavaScript.</p></article><article class="px9xea0" data-postid="1a8d4cd4-c440-511a-95f6-ab1e1696a559" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->March 06, 2017<!-- --> under the category <!-- -->JavaScript</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">March 06, 2017</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/arrays-objects-and-mutations/"><span class="">Arrays, objects and mutations</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Some ideas on how to treat arrays and objects as if they were immutable.</p></article><article class="px9xea0" data-postid="2057978c-e714-5544-a82b-14ca344aa6cb" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->February 01, 2017<!-- --> under the category <!-- -->Declarative UIs</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">February 01, 2017</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/inner-workings-of-redux/"><span class="">A look at the inner workings of Redux</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Let's try to understand what's really going on under the hood when we use Redux by implementing a simplified version of it from scratch.</p></article><article class="px9xea0" data-postid="e6549acb-f697-54c4-8465-c584cfddf35c" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->December 30, 2016<!-- --> under the category <!-- -->JavaScript</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">December 30, 2016</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/making-sense-out-of-context/"><span class="">Making sense out of context</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Learn how the this keyword works, and the different ways in which contexts are bound on function calls.</p></article><article class="px9xea0" data-postid="01b37194-088b-5228-a398-6e14a1ae4fee" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->December 27, 2016<!-- --> under the category <!-- -->Functional Reactive Programming</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">December 27, 2016</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/manipulating-event-streams/"><span class="">Manipulating event streams in Bacon.js</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Here we'll explore how applying transformations to source streams produces new observables.</p></article><article class="px9xea0" data-postid="4a89e425-6d01-56f7-8cc5-6713e7a71063" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->September 21, 2016<!-- --> under the category <!-- -->Functional Reactive Programming</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">September 21, 2016</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/event-streams-vs-properties/"><span class="">Event streams vs Properties in Bacon.js</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Brief overview of what properties are and how they are different from event streams. We also cover how to create them and how to convert event streams into properties and vice versa.</p></article><article class="px9xea0" data-postid="5e09c02a-9f4f-5f5c-a039-6ec18bad02d8" data-testid="archive-post"><span class="dmsbls4">Published on <!-- -->September 17, 2016<!-- --> under the category <!-- -->Functional Reactive Programming</span><div class="_19o0aq30" aria-hidden="true"><span class="_19o0aq31" data-testid="metadata-publication-date">September 17, 2016</span></div><h2 class="px9xea1 dmsbls0" data-testid="archive-post-title"><a class="dmsbls3 dmsbls2" href="/blog/wrapping-things-in-bacon/"><span class="">Wrapping things in Bacon</span></a></h2><p class="px9xea2 dmsbls1" data-testid="archive-post-spoiler">Learn to create event streams from multiple sources, including DOM events, promises, timers and many others.</p></article></main></div><div id="gatsby-announcer" style="position:absolute;top:0;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0" aria-live="assertive" aria-atomic="true"></div></div><script id="gatsby-script-loader">/*<![CDATA[*/window.pagePath="/";/*]]>*/</script><!-- slice-start id="_gatsby-scripts-1" --> <script id="gatsby-chunk-mapping" > window.___chunkMapping="{\"app\":[\"/app-04ee7f5a8cc413847993.js\"],\"component---src-templates-blog-tsx\":[\"/component---src-templates-blog-tsx-6a5dbd7c6d57d02b13fc.js\"],\"component---src-templates-index-tsx\":[\"/component---src-templates-index-tsx-1dc445141ef89212cb9b.js\"]}"; </script> <script>window.___webpackCompilationHash="791e8d5abaec47d43517";</script><script src="/webpack-runtime-fe90664acf86a68c61dd.js" async></script><script src="/framework-f90682dfa2bbb8a99674.js" async></script><script src="/app-04ee7f5a8cc413847993.js" async></script><!-- slice-end id="_gatsby-scripts-1" --><!-- Cloudflare Pages Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "ad4da2ebedb74814ba19c0d00468a7a0"}'></script><!-- Cloudflare Pages Analytics --></body></html>