<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Tomas Pustelnik</title>
    <description>The latest articles on Forem by Tomas Pustelnik (@pustelto).</description>
    <link>https://forem.com/pustelto</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F340744%2F399d5f1a-001c-40c0-b462-60ec7fac52ec.jpeg</url>
      <title>Forem: Tomas Pustelnik</title>
      <link>https://forem.com/pustelto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pustelto"/>
    <language>en</language>
    <item>
      <title>I have switch from VS Code to VIM and I will never go back</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Mon, 16 Jan 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/i-have-switch-from-vs-code-to-vim-and-i-will-never-go-back-2b04</link>
      <guid>https://forem.com/pustelto/i-have-switch-from-vs-code-to-vim-and-i-will-never-go-back-2b04</guid>
      <description>&lt;p&gt;Some time ago, I posted a &lt;a href="https://twitter.com/pustelto/status/1552915586203541505"&gt;tweet announcing I had switched from VS Code to VIM&lt;/a&gt; (&lt;a href="https://neovim.io/"&gt;Neovim&lt;/a&gt; to be precise).&lt;/p&gt;

&lt;p&gt;Given that most of my colleagues looked at me in disbelief when I told them. I have decided to summarize my reasons behind this and outline the process for those brave enough to follow 😁.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I ditched VS Code
&lt;/h2&gt;

&lt;p&gt;I would say my two main reasons are &lt;strong&gt;performance&lt;/strong&gt; and &lt;strong&gt;navigation&lt;/strong&gt; in the code. VIM is just great at those.&lt;/p&gt;

&lt;p&gt;And while you can easily add navigation to VS Code with &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim"&gt;VIM plugin&lt;/a&gt;. You can’t do much about performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;VS Code has become unbearable slow for me, especially on large projects. And I’m using a mac, so I can’t blame the slow machine. Main issues I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There was a noticeable delay in the response when I triggered suggestions and before I got a response from Intellisense.&lt;/li&gt;
&lt;li&gt;Opening large files.&lt;/li&gt;
&lt;li&gt;Changing a project. When I wanted to check other projects, it took some time until the editor was fully responsive.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Navigation
&lt;/h3&gt;

&lt;p&gt;I tend to learn a lot of shortcuts (and prefer to use a keyboard most of the time). I could work like this in VS Code for most of the stuff, even though some keyboard shortcuts I used were quite complicated and required a combination of three keys most of the time.&lt;/p&gt;

&lt;p&gt;But for the detailed movements in the code, I had to use mouse or arrow keys. Getting my hand aways from letters to reach for arrows just become annoying for me. In the end I add custom keybinding which simulated VIM’s &lt;code&gt;hjkl&lt;/code&gt; basic navigation.&lt;/p&gt;

&lt;p&gt;That was a point where I realized I should probably use at least VIM plugin instead of reinventing wheel.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I feel about Neovim
&lt;/h2&gt;

&lt;p&gt;I love it.&lt;/p&gt;

&lt;p&gt;Seriously.&lt;/p&gt;

&lt;p&gt;I don’t think I will ever switch back to VS Code (or a similar IDE). Here is a quick summary of the good, ugly and bad from VIM (please note I’m still a beginner and know like 1% of VIM capabilities):&lt;/p&gt;

&lt;h3&gt;
  
  
  The good parts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It does everything I need, but faster (a &lt;strong&gt;lot faster&lt;/strong&gt; in many cases).&lt;/li&gt;
&lt;li&gt;It starts almost instantly. Getting into a file and quickly editing a few lines is a breeze. I am using a tmux and I have a running session for other projects. So this process is usually a matter of a few strokes. The ergonomics of this flow are genuinely nice.&lt;/li&gt;
&lt;li&gt;Sleek minimalistic look.&lt;/li&gt;
&lt;li&gt;Navigation and motions in the code (once you learn it, it is hard to go back).&lt;/li&gt;
&lt;li&gt;I don’t have to use a mouse.&lt;/li&gt;
&lt;li&gt;I like to mingle with my configs, so I enjoy this part as well (it is a good opportunity to learn something new).&lt;/li&gt;
&lt;li&gt;It gives me that nerdy feeling of terminal superiority 🤓.&lt;/li&gt;
&lt;li&gt;Editor in the terminal.

&lt;ul&gt;
&lt;li&gt;I can easily edit any file from everywhere. This seems like a minor thing, but it actually is a great boost for productivity. Yes, I know I could open files in VS Code from terminal, but it took some time as well. Now I just type &lt;code&gt;vim docker-compose.yml&lt;/code&gt;, and I can start editing. And I have all my keyboard shortcuts and plugins ready.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ugly parts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I miss multi-cursor sometimes, but less often than I would expect. I expect this will get less relevant over time as I learn how to properly use VIM for this kind o stuff (macros, search and replace, global command, etc.).&lt;/li&gt;
&lt;li&gt;I still haven’t finished my setup. Less used things do not have a proper config or do not have a keybinding.&lt;/li&gt;
&lt;li&gt;Hard to debug sometimes, why something is not working. But most of the time everything just works as intended.&lt;/li&gt;
&lt;li&gt;You must be willing to invest time to learn VIM (but you should invest your time to learn any other editor of your choice anyway).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bad parts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Initial setup takes quite a lot of time. You could use one of the ready-to-use distros like &lt;a href="https://www.lunarvim.org/"&gt;LunarVim&lt;/a&gt; or &lt;a href="https://astronvim.github.io/"&gt;AstroVim&lt;/a&gt;, but I haven’t check those too much.&lt;/li&gt;
&lt;li&gt;Given the large ecosystem and nature of VIM, some plugins might conflict with each other. That may be hard to debug. So far I’ve had this issue only once, but it was still a pain to solve.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How did I do it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BNny70sm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pustelto.com/blog/i-switched-to-vim/mhUlHAPCeu-296.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BNny70sm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pustelto.com/blog/i-switched-to-vim/mhUlHAPCeu-296.jpeg" alt="Boromir meme. Boromir telling is that one does not simply switch to VIM." width="296" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you get interested in Vim and would like to give it a shot as well? Then you will need quite a lot of patience. But in the end, I think it is not so difficult as many people (and Boromir) believe. You can learn a few basic commands to be reasonably productive in a fairly short time.&lt;/p&gt;

&lt;p&gt;Here is what I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I installed the VIM plugin for &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim"&gt;VS Code&lt;/a&gt;. It is a great for learning VIM. When you don’t know some commands, you still have a mouse and command palette at your disposal.&lt;/li&gt;
&lt;li&gt;Then I spent a month or two playing with it, learning more keybinding and gettings used to it (there are some nice &lt;a href="https://quickref.me/vim"&gt;VIM cheatsheets&lt;/a&gt; that can help)&lt;/li&gt;
&lt;li&gt;When I have decided to switch I wrote down a list of features I wanted and needed in my editor.&lt;/li&gt;
&lt;li&gt;I jump on Google and YouTube to see what is possible and how to configure the stuff. I found YouTube series &lt;a href="https://www.youtube.com/playlist?list=PLhoH5vyxr6Qq41NFL4GvhFp-WLd5xzIzZ"&gt;Neovim from scratch&lt;/a&gt;. The setup covered in the series have almost everything I need. So I mostly copy-paste and tweak a the config a little bit (there is a GitHub repo so you can just clone it).&lt;/li&gt;
&lt;li&gt;Once I had a feeling I have the most critical features I make the move and add more stuff as needed.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;That was my story with VIM in short.&lt;/p&gt;

&lt;p&gt;This is not meant to convince anyone to move to VIM. Use what you feel is the best tool for the job. In the end, you can be incredibly productive in any editor if you invest your time in learning it properly.&lt;/p&gt;

&lt;p&gt;As for me, I will stay with VIM. I don’t have a reason to go back to VS Code or any other “standard” editor. I’m really enjoying the experience and feel more productive.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>tools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to to (not)make a button</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Fri, 16 Sep 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/how-to-to-notmake-a-button-1ol9</link>
      <guid>https://forem.com/pustelto/how-to-to-notmake-a-button-1ol9</guid>
      <description>&lt;p&gt;Today’s web is a very interactive experience, yet we often fail to provide the same experience to everyone.&lt;/p&gt;

&lt;p&gt;Complex form widgets, interactive configurators, tables, shop listings, and the list goes on. We should use buttons and links to interact with those components. But often, we just put an &lt;code&gt;onClick&lt;/code&gt; handler on a div and call it a day.&lt;/p&gt;

&lt;p&gt;That leads to a poor experience for some users.&lt;/p&gt;

&lt;p&gt;I want to show you how to properly turn a &lt;code&gt;div&lt;/code&gt; into a button, in case you ever need it. So the result will be accessible and useable by everyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DISCLAIMER&lt;/strong&gt;: Please don’t do this. I’m not suggesting using div (or any other element) instead of a native button. Instead, I urge you to use the button. I only have to use a div instead of a button once in my life. And most likely, even in that one case, I could have solved it differently.&lt;/p&gt;

&lt;p&gt;So whatever your use case. You can most likely use a button for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would you want to create a custom button?
&lt;/h2&gt;

&lt;p&gt;There may be various reasons for this.&lt;/p&gt;

&lt;p&gt;We may have limited control over the markup (eg. when we use 3rd party library). Or there is some specific use case that doesn’t seem to be a good fit for a button or a link (and I have seen a lot of them in my career). For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interactive clickable card with the product info and other controls (add to cart, compare, etc.)&lt;/li&gt;
&lt;li&gt;Nested controls (a button with another button inside)&lt;/li&gt;
&lt;li&gt;Clickable table rows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While having limited control over markup may be hard to overcome. We can often solve these specific cases with a little bit of effort.&lt;/p&gt;

&lt;p&gt;Changing the design may be a valid option in some cases. But often we just need to rethink the markup a little bit. Here are some links for common patterns and how to do them correctly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://inclusive-components.design/cards/"&gt;Cards - Inclusive component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adrianroselli.com/2019/09/table-with-expando-rows.html"&gt;Table with Expando Rows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adrianroselli.com/2021/06/multi-column-sortable-table-experiment.html"&gt;Multi-Column Sortable Table Experiment&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if you think you still have to build a custom button, then read on:&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a button from a div
&lt;/h2&gt;

&lt;p&gt;Your first step will most likely be adding an &lt;code&gt;onClick&lt;/code&gt; handler. So let’s start with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div onClick={doSomething}&amp;gt;Click me. I'm a fake button&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Often this is also where it ends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: I use &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; syntax since I work with React most of the time. First, I think it’s readable, and second, JS frameworks like React make it really easy to put events like this into non-interactive elements since you write markup in JS as well.&lt;/p&gt;

&lt;p&gt;But as soon as you try to use a keyboard to interact with your new button, you will find that you can’t select it using the Tab key.&lt;/p&gt;

&lt;p&gt;So let’s fix that and add a few more properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard navigation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div tabindex={0} onClick={onClickButtonHandler} onKeyDown={onKeyDownHandler}&amp;gt; Click me. I'm a fake button&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to add a &lt;code&gt;tabindex&lt;/code&gt; attribute with the value &lt;code&gt;0&lt;/code&gt;. This will make the button focusable when using a keyboard (an important part of any accessible interface).&lt;/p&gt;

&lt;p&gt;Next, we have to assign a &lt;code&gt;keydown&lt;/code&gt; event listener to our custom button. HTML button can be pressed using Enter and Space keys. So we need to add that behavior as well. The listener callback will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function onKeyDownHandler(event) {
  if (event.key === "Enter" || event.key === " " /* space */) {
    onClickButtonHandler();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But in reality, this is not exactly correct behavior. The native button works slightly differently, as Adrian Roselli pointed out in his article &lt;a href="https://adrianroselli.com/2022/04/brief-note-on-buttons-enter-and-space.html"&gt;Brief Note on Buttons, Enter, and Space&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enter triggers the native button on the &lt;code&gt;keydown&lt;/code&gt; event, but Space triggers the button on the &lt;code&gt;keyup&lt;/code&gt; event (the press with Space can be canceled). If we want to mimic this behavior we have to update our handlers again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div tabindex={0} onClick={onClickButtonHandler} onKeyDown={onKeyDownHandler} onKeyUp={onKeyUpHandler}&amp;gt; Click me. I'm a fake button&amp;lt;/div&amp;gt;

function onKeyDownHandler(event) {
  if (event.key === "Enter") {
    onClickButtonHandler();
  }
}

function onKeyUpHandler(event) {
  if (event.key === " " /* space */) {
    onClickButtonHandler();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: all this stuff is handled on the native button via the &lt;code&gt;onClick&lt;/code&gt; method. So there is no need to pass keyboard event handlers for a button press.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility improvements
&lt;/h3&gt;

&lt;p&gt;Right now, we have a fake div button that users can click on. And they can control it with a keyboard as well. But we still have to do a few more things to make this button accessible. First, we need to tell screen readers that this is really a button, not a div. We will add the &lt;code&gt;role="button"&lt;/code&gt; attribute. Without it, screen readers won’t announce this as a button to the users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div tabindex={0} onClick={onClickButtonHandler} onKeyDown={onKeyDownHandler} onKeyUp={onKeyUpHandler} role="button"&amp;gt; Click me. I'm a fake button&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Are we done?&lt;/p&gt;

&lt;p&gt;For the basic functionality, yes. But what if you need to disable that button?&lt;/p&gt;

&lt;p&gt;For an HTML button, you would just use the &lt;code&gt;disabled&lt;/code&gt; attribute and the browser would take care of everything (default styles, turn off the interactivity, etc.). But that is not going to work for our fake button.&lt;/p&gt;

&lt;p&gt;We have to use the &lt;code&gt;aria-disabled&lt;/code&gt; attribute. But we also have to handle the styling and also disabling of the event handlers. You might also want to prevent the button to be unfocusable via tab. All this means just more work for us.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final result
&lt;/h3&gt;

&lt;p&gt;This is our final code for a button with support for the disabled state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div tabindex={0} onClick={onClickButtonHandler} onKeyDown={onKeyDownHandler} onKeyUp={onKeyUpHandler} role="button"&amp;gt; Click me. I'm a fake button&amp;lt;/div&amp;gt;

function isDisabled(eventTarget) {
  const ariaDisabled = eventTarget.getAttribute("aria-disabled");
  const isDisabled = ariaDisabled === "" || ariaDisabled === "true";
  return isDisabled;
}

function onKeyDownHandler(event) {
  if (event.key === "Enter" &amp;amp;&amp;amp; !isDisabled(event.target)) {
    onClickButtonHandler();
  }
}

function onKeyUpHandler(event) {
  if (event.key === " " &amp;amp;&amp;amp; !isDisabled(event.target)) {
    onClickButtonHandler();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quite a lot of code for a simple component, right? And even if you write all this code you still don’t get the full button feature set.&lt;/p&gt;

&lt;p&gt;I hope by this time that you realize that instead of writing all this code yourself, it is much easier to write this code and get all the goodies for free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button type="button" onClick={onClickButtonHandler}&amp;gt; Click me! I'm a real button.&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isn’t that much easier?&lt;/p&gt;

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

&lt;p&gt;While the button seems to be a simple component, which we can easily hack together with the &lt;code&gt;div&lt;/code&gt; and &lt;code&gt;onClick&lt;/code&gt; handler, the opposite is true.&lt;/p&gt;

&lt;p&gt;I hope you have learned how complex it is to create a good button component and how much time and effort you can save using a native button.&lt;/p&gt;

&lt;p&gt;And your users will probably thank you as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional resources
&lt;/h2&gt;

&lt;p&gt;Want to learn more? Check out these amazing resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://adrianroselli.com/2022/04/brief-note-on-buttons-enter-and-space.html"&gt;Brief Note on Buttons, Enter, and Space&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A three-part series about implementing a button in the React-Aria library:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://react-spectrum.adobe.com/blog/building-a-button-part-1.html"&gt;Building a Button Part 1: Press Events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react-spectrum.adobe.com/blog/building-a-button-part-2.html"&gt;Building a Button Part 2: Hover Interactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react-spectrum.adobe.com/blog/building-a-button-part-3.html"&gt;Building a Button Part 3: Keyboard Focus Behavior&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Real-world CSS vs. CSS-in-JS performance comparison</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Fri, 09 Apr 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/real-world-css-vs-css-in-js-performance-comparison-2fpa</link>
      <guid>https://forem.com/pustelto/real-world-css-vs-css-in-js-performance-comparison-2fpa</guid>
      <description>&lt;p&gt;CSS-in-JS has taken a solid place in front-end tooling, and it seems this trend will continue in the near future. Especially in the React world. For example, out of 11492 people who participate in &lt;a href="https://2020.stateofcss.com/en-US/" rel="noopener noreferrer"&gt;State of CSS&lt;/a&gt; survey in 2020 only 14.3% didn’t hear of &lt;a href="https://styled-components.com/" rel="noopener noreferrer"&gt;Styled Components&lt;/a&gt; (a dominant CSS-in-JS library). And more than 40% of participants have used the library.&lt;/p&gt;

&lt;p&gt;I wanted to see an in-depth performance comparison of CSS-in-JS libraries like Styled Components and a good old CSS for a long time. Sadly I was unable to found a comparison on a real-world project and not some simple test scenario. So I decided to do it myself. I have migrated the real-world app from Styled Components to &lt;a href="https://linaria.dev/" rel="noopener noreferrer"&gt;Linaria&lt;/a&gt;, which will extract CSS on build time. No runtime generation of the styles on the user’s machine.&lt;/p&gt;

&lt;p&gt;A short notice, before we begin. I’m not a hater of CSS-in-JS. I admit they have great DX, and the composition model inherited from React is great. It can provide developers with some nice advantages like &lt;a href="https://twitter.com/joshwcomeau" rel="noopener noreferrer"&gt;Josh W. Comeau&lt;/a&gt; highlights in his article &lt;a href="https://www.joshwcomeau.com/css/styled-components/" rel="noopener noreferrer"&gt;The styled-components Happy Path&lt;/a&gt;. I also use Styled Components on several of my projects or projects I have worked on. But I wondered, what is the price for this great DX from the user’s point of view.&lt;/p&gt;

&lt;p&gt;Let’s see what I have found.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR:
&lt;/h2&gt;

&lt;p&gt;Don’t use runtime CSS-in-JS if you care about the load performance of your site. &lt;strong&gt;&lt;em&gt;Simply less JS = Faster Site.&lt;/em&gt;&lt;/strong&gt; There isn’t much we can do about it. But if you want to see some numbers, continue reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I measured and how
&lt;/h2&gt;

&lt;p&gt;The app I have used for the test is a pretty standard React app. Bootstrapped using Create React App project, with Redux and styled using Styled components (v5). It is a fairly large app with many screens, customizable dashboards, customer theming, and more. Since it was built with CRA, it doesn’t have server-side rendering, so everything is rendered on the client (since it’s a B2B app, this wasn’t a requirement).&lt;/p&gt;

&lt;p&gt;I took this app and replaced the Styled Components with Linaria, which seems to have a similar API. I thought the conversion would be easy. It turned out it wasn’t that easy. It took me over two months to migrate it, and even then, I have migrated only a few pages and not the entire app. I guess that’s why there is no comparison like this 😅. Replacing the styling library was the only change. Everything else remained intact.&lt;/p&gt;

&lt;p&gt;I have used Chrome dev tools to run several tests on the two most used pages. I have always run the tests three times, and the presented numbers are an average of those 3 runs. For all the tests, I have set &lt;em&gt;CPU throttling to 4x&lt;/em&gt; and &lt;em&gt;network throttling to Slow 3G&lt;/em&gt;. I used a separate Chrome profile for performance testing without any extensions.&lt;/p&gt;

&lt;p&gt;Run test:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Network (size of the JS and CSS assets, coverage, number of requests)&lt;/li&gt;
&lt;li&gt;Lighthouse audits (performance audit with mobile preset).&lt;/li&gt;
&lt;li&gt;Performace profiling (tests for page load, one for drag and drop interaction)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Network comparison
&lt;/h2&gt;

&lt;p&gt;We will start with a network. One of the advantages of CSS-in-JS is that there are no unused styles, right? Well, not exactly. While you have active only the styles used on the page, you may still download unnecessary styles. But instead of having them in a separate CSS file, you have them in your JS bundle.&lt;/p&gt;

&lt;p&gt;Here is a data comparison of the same home page build with Styled Components and Linaria. Size before the slash is gzipped size, uncompressed size is after it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Home page network stats comparison:&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Styled Component&lt;/th&gt;
&lt;th&gt;Linaria&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total number of requests&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total size&lt;/td&gt;
&lt;td&gt;361kB/1.8MB&lt;/td&gt;
&lt;td&gt;356kB/1.8MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS size&lt;/td&gt;
&lt;td&gt;2.3kB/7.2kB&lt;/td&gt;
&lt;td&gt;14.7kB/71.5kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No. of CSS requests&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JS size&lt;/td&gt;
&lt;td&gt;322kB/1.8MB&lt;/td&gt;
&lt;td&gt;305kB/1.7MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No. of JS requests&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Search page network stats comparison:&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Styled Component&lt;/th&gt;
&lt;th&gt;Linaria&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total number of requests&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total size&lt;/td&gt;
&lt;td&gt;395kB/1.9MB&lt;/td&gt;
&lt;td&gt;391kB/1.9MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS size&lt;/td&gt;
&lt;td&gt;2.3kB/7.2kB&lt;/td&gt;
&lt;td&gt;16.0kB/70.0kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No. of CSS requests&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JS size&lt;/td&gt;
&lt;td&gt;363kB/1.9MB&lt;/td&gt;
&lt;td&gt;345kB/1.8MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No. of JS requests&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Even though our CSS payload increased quite a lot, we are still downloading fewer data in total in both test cases (yet the difference is almost neglectable in this case). But what is more important, the sum of CSS and JS for Linaria is still smaller than the size of the JS itself in Styled Component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coverage
&lt;/h3&gt;

&lt;p&gt;If we compare coverage, we get a lot of unused CSS for Linaria (around 55kB) compared with 6kB for Styled Component (this CSS is from npm package, not from the Styled Components itself). The size of the unused JS is 20kB smaller for Linaria compared to Styled Component. But the overall size of the unused assets is larger in Linaria. This is one of the trade-offs of external CSS.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Coverage comparison – Home page:&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Styled Component&lt;/th&gt;
&lt;th&gt;Linaria&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Size of unused CSS&lt;/td&gt;
&lt;td&gt;6.5kB&lt;/td&gt;
&lt;td&gt;55.6kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size of unused JS&lt;/td&gt;
&lt;td&gt;932kB&lt;/td&gt;
&lt;td&gt;915kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total size&lt;/td&gt;
&lt;td&gt;938.5k&lt;/td&gt;
&lt;td&gt;970.6kB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Coverage comparison – Search page:&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Styled Component&lt;/th&gt;
&lt;th&gt;Linaria&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Size of unused CSS&lt;/td&gt;
&lt;td&gt;6.3kB&lt;/td&gt;
&lt;td&gt;52.9kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size of unused JS&lt;/td&gt;
&lt;td&gt;937kB&lt;/td&gt;
&lt;td&gt;912kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total size&lt;/td&gt;
&lt;td&gt;938.5k&lt;/td&gt;
&lt;td&gt;970.6kB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Lighthouse performance audit
&lt;/h2&gt;

&lt;p&gt;If we are talking about performance, it would be a shame not to use Lighthouse. You can see the comparisons in the charts below (average from 3 LI runs.). Aside from Web Vitals, I have also include Main thread work (time to parse, compile and execute assets, the biggest part of this is JS, but it covers layout and styles calculation, painting, etc.) and JS Execution time. I have omitted Cumulative Layout Shift since it was close to zero, and there was almost no difference between Linaria and Styled Component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faupx9vcn4yo81opnbrhd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faupx9vcn4yo81opnbrhd.jpg" alt="Lighthouse performance audit comparison of home page. Linaria has better speed index and larges contentful paint by more that 800 milliseconds. And main thread work is is lower by 1.63 seconds."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2s5mvdyqrmkw77l086w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2s5mvdyqrmkw77l086w.jpg" alt="Lighthouse performance audit comparison of search page. Linaria has better speed index by 900 milliseconds and larges contentful paint by 1.2 seconds. Main thread work is is lower by 1.27 seconds."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, Linaria is better in most of the Web Vitals (lost once in CLS). And sometimes by a large margin. For example, LCP is faster by 870ms on the home page and by 1.2s on the Search page. Not only does the page render with normal CSS much faster, but it requires fewer resources as well. Blocking time and time necessary to execute all the JS are smaller by 300ms and roughly 1.3 seconds respectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performace profiling
&lt;/h2&gt;

&lt;p&gt;Lighthouse can give you many insights on the performance. But to get into the details, the performance tab in the dev tools is the best bet. In this case, the performance tab confirms the Lighthouse results. You can see the details on the charts below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4i5badafc6xdo6r8pot.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4i5badafc6xdo6r8pot.jpg" alt="Profiling comparison of the home page. Rendering and paint are almost identical. But Linaria spend almost 1 second less time on scripting. And have total blocking time smaller by more than 1.5 seconds."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1h6fcn1chr98a42xmm6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1h6fcn1chr98a42xmm6.jpg" alt="Profiling comparison of the search page. Rendering and paint are almost identical. But Linaria spend more than 1 second less time on scripting and have total blocking time smaller almost by than 1.5 seconds."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screens build with Styled Component had more long-running tasks. Those tasks also took longer to complete, compared to the Linaria variant.&lt;/p&gt;

&lt;p&gt;To give you another look at the data, here is the visual comparison of the performance charts for loading the home page with Styled Component (top) and Linaria (bottom).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcclckz3nl1tqiky5y91x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcclckz3nl1tqiky5y91x.jpg" alt="Comparison of Chrome dev tools performance minimap chart of home page build with Styled Components and Linaria. Pages build with Linaria have a visually smaller amount of long-running task, loading finished earlier and had better FPS."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing user interaction
&lt;/h3&gt;

&lt;p&gt;To compare user interaction as well, not only the page load. I have measured the performance of the drag and drop activity used to assign items into groups. The result summary is below. Even in this case, Linaria beat the runtime CSS-in-JS in several categories.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Drag and drop comparison:&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Styled Component&lt;/th&gt;
&lt;th&gt;Linaria&lt;/th&gt;
&lt;th&gt;Diff&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scripting&lt;/td&gt;
&lt;td&gt;2955&lt;/td&gt;
&lt;td&gt;2392&lt;/td&gt;
&lt;td&gt;-563ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rendering&lt;/td&gt;
&lt;td&gt;3002&lt;/td&gt;
&lt;td&gt;2525&lt;/td&gt;
&lt;td&gt;-477ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Painting&lt;/td&gt;
&lt;td&gt;329&lt;/td&gt;
&lt;td&gt;313&lt;/td&gt;
&lt;td&gt;-16ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Blocking Time&lt;/td&gt;
&lt;td&gt;1862.66&lt;/td&gt;
&lt;td&gt;994.07&lt;/td&gt;
&lt;td&gt;-868ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffojk0ddx2haewx8x48f5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffojk0ddx2haewx8x48f5.jpg" alt="Comparison of Chrome dev tools performance minimap chart of drag and drop interaction for pages build with Styled Components and Linaria. Linaria shows less long-running tasks and less JS to execute."&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;That’s it. As you can see runtime CSS-in-JS can have a noticeable impact on your webpage. Mainly for low-end devices and regions with a slower internet connection or more expensive data. So maybe we should think better about what and how we use our tooling. Great developer experience shouldn’t come at the expense of the user experience.&lt;/p&gt;

&lt;p&gt;I believe we (developers) should think more about the impact of the tools we choose for our projects. The next time I will start a new project, I will not use runtime CSS-in-JS anymore. I will either use good old CSS or use some build-time CSS-in-JS alternative to get my styles out of JS bundles.&lt;/p&gt;

&lt;p&gt;I think build-time CSS-in-JS libs will be the next big thing in the CSS ecosystem as more and more libs are coming out (the last one being &lt;a href="https://github.com/seek-oss/vanilla-extract" rel="noopener noreferrer"&gt;vanilla-extract&lt;/a&gt; from Seek). And big companies are heading this way as well, like Facebook with their &lt;a href="https://www.youtube.com/watch?v=9JZHodNR184" rel="noopener noreferrer"&gt;styling lib&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>performance</category>
    </item>
    <item>
      <title>Freezing development of Qjub</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Sun, 10 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/freezing-development-of-qjub-53h5</link>
      <guid>https://forem.com/pustelto/freezing-development-of-qjub-53h5</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; I don’t have enough time to focus on all my side-projects and activities. So I have decided to focus more on &lt;a href="https://pustelto.com/"&gt;my blog&lt;/a&gt; than on the Qjub. For more detailed reasons, continue reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I’ve decided that way?
&lt;/h2&gt;

&lt;p&gt;A little bit of context first. I have a full-time job (last couple of months I worked only 4 days/week actually), two little kids, a few small &lt;a href="https://pustelto.com/projects/"&gt;open-source projects&lt;/a&gt;, and I wrote my own blog. That is a lot of going on and while one extra day to focus on these things helped. It still doesn’t allow me to focus on all those things equally.&lt;/p&gt;

&lt;p&gt;When I start writing my blog last year, my goal was to publish at least one article a month. I didn’t meet that goal (yet), but I want to continue to focus on writing more. To do that, I decided to freeze the development of the Qjub. Here are some reasons why I choose to do so:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Writing a blog makes more sense to me
&lt;/h3&gt;

&lt;p&gt;When I start my blog, I haven’t had a feeling I have too much to offer (hello imposter syndrome). But I gave it a shot and tried to regularly post new articles and republish them 14 days later to &lt;a href="https://dev.to/"&gt;Dev.to&lt;/a&gt; community. I still have a small audience, but two articles get some serious notice and more than 12k page views (on my blog or on Dev.to). Given these are some of my first articles, I consider that amazing success. And it’s a great motivation to continue with writing. Don’t get me wrong. Even if my article helps a single person I consider it a success. But seeing so many people read your blog feels amazing.&lt;/p&gt;

&lt;p&gt;While working with other developers and checking some existing apps, I realized many front-end developers lack deeper knowledge of web performance, semantic HTML, advanced CSS, and accessibility. So I decide to continue with my blog and focus on those things to teach other developers. And in general, help make the Web better for the users as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The unclear focus of Qjub
&lt;/h3&gt;

&lt;p&gt;I start Qjub as a learning project, but it was designed right from the start to solve one of my problems – how to effectively store and organize different notes and resources. Mainly from the web. I believe Qjub does a good job in this case. Or at least it works great for my needs. But I really didn’t figure out how to sold this to others. Currently, I have around 20 users, but very few of them are using Qjub regularly. A great example of this is traffic from my blog. One of my popular blog posts brought to Qjub about 300 visitors in two weeks (a huge spike in visits for me). But none of them become regular users.&lt;/p&gt;

&lt;p&gt;That leads me to the hypothesis that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;My idea is not so great and aside from me, no one needs it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Qjub’s homepage is really bad at its job to explain Qjub to others and convince them to sign up.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I believe that both points are valid. I plan to do something with point number 2 before really putting Qjub aside. As with number 1. I’m not sure I can do much with that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means for Qjub and its users
&lt;/h2&gt;

&lt;p&gt;Freezing Qjub’s development doesn’t mean I’m going to shut down the project. Qjub will be still there, and it is free to use for anyone. I use it quite a lot, so it’s not going anywhere. It would be a huge pain for me to migrate all my notes and other stuff somewhere else. And domain aside, I run it almost for free. So I have no reason to shut it down completely.&lt;/p&gt;

&lt;p&gt;I will simply stop developing new features and instead use available time for my other activities. You may say that I have already done it if you check &lt;a href="https://qjub.app/changelog/"&gt;Qjub’s changelog&lt;/a&gt;. But declaring it to the public like this will help me get rid of the mental overhead I currently have with it. And it’s aligned with my value of transparency to the users.&lt;/p&gt;

&lt;p&gt;I still may update it from time to time, since there are plenty of features I would like to add. But that will be an occasional activity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;Before completely putting Qjub aside, I plan to update the homepage as a final effort to better explain its value to the users. After that don’t expect any large updates.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>startup</category>
    </item>
    <item>
      <title>What you might not know about sizing in CSS</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Tue, 08 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/what-you-might-not-know-about-sizing-in-css-2cfj</link>
      <guid>https://forem.com/pustelto/what-you-might-not-know-about-sizing-in-css-2cfj</guid>
      <description>&lt;p&gt;A project I currently work on has a lot of different and sometimes non-trivial layouts. And it can be a struggle to get all the different elements sized correctly to avoid overflows and extra scrollbars. So I have deep dive into the CSS specification to learn about sizing and layout models as much as possible. And how to handle issues like this better in the future. I will share my findings with you.&lt;/p&gt;

&lt;p&gt;We will cover those topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How percentage works for the height property&lt;/li&gt;
&lt;li&gt;Two ways how to handle stretching in Flexbox&lt;/li&gt;
&lt;li&gt;What &lt;code&gt;1fr&lt;/code&gt; really means to the browser&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How does &lt;code&gt;height: 100%;&lt;/code&gt; work
&lt;/h2&gt;

&lt;p&gt;Sometimes you need to set the fixed height of some element. You can use absolute units like &lt;code&gt;px&lt;/code&gt;, or relative units like &lt;code&gt;em&lt;/code&gt; or &lt;code&gt;rem&lt;/code&gt;. Those work much better in the responsive design. There is not much to talk about. You set the height to some exact number and it just works. But, when you want to use a percentage, that’s when you can encounter some trouble.&lt;/p&gt;

&lt;p&gt;A common mistake is that people set &lt;code&gt;height&lt;/code&gt; to &lt;code&gt;100%&lt;/code&gt; and think it will stretch the entire height of the parent element. But that is not always the case. Here is what the specification says about this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The percentage is calculated with respect to the height of the generated box’s containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to ‘auto’.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To translate it into simple English. If the browser doesn’t know the height of a parent it can’t calculate the height of the element (you can’t calculate percentage from unknown value). In such a case it will let the content control the height instead. This often means that you have to set height across many parent nodes (eventually up to the &lt;code&gt;html&lt;/code&gt; element itself). That can lead to fragile layouts, where one change in the markup will break the whole damn thing.&lt;/p&gt;

&lt;p&gt;One cool trick to avoid this problem is the usage of CSS Grid. When you set the height of the grid item’s child using percentage it will work. For the purpose of calculating height, a grid item is considered to have explicit height. This works even for grid sizing keywords like &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;max-content&lt;/code&gt;, and &lt;code&gt;min-content&lt;/code&gt;. You can see it working in the codepen below.&lt;/p&gt;

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

&lt;p&gt;In the codepen below, you can explore how is the height with the percentage units affected by different properties.&lt;/p&gt;

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

&lt;p&gt;If you want to know how exactly percentage units work in different properties, definitely check the amazing article from &lt;a href="https://wattenberger.com/blog/css-percents"&gt;Amelia Wattenberger&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How sizing in Flexbox works
&lt;/h2&gt;

&lt;p&gt;Flexbox is a powerful layout module, solving a lot of common layout and alignment issues easily. But, if you have been using Flexbox for some time, you have probably encountered a situation where the flex items didn’t size exactly as you expect. Flexbox works great when you don’t care so much about the size of the items. But it can get a little tricky when you need exact sizes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; I assume you have some basic knowledge of flexbox module and how to use it. If not, I would suggest checking some great materials like the &lt;a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/"&gt;Flexbox guide here on CSS-Tricks&lt;/a&gt; or the &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox"&gt;Flexbox guide at MDN&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To explain how Flexbox really works we will use a simple example. We have a flex container with 3 items of different widths. If we set only &lt;code&gt;display: flex&lt;/code&gt; on parent it will look like on the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ywoLhSB_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xlbevzngxsgwfcuvqo14.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ywoLhSB_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xlbevzngxsgwfcuvqo14.jpg" alt="Flexbox container with 3 items showing default browser behavior when settings display: flex on HTML element. Each item width is based on the content, items will not grow even if there is empty space in the container."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Flexbox, &lt;code&gt;flex-grow&lt;/code&gt; and &lt;code&gt;flex-shrink&lt;/code&gt; properties control the shrinking and the expansion of the flex items. Those properties can be also set by shorthand &lt;code&gt;flex&lt;/code&gt; property. The default value for the browsers is &lt;code&gt;flex: 0 1 auto&lt;/code&gt;. This means that items can shrink if there is not enough space, but they will not expand to fill the container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AQxAv80D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s8k2hylsaveomj04p42e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AQxAv80D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s8k2hylsaveomj04p42e.jpg" alt="Flex shorthand property can take 3 arguments. First is the value of flex-grow, second is for flex-shrink and third is for flex-basis."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you add &lt;code&gt;flex-grow: 1&lt;/code&gt; to flex items, they will stretch to fill the entire width of the container. But the items don’t have the same size. Even though they can easily fit into the container and all of them have the same value of &lt;code&gt;flex-grow&lt;/code&gt; property. Also, the right part is a bit smaller than the left part.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B49cVJmi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/revzkmbnmsbycpry64xu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B49cVJmi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/revzkmbnmsbycpry64xu.jpg" alt="Flex container with 3 items which have flex-grow set to 1. All items will stretch to fill the entire container."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How is that possible? Shouldn’t all items have the same width? No, because Flexbox by default distributes the remaining empty space (hatched area in the image below). Not the entire container width, as some developers often think. Even if you set the same &lt;code&gt;flex-grow&lt;/code&gt; value to all flex items, they will not have equal widths. Unless their basic width is the same as well (set via &lt;code&gt;width&lt;/code&gt; or &lt;code&gt;flex-basis&lt;/code&gt; properties).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OILXRQQs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hkejo7hybqkolhohbeq9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OILXRQQs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hkejo7hybqkolhohbeq9.jpg" alt="Flex container with 3 flex items before the items will be stretched thanks to flex-grow property. Remaining free space will be distributed to the flex items based on the value of their respective flex-grow properties."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To avoid this way of space distribution you can set the &lt;code&gt;flex-basis&lt;/code&gt; value to &lt;code&gt;0&lt;/code&gt;. When the &lt;code&gt;flex-basis&lt;/code&gt; is set to any value other than &lt;code&gt;auto&lt;/code&gt;, the &lt;code&gt;width&lt;/code&gt; property of the items is ignored and browses will consider that all items have basic width equal to the given &lt;code&gt;flex-basis&lt;/code&gt;. So when you set &lt;code&gt;flex-basis: 0&lt;/code&gt; you are telling the browser that all flex items have zero width. Thus the entire flex container width will be used as a free space to distribute based on values of &lt;code&gt;flex-grow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; While width and height are ignored when &lt;code&gt;flex-basis&lt;/code&gt; is set to any value other than &lt;code&gt;auto&lt;/code&gt;. Min-height and max-height properties (and their width counter parts) are still honored. This can be used for some clever CSS magic like &lt;a href="https://heydonworks.com/article/the-flexbox-holy-albatross/"&gt;Holy albatros technique&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can see on the schema below how flex-basis &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;auto&lt;/code&gt; work exactly (image is taken from the &lt;a href="https://www.w3.org/TR/css-flexbox-1/#flex-property"&gt;specification&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TXNTGYHi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yd5vngeh2gkapy1hsr7o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TXNTGYHi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yd5vngeh2gkapy1hsr7o.jpg" alt="Difference between space distribution when we use flex-basis: auto and flex-basis: 0. With value auto only remaining free space is distributed. With value 0, all space in the flex container is distributed based on the values of flex-grow properties defined on the flex items."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Beware of the extra padding and border
&lt;/h3&gt;

&lt;p&gt;One more thing to be aware of is that borders and padding on child items will increase the item’s width. And the flex items will not honor the &lt;code&gt;flex-grow&lt;/code&gt; ratio precisely (even with &lt;code&gt;flex-basis: 0&lt;/code&gt;). Here is a related part of the specification:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The hypothetical main size is the item’s flex base size clamped according to its used min and max main sizes (and flooring the content box size at zero).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Add padding or border to the child of flex item to fix this. As seen in the codepen below.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Large grid items breaking from the grid layout
&lt;/h2&gt;

&lt;p&gt;Imagine you have two columns layout. Sidebar with header and footer and a large list of items we want to scroll. And then the main area where we display the detail of the selected item. This layout can be usually seen in an email client. We have set the fixed height of the grid. After all, we don’t want to scroll the page itself, but the items in the sidebar or the detail in the content area. &lt;code&gt;grid-template-rows&lt;/code&gt; is set to 1fr to fill all available space.&lt;/p&gt;

&lt;p&gt;You can see the layout in codepen below.&lt;/p&gt;

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

&lt;p&gt;But for some reason items in the sidebar are overflowing out of the grid area and the entire page is scrollable. Not exactly what we want or expect.&lt;/p&gt;

&lt;p&gt;The problem is in the &lt;code&gt;grid-template-rows&lt;/code&gt; property. When we set its size using the &lt;code&gt;fr&lt;/code&gt; unit, grid items min-size is set to &lt;code&gt;auto&lt;/code&gt; by default (according to specification). With value &lt;code&gt;auto&lt;/code&gt; grid item will resize to fit in all the content, even it is bigger than the defined grid cell.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;grid-template-rows: 1fr;&lt;/code&gt; is equal to &lt;code&gt;grid-template-rows: minmax(auto, 1fr);&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To fix this problem let’s change out the definition of grid rows to &lt;code&gt;grid-template-rows: minmax(0, 1fr);&lt;/code&gt;. With this, our extra-large &lt;code&gt;ul&lt;/code&gt; list will shrink to fit the grid defined area as we would expect. You can test it in the codepen mentioned above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;And that’s it. We have covered a few cases where the sizing doesn’t behave as we could expect at first. Hopefully, this article will help you to build layouts in CSS more easily and with less frustration.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What I read to stay up-to-date</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Thu, 17 Sep 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/what-i-read-to-stay-up-to-date-5fjn</link>
      <guid>https://forem.com/pustelto/what-i-read-to-stay-up-to-date-5fjn</guid>
      <description>&lt;p&gt;Some time ago I have published a post about &lt;a href="https://pustelto.com/blog/tools-i-use/"&gt;tools I use in front-end development&lt;/a&gt;, and it had a bigger response than I expected (in a positive manner 😊). And quite a few people ask me how do I stay up-to-date with modern web dev. So I decided to share another list. This time it’s about blogs and other resources I watch and read to keep myself up-to-date with ever-evolving web development.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is my workflow #
&lt;/h2&gt;

&lt;p&gt;I use &lt;a href="https://feedly.com/"&gt;Feedly&lt;/a&gt; to aggregate RSS feeds from the blogs listed below. Many people seem surprised by the fact I use RSS, but honestly, it’s a great way how to keep an eye on many resources without losing time and valuable stuff. Of course, I don’t read every article published on the sites listed below. If I did, I would be reading 24/7, not exactly what I want. So I’m quite picky what to read (but still have a huge buffer).&lt;/p&gt;

&lt;p&gt;I usually keep interesting articles unread and dismiss the articles I don’t found relevant to me. Then from time to time, I open a bunch of articles and either read them if I have the time or save them to &lt;a href="https://getpocket.com/"&gt;Pocket&lt;/a&gt; and read them later. I usually read them offline when I’m commuting to work. Feedly and Pocket are a great combo and work very well for me and save me a lot of time.&lt;/p&gt;

&lt;p&gt;So without any more talking, here is the list of web sites and other resources I keep an eye on (in no particular order):&lt;/p&gt;

&lt;h2&gt;
  
  
  Blogs #
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://css-tricks.com/"&gt;CSS-Tricks&lt;/a&gt; - great resource for a front-end related stuff. Often with links to other interesting resources. I would say the main focus is on CSS/HTML related stuff (no surprises), animations, SVGs, etc. But you can found articles on static-site generators, React, Vue, and much more.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.smashingmagazine.com/"&gt;Smashing Magazine&lt;/a&gt; - a great site full of in-depth articles on design, UX/UI, front-end, and accessibility. I found especially the mix of design and development articles very valuable since I think front-end developers should have some knowledge of design principles as well.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scotch.io/"&gt;Scotch.io&lt;/a&gt; - tutorial site focusing on all web dev (frontend and backend). I think it’s great for junior developers. I don’t personally read their articles too often these days, but I still found it valuable to keep it in my RSS.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.sitepoint.com/blog/"&gt;SitePoint&lt;/a&gt; - another tutorial site, similar to Scotch.io. Covers backend as well. It has a wide range of topics covered and some interesting authors. You can often found articles focusing on best practices. Introductions to new technologies etc.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tympanus.net/codrops/"&gt;Codrops&lt;/a&gt; - I keep an eye on this site mainly for their &lt;a href="https://tympanus.net/codrops/collective/"&gt;Collective&lt;/a&gt; section. It is a basically web-based newsletter with the newest and coolest development and design stuff from around the internet. Aside from the Collective, they also post a lot of cool demos. Mainly focusing on high-quality animations and transitions. So if you looking for something fancy on your new page, this is the place to go.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Personal sites #
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://csswizardry.com/"&gt;CSS Wizardry&lt;/a&gt; - personal website of Harry Roberts. He publishes irregularly about web performance and CSS. His posts are always high quality and go really deep. So if you are into the WebPerf this is one of the resources I suggest to follow.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://addyosmani.com/"&gt;Addy Osmani&lt;/a&gt; - Addy is Engineering Manager at Google working on Chrome. As such he mostly writes about WebPerf, often with relation to Chrome Browser.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://adrianroselli.com/"&gt;Adrian Roselli&lt;/a&gt; - Adrian writes about accessibility (a11y) and has plenty of great articles about this topic. Definitely worth following if you are interested in this topic (and you should as a front-end dev).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wattenberger.com/"&gt;Amelia Wattenberger&lt;/a&gt; - Amelia writes mostly about D3 and data visualization, but you can found articles about SVG, CSS, and React. What makes Amelia’s blog stand out is the high quality and interactivity of her articles. Each of them is like an interactive microsite with a lot of examples to help you understand the given topic.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.sarasoueidan.com/blog/"&gt;Sara Soueidan&lt;/a&gt; - Sara has a large collection of articels about SVG, CSS and a11y.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://timkadlec.com/"&gt;Tim Kadlec&lt;/a&gt; - Tim is well known for is focus on WebPerf, so you can found lots of articles about this topic on his blog.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://joshwcomeau.com/"&gt;Josh Comeau&lt;/a&gt; - Josh writes about various subjects related to front-end development, like React, Gatsby, CSS and animations, JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://philipwalton.com/"&gt;Philip Walton&lt;/a&gt; - Phil is an engineer at Google, and his articles focus a lot on web performance (mainly fast loading of the website) and JavaScript, but you can found articles about other topics as well.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.hawksworx.com/blog"&gt;Phil Hawksworth&lt;/a&gt; - Phil works at Netlify in the Developer experience team, so expect his articles to focus mainly on &lt;a href="https://jamstack.org/"&gt;JAMstack&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://bitsofco.de/"&gt;Bits of Code&lt;/a&gt; - Ire Aderinokun’s blog about front-end development. Some topics covered on the blog: CSS, JS, HTML and DOM, Puppeteer, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other #
&lt;/h3&gt;

&lt;p&gt;Recently I started to follow the blogs of W3C (World Wide Web Consortium) and WHATWG (The Web Hypertext Application Technology Working Group) to keep an overview of specification updates for HTML and CSS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.whatwg.org/"&gt;The WHATWG Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/blog/CSS/"&gt;https://www.w3.org/blog/CSS/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Newsletters #
&lt;/h2&gt;

&lt;p&gt;Aside from following many websites and blogs, I have also signup for plenty of newsletters (more than I like actually 😅). I have already unsubscribed from some I don’t read and I send the rest to a special folder in Gmail which I check from time to time. Below you can found a list of newsletters I still receive and check regularly. Again I do not read all the articles listed inside, but only a few which seem relevant or interested to me. My flow for newsletters is similar to the one I use for blog articles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kentcdodds.com/"&gt;Kent C. Dodds&lt;/a&gt; - Kent writes blog mostly about React and testing. I have subscribed to his newsletter to get the blog post updates sooner and to get info about his new projects or courses.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://javascriptweekly.com/"&gt;JavaScript Weekly&lt;/a&gt; - news from JS world, upcoming additions to JS, cool projects and tools. Tutorials and community articles.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stackshare.io/"&gt;StackShare Weekly&lt;/a&gt; - since I’m a bit a tooling geek, I have an account on StackShare and get their newsletter. It contains a list of new interesting tools and case studies about scaling infrastructure. Not extra relevant for a front-end dev, but if you are into DevOps, this may be an interesting option for you.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lengstorf.com/newsletter/"&gt;Jason Lengstorf newsletter&lt;/a&gt; - Jason mostly writes about motivation and productivity. Apart from articles on his blog, he also sent extra stuff in the newsletter. Since I’m running my own blog and working on &lt;a href="https://qjub.app/"&gt;Qjub&lt;/a&gt; in my free time, these topics are quite relevant to me (combining day job with two little kids, blog/side-project and to have some free time for me and my wife is pretty difficult).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tinyreact.email/"&gt;Tiny React&lt;/a&gt; - 3 links about React each week. Short and simple (I like those).&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://esnextnews.com/"&gt;ES.next news&lt;/a&gt; - latest news from JS world, what is coming to spec. New tools etc. Similar to JavaScript Weekly mentioned above. Some info is the same in both (like new spec and releases), but not all.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://calibreapp.com/newsletter"&gt;Calibre’s performance newsletter&lt;/a&gt; - a newsletter about web performance and how to improve it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Twitter #
&lt;/h2&gt;

&lt;p&gt;I also follow a bunch of smart and amazing people on Twitter, so I get some gems and new ideas from here as well. But because of Twitter’s nature and my attempt to limit my time there, it’s not an extra reliable source to keep up to date with front-end dev. Never the less if you want to who I follow, check my Twitter profile (I mostly follow people whos blog I read).&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>learning</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Optimizing CSS for faster page loads</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Sun, 02 Aug 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/optimizing-css-for-faster-page-loads-ffb</link>
      <guid>https://forem.com/pustelto/optimizing-css-for-faster-page-loads-ffb</guid>
      <description>&lt;p&gt;Not long ago I decided to improve the loading times of my website. It already loads pretty fast, but I knew there was still room for improvement and one of them was CSS loading. I will walk you through the process and show you how you can improve your load times as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why loading time matters?
&lt;/h2&gt;

&lt;p&gt;Because &lt;strong&gt;Time is money&lt;/strong&gt;. That proverb is especially true for webpage load times. Your page load time has a direct impact on your profit. People are more likely to buy something on a fast e-shop than on the slow one. According to study &lt;a href="https://www2.deloitte.com/ie/en/pages/consulting/articles/milliseconds-make-millions.html"&gt;Milliseconds make millions&lt;/a&gt; improvement by 0.1s on mobile site increased conversions by 10.1% and order value by 1.9% on Travel sites. That can be a lot of money.&lt;/p&gt;

&lt;p&gt;So if you want to build a profitable business, you shouldn’t underestimate your page load times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;em&gt;There is more studies confirming this pattern. I used an example from the study mentioned above because it's the most recent one I could find.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How does CSS affect load times
&lt;/h3&gt;

&lt;p&gt;To see how CSS affects the load time of a webpage we first have to know how the browser converts an HTML document into a functional webpage.&lt;/p&gt;

&lt;p&gt;First, it has to download an HTML document and parse it to create DOM (Document Object Model). Any time it encounters any external resource (CSS, JS, images, etc.) it will assign it a download priority and initiate its download. Priorities are important because some resources are critical to render a page (eg. main stylesheet and JS files) while others may be less important (like images or stylesheets for other media types).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;em&gt;HTTP/1.1 has also a hard limit on the number of connections per one domain (the exact number depends on the browser, it's usually 6 these days). So if you want to download a large number of resources from one domain some of them have to wait in a queue until resources with higher priorities finish downloading. So keep the number of requests small when using HTTP/1.1. HTTP/2 doesn't have this limitation, but not all sites are using HTTP/2 so far.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the case of CSS, this priority is usually high because stylesheets are necessary to create CSSOM (CSS Object Model). To render a webpage browser has to construct both DOM and CSSOM. Without those browser will not render any pixels on the screen. The reason for this is that styles define the look of the page and rendering page first without them would be a waste of processing powers and bad user experience. Only when the browser has both DOM and CSSOM available it can create render tree by combining them and start rendering the screen. In short no CSS downloaded, no page rendered.&lt;/p&gt;

&lt;p&gt;As you can see CSS has a huge impact on the load time of your webpage. There are two basic areas affecting webpage load time when we talk about CSS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;CSS file size and the total amount of CSS on the page (number of files). Too large CSS files will take a longer time to download and thus the entire page will take much more time to render (it has to wait for that big CSS to download first).&lt;/li&gt;
&lt;li&gt;When and how we initiate and download our CSS. You want to download your styles as soon as possible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s see in detail how we can improve those.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limit size of your stylesheet #
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; Configure your tools correctly to use modern code whenever possible.&lt;/p&gt;

&lt;p&gt;If you want to faster load times, making your CSS files smaller is a good idea. These days it’s pretty common to use some tool to modify the CSS on build time (either post processor or &lt;a href="https://postcss.org/"&gt;PostCSS&lt;/a&gt;) to provide fallbacks for older browsers or some other enhancements.&lt;/p&gt;

&lt;p&gt;I would suggest checking the result code for unnecessary bloat. Especially if you are using PostCSS with multiple plugins. In my case, I had CSS with generated fallbacks for CSS variables and with prefixes for older flexbox syntax. That may seem like a trivial issue with very little effect, but resulting savings were around 3 kB for small stylesheet like mine. I think that is a great improvement for very little work. And for large CSS it has the potential to have an even bigger impact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;old index.css: 12.5kB (without GZip)
new index.css: 9.2kB (without GZip, ~26.4% smaller)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All I had to do was to update a &lt;a href="https://github.com/browserslist/browserslist"&gt;browserslist&lt;/a&gt; config which is used by Autoprefixer and other similar tools to target generated code for specific browser versions. I have updated my PostCSS config a bit as well. (I also added the plugin to concatenate media queries together to save some extra space). See the &lt;a href="https://github.com/Pustelto/personal_web/blob/master/src/styles/index.11ty.js"&gt;PostCSS config in the source code&lt;/a&gt; and &lt;a href="https://github.com/Pustelto/personal_web/blob/master/package.json#L47"&gt;my browserslist definition&lt;/a&gt; if you want to see my exact setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use critical CSS #
&lt;/h2&gt;

&lt;p&gt;So we shrank our CSS file, but we still need to download it. We can speed up the webpage load time by reducing network requests. And best network requests are no requests at all. We can inline our styles directly into the HTML to avoid the need for downloading any external stylesheets and thus saving some time.&lt;/p&gt;

&lt;p&gt;Of course, including an entire 9kb stylesheet (or large for bigger projects) on every page is not very effective. So we will include only the styles necessary to render the part of the page &lt;em&gt;above the fold&lt;/em&gt; and lazy-load the rest of the styles. That way we can still leverage browser caching for other pages and make our webpage load faster. Since we include styles that are critical for page rendering this technique is called &lt;em&gt;Critical CSS&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HKweEWUE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ea99zsxquf2b79ceffal.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HKweEWUE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ea99zsxquf2b79ceffal.jpg" alt="Above the fold is the content visible right away after page loads. Content not visible without scrolling is below a fold."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luckily you don’t have to decide what styles should be included in the HTML. Some tools will do it for you, like &lt;a href="https://github.com/addyosmani/critical"&gt;Critical&lt;/a&gt; from Addy Osmani. Please keep in mind this technique is about compromises. You need to find the right balance between what to include and the size of the CSS since this technique will save you one request when loading page but it also makes each page bigger (and thus makes it longer to download). So you want to experiment with this and measure the results to find the best setup for your site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy-load stylesheets #
&lt;/h2&gt;

&lt;p&gt;Since we use Critical CSS we want to lazy-load our stylesheets to avoid blocking the render of the page. Unless you need to support some old browsers, modern solution these days is using normal link tag you use for stylesheets but with different media type and a little bit of JS. This clever little trick is fully described in the &lt;a href="https://www.filamentgroup.com/lab/load-css-simpler/"&gt;Filament Group blog post&lt;/a&gt;. Below you can see the snippet for lazy-loading CSS from the post, but I suggest reading the entire thing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;em&gt;If you use Critical package from above, it transforms your stylesheet to be lazy loaded like that automatically.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You may want to include fallback when JS is disabled. That way your styles will load normally and you will avoid unstyled content which would badly affect user experience.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'"&amp;gt;
&amp;lt;noscript&amp;gt;
  &amp;lt;link rel="stylesheet" href="/path/to/my.css" media="screen"&amp;gt;
&amp;lt;/noscript&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the waterfall diagrams below you can see that page with critical CSS starts rendering right away (violet portion of the graph in &lt;em&gt;Browser main thread&lt;/em&gt; row) and is interactive much sooner compared to the old version where CSS file has to be downloaded first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OlR3XzYb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0y0v1ddo87fwibw358u2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OlR3XzYb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0y0v1ddo87fwibw358u2.jpg" alt="Page starts rendering after 3.6 seconds and is interactive after 3.8 seconds when loading stylesheet normal way using link tag"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KCCWWval--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4nset1o45envo3c12qgb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KCCWWval--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4nset1o45envo3c12qgb.jpg" alt="Page starts rendering after 3.2 seconds and is interactive after 3.3 seconds when using critical CSS and lazy loading of stylesheets."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Use code-splitting for your stylesheets #
&lt;/h2&gt;

&lt;p&gt;We have CSS with properties we need for modern browsers and we use critical CSS and lazy-load the rest. But we can probably decrease our file size a bit more. In Chrome dev tools there is a tool called Coverage. It can show you what portion of CSS and JS files is used on the current page. Open dev tools and press Ctrl+Shift+p to open a command pallet and type &lt;em&gt;Coverage&lt;/em&gt;. Select &lt;em&gt;Show coverage&lt;/em&gt; option to show the panel. Now reload the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BGnaiQUq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tgxsoovv9r8pu1ncpe8h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BGnaiQUq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tgxsoovv9r8pu1ncpe8h.jpg" alt="Coverage report for my home page before any optimizations, over 45% of the CSS is not used on the page."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qsiuHyJv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f1wke3w4p954xs75g21p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qsiuHyJv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f1wke3w4p954xs75g21p.jpg" alt="Coverage report for my projects page before any optimizations, over 53% of the CSS is not used on the page."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had almost 50% of my CSS code unused on the page. When we check another page we get even more – almost 54% of unused CSS. That’s a lot of unnecessary code. And this number can be even bigger on large legacy apps.&lt;/p&gt;

&lt;p&gt;When using JS we often use code-splitting to create multiple smaller files (bundles). We download those bundles when needed them instead of fetching one large JS bundle on page load. We can use a similar approach for CSS as well. We can split our CSS in three different ways.&lt;/p&gt;
&lt;h3&gt;
  
  
  Split CSS based on media queries #
&lt;/h3&gt;

&lt;p&gt;In this approach, you split your big CSS into smaller stylesheets based on your media queries (PostCSS have &lt;a href="https://github.com/hail2u/node-css-mqpacker"&gt;plugin&lt;/a&gt; for that) and reference those stylesheets in your HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" href="index.css" media="all" /&amp;gt;
&amp;lt;link rel="stylesheet" href="mobile.css" media="(max-width:44.9375rem)" /&amp;gt;
&amp;lt;link rel="stylesheet" href="table.css" media="(min-width: 45rem)" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be aware that this approach doesn’t make much sense when using Critical CSS and lazy-loading of the stylesheet. The browser will download all stylesheets no matter what media query is used. It will only use media attribute to prioritize the downloads. So basically it will download CSS with a high priority for active media query and lazy-load the rest of the stylesheets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Page based code-splitting #
&lt;/h3&gt;

&lt;p&gt;Another approach is to use separate CSS for each page. As we have seen above there is a lot of unused styles for different pages. It would be great if we could remove those unused styles and keep only what is necessary for a given page. This is what I choose to do. Sadly I couldn’t find any tool to do this — take one large CSS file and generate a smaller bundle for each page based on its content.&lt;/p&gt;

&lt;p&gt;Sounds fairly simple so I decided to give it a shot and build a node script which can do this kind of thing. It’s called &lt;a href="https://github.com/Pustelto/css-split"&gt;CSS Split&lt;/a&gt; and it works great for sites built using static site generator (like &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt; which I use for my site). It uses &lt;a href="https://purgecss.com/"&gt;PurgeCSS&lt;/a&gt; to remove unused styles so it should work on other non-HTML files as well (based on their documentation). I didn’t test it for anything else than HTML so when using it this way, be sure to double-check the results.&lt;/p&gt;

&lt;p&gt;Using this technique I was able to reduce the file size of requested CSS by almost 50%. Below are some stats after implementing Critical CSS and page based code-splitting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;single index.css for all pages: 9.2kB (without GZip)
CSS file for homepage: 5.4kB (without GZip)
CSS file for projects: 4.4kB (without GZip)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DRc5_Bgm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9myodqt6cdc8tanagl34.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DRc5_Bgm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9myodqt6cdc8tanagl34.jpg" alt="Coverage report for my home page after code-splitting, only around 400 bytes are unused."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BnBKUvvA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r1tk2qtjyb0pumerjsfm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BnBKUvvA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r1tk2qtjyb0pumerjsfm.jpg" alt="Coverage report for my projects page after code-splitting, only around 400 bytes are unused."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that there are still some unused bytes. That’s ok as Coverage doesn’t include hover or focus states or queries. It is unlikely that you will ever get unused bytes to 0.&lt;/p&gt;

&lt;h3&gt;
  
  
  Component based code-splitting #
&lt;/h3&gt;

&lt;p&gt;I’ve got this tip from &lt;a href="https://csswizardry.com/"&gt;Harry Roberts&lt;/a&gt;. We can also split CSS on the component basis and only load progressively CSS for components we use on the page (footer, header, article, etc.). You can read more about this neat trick in &lt;a href="https://csswizardry.com/2018/11/css-and-network-performance/"&gt;Harry’s article&lt;/a&gt;. This technique I’m talking about is described in the last section of the article. But read the entire article, it’s full of great info about improving CSS network performance I don’t cover here (couldn’t write it better anyway).&lt;/p&gt;

&lt;p&gt;I still didn’t test this technique to see how well it will work compared to my current setup, but it’s on my To-do list. So stay tuned for some future article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary #
&lt;/h2&gt;

&lt;p&gt;Even though my site is fairly simple and doesn’t have too much room for improvements, by using the techniques mentioned there I was able to speed up the initial load of my webpage and lower the total size of assets. You can use the same process for any webpage to improve it’s loading performance (probably with better results for larger projects).&lt;/p&gt;

&lt;p&gt;Below you can see some final results after the updates. Graphs show what percentage of the page was rendered at what time. Those tests were run on a slow 3G connection, that’s why it takes so long to load the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NkyNiIdw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aqxzv3wujh7pyzxy4dt2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NkyNiIdw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aqxzv3wujh7pyzxy4dt2.jpg" alt="Graph comparing time to fully render homepage before and after optimizations. Homepage loads around 0.2 second faster after optimizations."&gt;&lt;/a&gt;&lt;/p&gt;
Homepage – final comparison



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sJrJLlkl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/volxtviy0ggmmjfmcsu6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sJrJLlkl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/volxtviy0ggmmjfmcsu6.jpg" alt="Graph comparing time to fully render projects page before and after optimizations. Page loads around 0.5 second faster after optimizations."&gt;&lt;/a&gt;&lt;/p&gt;
Projects page – final comparison



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tbPpqsh2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zwgzlu6gny7y83w48l5t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tbPpqsh2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zwgzlu6gny7y83w48l5t.jpg" alt="Graph comparing time to fully render single blog post before and after optimizations. Page loads around 0.6 second faster after optimizations."&gt;&lt;/a&gt;&lt;/p&gt;
Single article – final comparison



</description>
    </item>
    <item>
      <title>What have I learned when releasing Qjub</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Fri, 05 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/pustelto/what-have-i-learned-when-releasing-qjub-3a6o</link>
      <guid>https://forem.com/pustelto/what-have-i-learned-when-releasing-qjub-3a6o</guid>
      <description>&lt;p&gt;Some time ago, I have finally released &lt;a href="https://qjub.app/"&gt;Qjub&lt;/a&gt; in private beta. It was a great feeling to finally kick it off the door. And a big relief as well. However, getting to that moment was not an easy task. This week I had a little time to reflect on that journey. And I would like to share my experience and the lessons I learned with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR - Lessons I have learned #
&lt;/h2&gt;

&lt;p&gt;For those who do not have time or do not want to read the entire article:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Steady small progress &amp;gt; occasional big chunks of work - it keeps momentum and eventually may give you more time.&lt;/li&gt;
&lt;li&gt;Set fixed deadlines and stick with them as much as you can.&lt;/li&gt;
&lt;li&gt;Cut unnecessary things and do not be afraid to release unpolished features or apps.&lt;/li&gt;
&lt;li&gt;Releasing is hard - you had to check and prepare so many little things which are often important, that it will take you a huge chunk of your time. Take it into account when planning the initial launch of your project.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Full story #
&lt;/h2&gt;

&lt;p&gt;Let’s start with a little background. When I start my current job I had to learn a lot of new stuff and I wanted to get better. So I start building Qjub. To learn in-depth all the new stuff I used in my work and to build something to help myself.&lt;/p&gt;

&lt;p&gt;You see, I tend to collect a lot of resources across the web. Web development tips, books I want to read, cooking recipes, and design inspiration. But I had always had those things at different locations. Finding that one thing I was looking for was difficult. None of the products I tried worked for me, so I decided to build my own solution. Building Qjub was like to kill to birds with one stone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistent work on stuff that matters #
&lt;/h3&gt;

&lt;p&gt;While Qjub was slowly taking shape, it was still mainly a learning project without any pressure to release it. Somewhere along the way, I decided to go all-in and make Qjub available to everyone as an app. With the eventual prospect of getting some income from it (and ideally building it full time).&lt;/p&gt;

&lt;p&gt;At that time I had like a million features I wanted to be there, some more reasonable than the others. But still too much to ever get close to release. I start by splitting the development into several milestones and assigning then a reasonable amount of tasks. Of course, I had to prioritize and make some sort of minimum viable product (aka MVP) to be able to release.&lt;/p&gt;

&lt;p&gt;I also mostly work on Qjub during free weekends. But because of children and other activities, those times were rare (sometimes I did not touch code for several months). Inspired by some podcasts and books I was reading I decide to make a change. I have started to work on Qjub each morning before I go to work for 1 hour every day. It may seem like very little time but it gave me an incredible boost in productivity and Qjub started to move forward like never before. I can confirm what many other awesome people say - working in small chunks regularly adds up, builds momentum, and eventually allow you to build much more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I decide to work on Qjub each morning before I go to work for 1 hour. It may seem like very little time but it gave me an incredible boost in productivity and Qjub started to move forward like never before.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A few months later Qjub was looking good but I still couldn’t see the end of it. I sit down and think really hard about the Qjub. What do I want it to do? What is needed for release and what can wait? This has lead to two thinks. First I drastically cut down the scope of the project for initial release. Second I set a fixed release date.&lt;/p&gt;

&lt;p&gt;Because of the fixed date, I had to keep asking what is important and what is not. I cut the scope a few more times during the remaining time to meet the deadline. This forced me to make some hard decisions and compromises. For example, I decided to postpone search functionality and board sharing. Or keep some stuff unpolished, intentionally limiting its scope and capabilities (eg. you can’t insert images to text notes at the moment). I can always make those things later if needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is always some feature you can cut down or limit its scope to meet the deadline and focus on stuff that matters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s take a closer look at the search feature and my reasoning behind not implementing it at the beginning. My reasoning behind it was that no one will need search functionality at the beginning because there will most likely be very little content. So I can build a search later before anyone needs it.&lt;/p&gt;

&lt;p&gt;This is the approach I try to use for everything in Qjub since then. Do I need this feature now? How much value does it give me? How much effort does it cost me? Building the Qjub myself, I have to think hard about my time and how to use it efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Releasing it #
&lt;/h3&gt;

&lt;p&gt;Finally, my release day approach, and I found out I’m still not ready for release. Yeah, I missed my fixed deadline, even when I tried my best and have huge support from my wife, who took care of our home and children herself so I could focus on Qjub. That was disappointing for me. But I pushed hard and finally make release two weeks later. Turns our releasing an app is more difficult than building it (at least for me). There are tons of small things to check that you can easily spend another week with just that.&lt;/p&gt;

&lt;p&gt;So when you decide to release your next big thing, take into account that the release takes some time as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving forward #
&lt;/h2&gt;

&lt;p&gt;The release of the Qjub is just a start. I plan to work on it to better suit my needs and keep my information organized and easily reachable. I have already thought about my next steps and release the &lt;a href="https://trello.com/b/hIX23oVP/qjub-public-roadmap"&gt;public roadmap&lt;/a&gt;. I also plan to write more about my journey on this blog.&lt;/p&gt;

&lt;p&gt;So stay tuned and if you found Qjub interesting give it a shot. Go to &lt;a href="https://qjub.app/#request-access"&gt;Qjub homepage&lt;/a&gt; and request access to the private beta. I will appreciate any feedback and suggestions.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>showdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>Launching private beta of Qjub</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Mon, 25 May 2020 10:39:26 +0000</pubDate>
      <link>https://forem.com/pustelto/launching-private-beta-of-qjub-45m7</link>
      <guid>https://forem.com/pustelto/launching-private-beta-of-qjub-45m7</guid>
      <description>&lt;p&gt;After a few months of hard work, I'm more than happy to announce that Qjub (read as &lt;em&gt;kjuːb&lt;/em&gt;) is now in private beta.  What started as a learning project to try new stuff and get better at front-end development evolved into a side-project I was hacking during nights and weekends. And now it's finally ready for first users.&lt;/p&gt;

&lt;p&gt;Go and request beta access &lt;a href="https://qjub.app/#request-access"&gt;here&lt;/a&gt;. Or read on if you want to know more about Qjub and my reasons behind its creation.&lt;/p&gt;

&lt;p&gt;Not wanting to do some typical app like Todo list as a learning project I choose to work on something I would like to use myself. Something where I could keep all my links, notes, and files from different sources together. So they can be easily found later. No existing solution I found worked for me. It could work only with links or quickly become messy and hard to navigate as I entered a large amount of data. My answer to that is Qjub.&lt;/p&gt;

&lt;p&gt;Getting to this point was not an easy task and it is just the beginning of my journey. I had to change priorities and make compromises to get there and I learned a lot during the process. For example naming is hard :-). Pre-release preparations and final checks are more difficult than developing the product itself (at least for me). And probably most important - less is more and sometimes Good enough is better than perfect. I will definitely write more detailed blog post about lessons learned.&lt;/p&gt;

&lt;p&gt;Feeling like Qjub could help you as well? Check out the &lt;a href="https://qjub.app/"&gt;homepage&lt;/a&gt; for more info and request access to beta to play around with it. And if you have any questions left, do not hesitate to contact me via &lt;a href="//mailto:tomas@qjub.app"&gt;email&lt;/a&gt; or on Twitter (&lt;a href="https://twitter.com/pustelto"&gt;@pustelto&lt;/a&gt; or &lt;a href="https://twitter.com/qjubapp"&gt;@qjubapp&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Tools I use for front-end dev</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Thu, 23 Apr 2020 06:16:50 +0000</pubDate>
      <link>https://forem.com/pustelto/tools-i-use-for-front-end-dev-3ekn</link>
      <guid>https://forem.com/pustelto/tools-i-use-for-front-end-dev-3ekn</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was first published at my &lt;a href="https://pustelto.com/blog/what-every-javascript-developer-should-know-about-html/"&gt;personal blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Front-end development is quite a complex discipline and you will hardly ever need only a browser and code editor (at least for bigger projects). I have decided to post a list of the tools I use for development. I hope this will help others to find some great tools they can use in their workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic stuff
&lt;/h2&gt;

&lt;p&gt;Those are the tools I use daily and I couldn't literary produce much of my work without them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com"&gt;VS Code&lt;/a&gt; - You need to write your code somewhere. My editor of choice is VS Code from Microsoft. It's free, lightweight (compared to IDEs like WebStorm), has a ton of functionality out of the box and extensions which can give it even more powers.&lt;/li&gt;
&lt;li&gt;Browsers - I use Firefox as my default browser, sometimes switching to Chrome for development. But I have installed other browsers for testing as well.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://devdocs.io"&gt;DevDocs&lt;/a&gt; - Web app which aggregates documentation from different projects. It can also work in offline mode. This my go-to page when I need to look for some documentation.
Using it mainly for JS and DOM/Browser related stuff. As I really couldn't find anything similar (easy to search and detailed). You should check it out.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://google.com"&gt;Google&lt;/a&gt; - Yes, I google things very often. Bugs, how to do stuff (sometimes pretty basic) or examples and documentations for packages and libraries (if they aren't on DevDocs).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US"&gt;MDN&lt;/a&gt; - Greate resource for any web developer. Part of this site can be accessed via DevDocs mentioned earlier, but some pages are only on MDN.
I use it mainly when I need to check some a11y related stuff as they have there some good articles about the topic.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stackoverflow.com"&gt;StackOverflow&lt;/a&gt; - Usually get there from Google. If you have some problem, you can probably find a solution there.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com"&gt;Github&lt;/a&gt; - When I have some issues with a package or just need to know more about it I dig into the source code or issues. You can find here answers to your problems almost as often as on StackOverflow. I'm personally more successful with Github issues if I have problems related to one package (unless it's React or something similar hugely popular). And of course, I use it for version control as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CSS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://css-tricks.com/"&gt;CSS-Tricks&lt;/a&gt; - Aside from their blog where you can find a ton of interesting articles and tips there is also a guide section with in-depth articles about certain HTML/CSS and JS concepts. I usually go there if I need to refresh my Grid knowledge. But other guides are great as well, so definitely worth checking it out.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://tympanus.net/codrops/css_reference"&gt;CSS Reference&lt;/a&gt; - If I need to refresh some of my CSS knowledge or use some property I do not know/use very often, this is my go-to resource. It contains an in-depth explanation of every CSS property with clear examples so it's easy to understand and use in your project. Written by excellent &lt;a href="https://www.sarasoueidan.com"&gt;Sara Soudain&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://caniuse.com"&gt;Can I Use&lt;/a&gt; - A must-have tool if you care about browser support and using cutting edge features responsibly (aka progressive enhancement).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance and optimizations tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jakearchibald.github.io/svgomg"&gt;SVGOMG&lt;/a&gt; - You will rarely get SVG from designer optimized for the web. In such cases, I will use SVGOMG to optimize and minify the SVG. You would be surprised how much of useless stuff you can get rid of. It's web GUI for &lt;a href="https://github.com/svg/svgo"&gt;SVGO&lt;/a&gt;, so you can get the same results from CLI if you want to.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://shrinkme.app"&gt;Shrinkme.app&lt;/a&gt; - Web app when I need to quickly optimize images. It supports batch uploads and provides very good results out of the box.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://squoosh.app"&gt;Sqoosh&lt;/a&gt; - When I need to squeeze every last drop of performance from images or need to create images in webp format. A lot of options to play with to get the results you need.
You can also resize images and convert them to different formats. It's fairly cutting edge (it was done as a demo of what modern browsers can do by Google Chrome team) so you have to use Chrome or another Chromium-based browser (Opera, Brave, etc.). It didn't work properly in Firefox last time I test it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://icomoon.io/app/#/select"&gt;Icomoon app&lt;/a&gt; - My go-to tool when I need to create a custom icon set. You can choose from existing icons (free or paid) or upload your own. Then you can either use that to generate icon font or SVG icon set (which is a better solution these days).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fonts.google.com"&gt;Google Fonts&lt;/a&gt; - When I want some custom web fonts, this is usually my first stop. I usually download the files I need and self-host it myself (for better performance). What is great is that you can select only encoding you need and avoid downloading unnecessary characters.
&lt;strong&gt;NOTE:&lt;/strong&gt; You could select encoding on the old Google Fonts page, but I can't fount it anywhere on their new site. If you know where it is (or if it is there at all), let me know, please.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/filamentgroup/glyphhanger"&gt;Glyphhanger&lt;/a&gt; - Decreasing file size is one of the best ways how to improve the performance of the website. Web fonts often use many glyphs we do not need so I use Glyphhanger for font subsetting.
You can specify Unicode ranges or characters you want in the font and Glyphanger will create a new font file for you with only specified characters. It can also convert &lt;code&gt;.ttf&lt;/code&gt; files to other formats much more suitable for the web. like &lt;code&gt;.woff&lt;/code&gt; and &lt;code&gt;.woff2&lt;/code&gt;. Take a bit of effort to use it right, but I think it's an option worth considering when font performance is an issue.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/GoogleChrome/lighthouse"&gt;Lighthouse&lt;/a&gt; - I test the webpages before releasing them and one of the tools I use most often is Lighthouse audit in Chrome browser. It checks for the most common issues in several areas and gives you score for each area as well as hints on how to improve. It's great as a first check to see if there are any problems I forgot to address during development.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://meowni.ca/font-style-matcher"&gt;Font style matcher&lt;/a&gt; - If you want to make font swap less noticeable after your custom fonts are loaded you can use this great tool to match the styles of your default and custom fonts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Accessibility (a11y for short)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;VoiceOver - default screen reader on macOS. It takes little practice to use it (I found &lt;a href="https://webaim.org/articles/voiceover"&gt;this article about it&lt;/a&gt; very useful), but I try to regularly use it in the development process. Thanks to that my usage of aria attributes and screen-reader only text has increased significantly. You would be surprised how very little context and information some ordinary webpage components have for the user depending on a screen reader.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://a11yproject.com/patterns"&gt;a11y guidelines&lt;/a&gt; - I usually try to find some existing solution with good a11y but that is not always possible. In that case, if I need to create some interactive component with accessibility in mind, I will go to this page. You can find a detailed explanation of what, why and how. Together with example codes, you can often copy and reuse with a little effort.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/TR/wai-aria-1.1"&gt;WAI-ARIA specification&lt;/a&gt; - I don't ready specifications very often. But when I do, it's usually this one. It contains a lot of valuable information about aria roles and attributes and how to use them. I would say this is mandatory reading for anyone who takes a11y seriously&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Honorable mentions
&lt;/h2&gt;

&lt;p&gt;And last but not least there is a list of other tools I found useful, but not using them that often.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://responsivebreakpoints.com"&gt;Responsive breakpoints generator&lt;/a&gt; - Manually creating responsive images with a lot of variants is a pain. This is a great tool to lessen that pain.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.toptal.com/designers/htmlarrows"&gt;HTML Arrows&lt;/a&gt; - List of special characters together with Unicode code (in different contexts like CSS, JS, plain Unicode) and HTML entity to use them safely on a web. I use it now and then when I want to have good typography.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.w3.org/html5/html-author/charref"&gt;Char reference&lt;/a&gt; - Similar to the tool above, but contains less information. It shows mainly HTML entities, so if that is what you need this may be a better option.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.typewolf.com/cheatsheet"&gt;Typography cheatsheet&lt;/a&gt; - Explains common typography rules and issues. If you want to improve your typesetting on the web, this is a good starting point.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.modularscale.com"&gt;Modular scale&lt;/a&gt; - When I work on a design I usually pick some modular scale using this tool. It helps you create a harmonical vertical rhythm. To learn more about it I recommend reading &lt;a href="https://alistapart.com/article/more-meaningful-typography/"&gt;this article on A List Appart&lt;/a&gt; or this &lt;a href="https://vimeo.com/17079380"&gt;recording of Tim Brown talk&lt;/a&gt; from Build Conf 2010.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cssgradient.io"&gt;CSS gradient generetor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://brumm.af/shadows"&gt;Smooth shadow generator&lt;/a&gt; - When you want to have great looking shadows on your web.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cubic-bezier.com"&gt;Bezier curve generator&lt;/a&gt; - Custom timing function for your animation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://easings.net/en"&gt;Easing functions&lt;/a&gt; - Library of different easing functions ready to use in your CSS animations and transitions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ngrok.com"&gt;ngrok&lt;/a&gt; - I use it when I need to show some of my work running on localhost to someone else or if I need to test on different devices. Sometimes using it with Browserstack when their localhost extension refuses to work.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sharingbuttons.io"&gt;sharing buttons&lt;/a&gt; - This is a jewell if you need simple sharing buttons without all the JS and tracking mess around them.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dencode.com/en/date"&gt;Unix timestamp converter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://css2js.dotenv.dev/"&gt;CSS to JS converter&lt;/a&gt; - This may be handy when you work with CSS-in-JS library and need to convert from CSS to JS or vice versa.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://browserdefaultstyles.com"&gt;Browser default styles&lt;/a&gt; - List of default styles for common browsers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The end
&lt;/h2&gt;

&lt;p&gt;That's it. Those are the tools I used for my work and which help me to be productive and provide high-quality work. I hope you will find some of them useful. If yes please let me know on Twitter or in the comments. Or if you have some other great suggestions I would love to hear about them as well.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>tools</category>
    </item>
    <item>
      <title>Don't ignore Fieldset and Legend HTML elements</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Mon, 06 Apr 2020 03:24:00 +0000</pubDate>
      <link>https://forem.com/pustelto/don-t-ignore-fieldset-and-legend-html-elements-2e67</link>
      <guid>https://forem.com/pustelto/don-t-ignore-fieldset-and-legend-html-elements-2e67</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was first published at my &lt;a href="https://pustelto.com/blog/dont-ignore-fieldset-and-legend-html-elements/"&gt;personal blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Creating accessible forms (especially more complex ones) may be difficult. There are many moving parts and different kinds of inputs. And we often have to use JavaScript to make the form accessible for all (check this &lt;a href="https://daverupert.com/2020/02/html-the-inaccessible-parts/"&gt;great summary from Dave Rupert to see what native HTML inputs are not accessible&lt;/a&gt;). But on the other hand, there are HTML tags which can help us a lot with structuring our form and make a great deal of work to make it more accessible. There is for example a &lt;code&gt;&amp;lt;datalist&amp;gt;&lt;/code&gt; element which got &lt;a href="https://gomakethings.com/how-to-create-an-autocomplete-input-with-only-html/"&gt;some spotlight recently&lt;/a&gt;. Other useful elements are &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt;. Today I want to talk about those two.&lt;/p&gt;

&lt;p&gt;Maybe you have heard about them, but a quick introduction won't hurt. This is what specification says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; element represents a set of form controls optionally grouped under a common name.&lt;/p&gt;

&lt;p&gt;The name of the group is given by the first &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt; element that is a child of the &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; element, if any. The remainder of the descendants form the group.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A typical example could be a billing and delivery addresses or a bunch of checkboxes to select your interests. Those inputs create a logical group and for better accessibility, you should enclose the in the fieldset. Legend serves as heading for the fieldset and to make fieldset useful, you have to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are they good for?
&lt;/h2&gt;

&lt;p&gt;Now let's have a look at why using &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt; is a good idea. Nothing will change for normal users using their sight and mouse to navigate on the screen. But it's a big help for users with a screen reader. The screen reader will announce the fieldset as a group of elements together with its name defined in &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt;. This is great as it gives users additional context about the upcoming fields (is it delivery or billing address). Some screen readers (like JAWS) will even read the legend before each input in the group.&lt;/p&gt;

&lt;p&gt;You may argue that you can simply add some text before the inputs (like heading) and give the user the same information. That's not entirely true. First, it may confuse the user as there is no clear connection between the group of form elements and the text you provided. Second, some screen readers have a special mode to work with the forms and in this mode, non-form elements may be ignored (so your heading will not work).&lt;/p&gt;

&lt;p&gt;Fieldset has one more great benefit. You can simply put the disabled attribute on it and it will disable all the input fields in it. So no extra delivery address? Sure just put one disabled there and you are done. Isn't that great? And by the way, you can use this trick on the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element itself to disable the entire form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some downsides
&lt;/h2&gt;

&lt;p&gt;As with most things in life, nothing is always perfect.&lt;/p&gt;

&lt;p&gt;Not all screen readers will announce the fieldset. Some will ignore it and read only a text contained in a &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt; as a normal text. This also depends on the browser as I have found. For example, VoiceOver (native macOS screen reader) will announce the fieldset correctly in Chrome, but not in Firefox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sidenote:&lt;/strong&gt; It seems this should be addressed in Firefox 76. Mozilla is aware of compatibility issues with Firefox and VoiceOver and is working on them. You can see &lt;a href="https://wiki.mozilla.org/Accessibility/Mac2020#Basic_VoiceOver_Support" rel="noopener"&gt;this page for a full overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Styling of &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt; also takes a little bit more effort, than using headings or some text element. But that shouldn't be an excuse for not using them.&lt;/p&gt;

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

&lt;p&gt;Don't be afraid of fieldset and legend tags. For very little effort, they help you structure your form and give users extra context about the purpose of the form fields. And as front-end developers, we should always aim for a more accessible solution.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>frontend</category>
      <category>html</category>
    </item>
    <item>
      <title>What every JavaScript developer should know about HTML and CSS</title>
      <dc:creator>Tomas Pustelnik</dc:creator>
      <pubDate>Mon, 24 Feb 2020 04:38:54 +0000</pubDate>
      <link>https://forem.com/pustelto/what-every-javascript-developer-should-know-about-html-and-css-2f82</link>
      <guid>https://forem.com/pustelto/what-every-javascript-developer-should-know-about-html-and-css-2f82</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was first published at my &lt;a href="https://pustelto.com/blog/what-every-javascript-developer-should-know-about-html/"&gt;personal blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Writing web apps in React or other JS frameworks doesn't mean you don't need to have a solid foundation of HTML and CSS. While you may be fine most of the time with basic knowledge, having more in-depth knowledge will help you create a much more accessible, robust and maintainable code. And in the end, deliver better products to your users.&lt;/p&gt;

&lt;p&gt;I have put together several concepts and practices I believe every frontend developer should know (not just JavaScript developers, but I often see the biggest lack of knowledge there).&lt;/p&gt;

&lt;p&gt;To avoid the article to be too long, I introduce only the necessary basics in each area and provide links to more resources on the web if you wish to learn more. There are many great articles about each of the topics mentioned here, but I found it useful to have it in one place like this.&lt;/p&gt;

&lt;p&gt;So let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use HTML elements with correct semantics
&lt;/h2&gt;

&lt;p&gt;One of the best (and probably easiest) things you can do for accessibility of your web is to use semantic markup. Yet often developers just tend to use &lt;code&gt;divs&lt;/code&gt; and &lt;code&gt;spans&lt;/code&gt;. But HTML is more than just that. It stands for &lt;em&gt;Hyper Text Markup Language&lt;/em&gt; and the &lt;em&gt;markup&lt;/em&gt; word is important. HTML is used to give a structure and meaning to the document. That can hardly be achieved with the bunch of &lt;code&gt;divs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I don't say you should stop using &lt;code&gt;divs&lt;/code&gt; and &lt;code&gt;spans&lt;/code&gt;. I use them a lot myself. But they have no semantical meaning. They are just containers to help you style your web page and section the content inside other HTML tags which do have meaning. You have probably heard and used heading elements (&lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;h2&lt;/code&gt; and so on), &lt;code&gt;nav&lt;/code&gt;, &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt;. Those are probably the most common semantic elements (added in HTML5). Using these is a good start. But there is much more. Do you know there are elements for abbreviations or keyboard input? Just check &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element"&gt;element reference on MDN&lt;/a&gt; to get the full list with explanations (I strongly suggest to read it).&lt;/p&gt;

&lt;p&gt;And why exactly is it important to use semantic markup? As I mentioned at the beginning of this section, accessibility is the main reason. People using screen readers can easily navigate using headings or so-called landmarks (you can think of a landmark as an important part of the web page). Landmark is created by using semantic HTML like &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;. The second reason is that screen readers also announces what landmark is a user on (like &lt;em&gt;main content&lt;/em&gt; or &lt;em&gt;navigation&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Another way how to create a landmark is to use &lt;code&gt;role&lt;/code&gt; attribute on HTML element eg. &lt;code&gt;&amp;lt;ul role="navigation"&amp;gt;&lt;/code&gt;. This is useful when creating some more advanced UI components (like menu button with dropdown etc.). But I strongly recommend using existing HTML tags whenever possible.&lt;/p&gt;

&lt;p&gt;Semantic markup provides us with the context of what we are looking at. But it can also help machines (search engines or some reading devices) understand the structure of the document and display it accordingly. I recommend reading this great &lt;a href="https://www.brucelawson.co.uk/2018/the-practical-value-of-semantic-html/"&gt;article from Bruce Lawson&lt;/a&gt; about the value of semantic markup.&lt;/p&gt;

&lt;p&gt;Here is some advice on how to start with semantic markup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;h&lt;/code&gt; tags of proper level (don't skip heading levels) to create a correct outline of the document.&lt;/li&gt;
&lt;li&gt;Start using &lt;code&gt;nav&lt;/code&gt;, &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;article&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check other HTML tags to see what else you can use and try to slowly incorporate them into your toolbelt.&lt;/li&gt;
&lt;li&gt;Read more about this topic, for example &lt;a href="https://www.smashingmagazine.com/2020/01/html5-article-section/"&gt;article on Smashing Magazine about section vs article&lt;/a&gt; or &lt;a href="https://css-tricks.com/how-to-section-your-html/"&gt;article on CSS-tricks about structuring document&lt;/a&gt; (be sure to read the comments in this one as well, there is a lot of good info).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learn how to use form elements
&lt;/h2&gt;

&lt;p&gt;Forms are often one of the most complex parts of the web app – a lot of states and moving parts. For a great UX, it is essential that all these parts work smoothly and as a user expects. Nothing kills a good impression from your web like a form you can't submit with Enter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrap forms in &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element
&lt;/h3&gt;

&lt;p&gt;It seems obvious, right? But I have seen forms without it. Especially in today's world of JS frameworks, it's easy to create a form-like component without it. But unless it's something simple as a standalone button with some specific functionality (like a toggle for menu) you should always use &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element. Your users will thank you. First, it tells screen readers that this is a form (we already talk about semantic markup). Second, it gives you standard UX behavior out of the box -- submitting the form on pressing Enter, ability to submit or reset form via a button and listen on form submit event to process submission.&lt;/p&gt;

&lt;h3&gt;
  
  
  Always use inputs with labels
&lt;/h3&gt;

&lt;p&gt;Inputs have to have a label, it tells the users what the input is for. Not a placeholder or some &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; but a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element. Placeholder is only a visual hint, it disappears once we enter something into the input field and some screen readers can ignore them (for a more detailed explanation why you should use labels instead of placeholder attribute see this &lt;a href="https://joshuawinn.com/ux-input-placeholders-are-not-labels/"&gt;great summary&lt;/a&gt; from Joshua Winn). So use &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; instead and connect it to the input field with for attribute like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--
 or nest the input into the label,
 that way id is not required, if you nest only one input :-)
--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"surname"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- or --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;Address&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way when you click on a label a connected input field will get focus. This is extremely important for radio buttons and checkboxes since &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; will increase the touch area of the radio/checkbox and make them easier to select on mobile devices.&lt;/p&gt;

&lt;p&gt;If you can't use &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; for some reasons you may use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute"&gt;aria-label&lt;/a&gt; or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-labelledby_attribute"&gt;aria-labelledby&lt;/a&gt; attributes as an alternative. But native &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element should be always your first candidate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use type attribute on a button element
&lt;/h3&gt;

&lt;p&gt;Since you are using &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element for your forms you want to always set type attribute on your buttons. There are three possible values - &lt;code&gt;submit&lt;/code&gt;, &lt;code&gt;reset&lt;/code&gt; and &lt;code&gt;button&lt;/code&gt;. Submit and reset values are useful only nested in &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element (first submits the form, the second one will clear the input fields in the form). Type &lt;code&gt;button&lt;/code&gt; is a generic type for all other buttons (menu toggles, showing/closing modals, etc.).&lt;/p&gt;

&lt;p&gt;And why should you always specify it? Because button elements without type attribute specified get the type set to &lt;code&gt;submit&lt;/code&gt; by default. And it can lead to bugs when in the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element since you can submit a form unintentionally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make things accessible
&lt;/h2&gt;

&lt;p&gt;Accessibility (a11y for short) is hard, especially in single-page applications it can be a daunting task. I struggle with it sometimes as well. But we should still try to make our products as much accessible as possible. While there is a lot to cover in terms of a11y (enough for a separate blog post or more likely a book). Most common issues I encounter often are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;sites aren't using correct semantic markup (we already covered that)&lt;/li&gt;
&lt;li&gt;and they are hard to use without a mouse&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are a few things you can do to mitigate those issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Always provide styles for focused interactive elements
&lt;/h3&gt;

&lt;p&gt;All interactive elements have default browser styles for focus state (usually in the form of outline). Users browsing the web using a keyboard use it to see where they are on the page. Remove it and the user does not see any feedback on his position (what element he can click on). It's like driving in the dark night without lights turned on. You have no idea where you are and what will happen if you turn the wheel.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Removing focus ring and failing to provide an alternative to the users is the same as driving a car in the dark night without lights turned on. You have no idea where you are and what will happen if you turn the wheel.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you absolutely have to remove the default one, replace it with another visual hint (based on your design system) when an element is focused. But never remove it entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use correct elements for interactions in the app
&lt;/h3&gt;

&lt;p&gt;We are back to semantic HTML. Native interactive elements like buttons and inputs can be controlled by a keyboard and focused out of the box. No JS or special attributes required. If you need a link, use &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; not a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with some javascript dark magic.&lt;/p&gt;

&lt;p&gt;Of course, you can make &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; to behave and look like a button (even for screen readers). In all my career, I have to do it only once due to some conflicts with drag and drop in React (library did not like a button to be draggable). It was ugly, and it took some time to make it accessible. I would prefer to use the native &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;And one last thing. Use &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag when navigating to a different page, use &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; for everything else. That means no &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag with JS opening a side menu or &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; using JS to navigate to a different page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't nest buttons and links
&lt;/h3&gt;

&lt;p&gt;How would you like to have an Esc key placed on top of your Enter? Your press one and both of them are pressed. That would be super annoying, right? That's exactly what you do when you nest buttons and anchor links into each other. It's not semantically correct and it's confusing for screen reader users. Not to mentioned it can create some weird behavior in the app.&lt;/p&gt;

&lt;p&gt;How to do some more complex UI components like a clickable card with additional buttons inside of it? You will have to use a little bit of CSS and absolute positioning or wrap only some part of the component (like heading) into &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag, not the entire card. For more tips check &lt;a href="https://css-tricks.com/breakout-buttons/"&gt;this article on CSS-tricks&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Box model and sizes
&lt;/h2&gt;

&lt;p&gt;Every element on the web page is a box. You can skew it, make it round, but for a browser, it will always be a box. I have met a few developers who didn't know how exactly is the size and position of these boxes determined. That caused them some issues when they tried to style those elements. I won't go into too much detail there. Plenty of resources about this topic already exist. You may check &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model"&gt;the article about the box-model on MDN&lt;/a&gt; or &lt;a href="https://www.w3.org/TR/CSS2/box.html"&gt;dive into the spec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I want to go through a few basic things to keep in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Box-sizing CSS property
&lt;/h3&gt;

&lt;p&gt;Box-sizing property controls how the final size of the HTML element will be calculated. By default it values is &lt;code&gt;content-box&lt;/code&gt; which means that width and height attributes (and their min and max variants) affect only a content area of the element (blue part in the picture below).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6wWBcMtE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pustelto.com/blog/what-every-javascript-developer-should-know-about-html/box-model.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6wWBcMtE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pustelto.com/blog/what-every-javascript-developer-should-know-about-html/box-model.png" alt="Box model schema showing content, paddding, border and margin areas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you add padding or border to the element, it will increase its size. That may result in the element overflowing from its container and can be a cause of some confusion for people who do not know about this (especially if they use some CSS reset without knowing what it does exactly). To see the difference between &lt;code&gt;box-sizing&lt;/code&gt; set to &lt;code&gt;content-box&lt;/code&gt; and &lt;code&gt;border-box&lt;/code&gt; have a look at the codepen below.&lt;/p&gt;

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

&lt;p&gt;To make &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; properties affect the padding and border of the element as well set value of &lt;code&gt;box-sizing&lt;/code&gt; to &lt;code&gt;border-box&lt;/code&gt;. Here is a suggested way of doing this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* :root stands for html, but it has higher specificity (same as class) */&lt;/span&gt;
&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/*
 This way it's easier to override the box-sizing if needed
 (children will inherit it from parent)
*/&lt;/span&gt;
&lt;span class="o"&gt;*,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Inline elements have extra space in between them
&lt;/h3&gt;

&lt;p&gt;Again not very well known &lt;q&gt;feature&lt;/q&gt; of CSS - if you have several inline or inline-block elements next to each other, you get small space between them. If you dig deeper you will found out that CSS is not the culprit.&lt;/p&gt;

&lt;p&gt;It's because space between inline elements in the code is treated as space (space between words is a good thing most of the time). However, in some cases, it's not what you want. The easiest way of getting rid of it these days is to set &lt;code&gt;display: flex&lt;/code&gt; on the container. For more detailed info I suggest &lt;a href="https://css-tricks.com/fighting-the-space-between-inline-block-elements/"&gt;this article on CSS tricks&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Margin collapsing
&lt;/h3&gt;

&lt;p&gt;If you already have experience building websites, you have probably encountered this. You work on the page styles, adding margin-bottom to your article heading and then some margin-top to the main image just below it. But the white space between them is not the sum of both margins. It is only the size of the bigger one. That's margin collapsing.&lt;/p&gt;

&lt;p&gt;When two vertical margins meet, they will collapse. This happens between sibling elements and sometimes between parent and child (if they aren't separated by border, padding, or if there is no formating context on parent element).&lt;/p&gt;

&lt;p&gt;You may play with the codepen below to see how margin collapsing changes with different CSS properties.&lt;/p&gt;

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

&lt;p&gt;For a more detailed explanation, do check the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing"&gt;MDN page about margin collapsing&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use appropriate sizing units
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; Don't use pixels.&lt;/p&gt;

&lt;p&gt;CSS offers a variety of different length units. Probably the most well-known unit is a pixel (&lt;code&gt;px&lt;/code&gt;). My advice is – don't use it. The main reason is accessibility. You can change the default font size in the browser settings, but if you define font sizes on your web in pixels this will not work. The text will have the same size.&lt;/p&gt;

&lt;p&gt;Instead of pixels, it's best practice to use &lt;code&gt;rem&lt;/code&gt; (rem stand for root em). More precisely, use relative units as much as possible (viewport units, percentage or size elements using flexbox and grid properties) and for fixed sizes (margins, font-size, icons...), use &lt;code&gt;rem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Under normal circumstances (user did not change the font size settings in the browser) 1rem equals 16px.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rem&lt;/code&gt; works similarly to &lt;code&gt;em&lt;/code&gt; unit except its size is calculated from the font-size of the root element (&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;). Unlike with &lt;code&gt;em&lt;/code&gt;, there isn't a problem with the multiplication of the sizes – if you nest elements inside each other, font-sizes with &lt;code&gt;em&lt;/code&gt; units will infer it's size from the parent. See the codepen below for an example (I have shamelessly copied the code from &lt;a href="https://tympanus.net/codrops/css_reference/"&gt;Codedrops CSS reference&lt;/a&gt;)&lt;/p&gt;

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

&lt;p&gt;If we are talking about font sizes, we have to mention &lt;code&gt;line-height&lt;/code&gt; property as well. Always define it as a unitless number (eg. 1.5). This way browser will calculate &lt;code&gt;line-height&lt;/code&gt; as a multiple of the &lt;code&gt;font-size&lt;/code&gt;. Again this is important for accessibility to ensure enlarged texts are readable. For a detailed explanation of this (and with examples) check &lt;a href="https://www.24a11y.com/2019/pixels-vs-relative-units-in-css-why-its-still-a-big-deal/"&gt;Kathleen McMahon's article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stacking context
&lt;/h2&gt;

&lt;p&gt;The stacking context controls how elements on the page are layered on the z-axis. From the user's perspective -- how are they layered and how they overlay each other. Think of modal dialog with semi-transparent overlay covering your entire page.&lt;/p&gt;

&lt;p&gt;Sometimes you may encounter an issue where the element with high &lt;code&gt;z-index&lt;/code&gt; is covered by another element with smaller &lt;code&gt;z-index&lt;/code&gt; (even though it should be above everything else). This may be confusing for people without the idea of what and how stacking context works.&lt;/p&gt;

&lt;p&gt;There isn't usually one but several stacking contexts at the same time. And element with stacking context works like a container for its children with the &lt;code&gt;z-index&lt;/code&gt; property. &lt;code&gt;z-index&lt;/code&gt; has an effect only inside of this stacking context, but not outside. Which in practice means that element with &lt;code&gt;z-index&lt;/code&gt; value of &lt;code&gt;999&lt;/code&gt; can be cover with another element with &lt;code&gt;z-index&lt;/code&gt; value &lt;code&gt;1&lt;/code&gt;. Check the codepen below for a concrete example.&lt;/p&gt;

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

&lt;p&gt;What you usually want to do in such a case is to add or update &lt;code&gt;z-index&lt;/code&gt; on the element which creates stacking context (&lt;code&gt;header&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt; in the example codepen). Check &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context"&gt;this article on MDN&lt;/a&gt; if you want to see when exactly is stacking context created.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS specificity
&lt;/h2&gt;

&lt;p&gt;Let's have a look at the code bellow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.red.blue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="nc"&gt;.blue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"red blue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;What color do I have?&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What color will the text have? If you answered magenta, you are correct, and probably know what CSS specificity is. If you guess it incorrectly, or perhaps you are not sure why does it have magenta color and not blue, read on.&lt;/p&gt;

&lt;p&gt;Browsers apply styles in the order they appear in the source code. So later styles overwrite styles that appeared early in the document. That's how web browsers decide which styles to use in case of conflicts. This works for duplicate properties in declaration block (this way we can provide fallbacks for older browsers) and for the declaration blocks as well if we have more selectors targeting the same element.&lt;/p&gt;

&lt;p&gt;However, with multiple selectors targeting one element, there is another factor in the game and that is CSS specificity. Which brings us back to the example at the beginning of this section. The paragraph will have magenta color because the first selector (&lt;code&gt;.red.blue&lt;/code&gt;) is more specific than the second selector (&lt;code&gt;p.blue&lt;/code&gt;). You can think of specificity as the importance of given CSS rule. Bigger specificity means bigger importance and thus such rule overwrite other rules which are less specific.&lt;/p&gt;

&lt;p&gt;You can see in the image below how is the specificity calculated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lkfAG0Uf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pustelto.com/blog/what-every-javascript-developer-should-know-about-html/specificity%402x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lkfAG0Uf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pustelto.com/blog/what-every-javascript-developer-should-know-about-html/specificity%402x.jpg" alt="Schema showing how CSS specificity is calculated"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you compare the specificity of two selectors, the higher one wins and its rules will be applied. In our case &lt;code&gt;.red.blue&lt;/code&gt; has specificity &lt;em&gt;0-2-0&lt;/em&gt; (we have two classes there) and the &lt;code&gt;p.blue&lt;/code&gt; has &lt;em&gt;0-1-1&lt;/em&gt; (one class and one element selector).&lt;/p&gt;

&lt;p&gt;You can also see that id selector beats all other selectors (classes, elements, etc.) and it can be overwritten only by another id selector, inline styles or &lt;code&gt;!important&lt;/code&gt; flag. To keep your stylesheets maintainable, try to keep specificity as low as possible. Preferably use only classes to style elements and avoid id selectors at all costs. Beating rules with high specificity with even higher specificity will lead to a circle of specificity wars that is hard to broke from without some major refactoring.&lt;/p&gt;

&lt;p&gt;Last info you need to know is how inline styles and &lt;code&gt;!important&lt;/code&gt; work with specificity. Inline styles beat any selector (even id), but they are hard to override because of that. &lt;code&gt;!important&lt;/code&gt; beats everything and only another property with a &lt;code&gt;!important&lt;/code&gt; flag can override it. So be extra careful when using it. A good use case for it is in utility classes which do only one single thing and they should take effect no matter what or when overriding some third-party styles.&lt;/p&gt;

&lt;p&gt;Again if you want to learn more about it, I suggest articles on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity"&gt;MDN&lt;/a&gt; or &lt;a href="https://css-tricks.com/specifics-on-css-specificity/"&gt;CSS tricks&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;And that's it. Congratulations on reading this far, I hope you like it and find it useful. HTML and CSS may seem trivial at first and not worthy of your time. But as you have seen there are few concepts that can help you write better code, be more efficient in it and have the potential to save you or your colleagues a ton of time trying to fix poorly written front-end.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>html</category>
      <category>css</category>
    </item>
  </channel>
</rss>
