<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: codestruct.io</title>
    <description>The latest articles on DEV Community by codestruct.io (@codestructio).</description>
    <link>https://dev.to/codestructio</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%2F610105%2F86fa9480-8f52-497d-aea7-ccb5ad54ffd7.png</url>
      <title>DEV Community: codestruct.io</title>
      <link>https://dev.to/codestructio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codestructio"/>
    <language>en</language>
    <item>
      <title>The power of CSS attribute selectors</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Tue, 30 Nov 2021 15:19:31 +0000</pubDate>
      <link>https://dev.to/codestructio/the-power-of-css-attribute-selectors-3of1</link>
      <guid>https://dev.to/codestructio/the-power-of-css-attribute-selectors-3of1</guid>
      <description>&lt;p&gt;Besides the obvious utility of selecting elements with an exactly matching data attribute, there are a lot more things we can achieve with CSS attribute selectors.&lt;br&gt;
In general, the attribute selector can target &lt;em&gt;any&lt;/em&gt; attribute that's attached to an HTML element. By default, the selector is case sensitive and has a lower specificity than id's and classes.&lt;/p&gt;

&lt;p&gt;Here's an attribute selector in its simplest form, selecting every anchor element that has an &lt;code&gt;href&lt;/code&gt; attribute — regardless of the actual href URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want it to be more specific about which &lt;code&gt;href&lt;/code&gt; to target, we can explicitly pass the URL to the attribute selector like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"https://specific-url.com"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the latest &lt;a href="https://www.w3.org/TR/selectors-4/#attribute-case"&gt;specs changes&lt;/a&gt; introduced a new flag for attribute selectors, which allows us to make the matching case insensitive, by adding an &lt;code&gt;i&lt;/code&gt; after our selector. This is &lt;a href="https://caniuse.com/?search=attribute%20case"&gt;fairly well supported&lt;/a&gt; and works across all modern browsers, except IE11.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"https://specific-url.com"&lt;/span&gt; &lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* matches &amp;lt;a href="https://SpEciFic-url.com"&amp;gt;&amp;lt;/a&amp;gt; ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Special types of attribute selectors
&lt;/h2&gt;

&lt;p&gt;Besides matching an attribute with an existing attribute or a specific value, we can use other types of attribute selectors to achieve partial matching on the&lt;br&gt;
value of an attribute. These selectors can also be combined to match very specific elements.&lt;/p&gt;
&lt;h3&gt;
  
  
  CSS attribute contains
&lt;/h3&gt;

&lt;p&gt;Using the wildcard operator &lt;code&gt;*&lt;/code&gt; we can match any element that has an attribute containing the given string in any form.&lt;br&gt;
That means the example below would match the exact string &lt;code&gt;value&lt;/code&gt; but also &lt;code&gt;something value something&lt;/code&gt; as well as &lt;code&gt;somethingvaluesomething&lt;/code&gt;.&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="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-attribute&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s1"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CSS attribute starts with
&lt;/h3&gt;

&lt;p&gt;If we want to look for an attribute whose value &lt;strong&gt;starts&lt;/strong&gt; with a given string, we can use the &lt;code&gt;^&lt;/code&gt; operator lie below.&lt;br&gt;
In that case, we'd only match &lt;code&gt;value something&lt;/code&gt; and &lt;code&gt;valuesomething&lt;/code&gt; but not &lt;code&gt;something value&lt;/code&gt;.&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="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-attribute&lt;/span&gt;&lt;span class="o"&gt;^=&lt;/span&gt;&lt;span class="s1"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CSS attribute ends with
&lt;/h3&gt;

&lt;p&gt;Conversely to looking for matched at the start, we can also look at the very end of an attribute's value by useing the &lt;code&gt;$&lt;/code&gt; operator.&lt;br&gt;
We'd match &lt;code&gt;something value&lt;/code&gt; but not &lt;code&gt;value something&lt;/code&gt;. This is especially interesting because we know that files always have a certain extension and by passing&lt;br&gt;
the full name into a data-attribute, we'd be able to match elemenets that represent PDF documents like this &lt;code&gt;a[href$="pdf"]&lt;/code&gt;.&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="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-attribute&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CSS attribute is in space-separated or dash-separated lists
&lt;/h3&gt;

&lt;p&gt;There are two selectors that allow us to specifically look for matches inside lists, where one is only matching when the value is dash-separated &lt;code&gt;|&lt;/code&gt; and the other operator&lt;br&gt;
matches everything inside a space-separated list &lt;code&gt;~&lt;/code&gt;. Especially the space separation can also be achieved with other operators mentioned above.&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="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-attribute&lt;/span&gt;&lt;span class="o"&gt;~=&lt;/span&gt;&lt;span class="s1"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* matches eg. &amp;lt;li data-years="thor value loki"&amp;gt;...&amp;lt;/li&amp;gt; */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-attribute&lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="s1"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* matches eg. &amp;lt;li data-years="value-2021"&amp;gt;...&amp;lt;/li&amp;gt; */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Combining attribute selectors
&lt;/h2&gt;

&lt;p&gt;Of course, we can also use multiple attribute selectors simultaneously to select specific elements. This can be especially handy when the HTML&lt;br&gt;
provides us with enough info to create different styles only through our attributes. Let's say we want to give icons to every file download link&lt;br&gt;
on a site and a special icon to PDFs. We can combine the contains and ends with selectors to select all files and then specifically find all PDFs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s1"&gt;"/downloads"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* file is in /downloads directory */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s1"&gt;"/downloads"&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"pdf"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* file is in /downloads directory */&lt;/span&gt;
    &lt;span class="c"&gt;/* AND ends with pdf */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Negating the attribute selector with :not
&lt;/h2&gt;

&lt;p&gt;All the attribute selectors above can also be combined with the CSS &lt;code&gt;:not&lt;/code&gt; selector, so we could also take our example above and find all files&lt;br&gt;
that are inside the downloads directory but are specifically &lt;em&gt;not&lt;/em&gt; PDF files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s1"&gt;"/downloads"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"pdf"&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* file is in /downloads directory */&lt;/span&gt;
    &lt;span class="c"&gt;/* AND ends NOT with pdf */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using attribute selectors in Javascript
&lt;/h2&gt;

&lt;p&gt;Just like using regular class and id selectors, we can also utilize all of the above selectors when writing JavaScript to select DOM elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;team&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img[src*="team"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>css</category>
    </item>
    <item>
      <title>A brief introduction to Remix JS</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Tue, 23 Nov 2021 15:03:47 +0000</pubDate>
      <link>https://dev.to/codestructio/a-brief-introduction-to-remix-js-22j0</link>
      <guid>https://dev.to/codestructio/a-brief-introduction-to-remix-js-22j0</guid>
      <description>&lt;p&gt;Remix is a new full stack JavaScript framework that gets rid of static site generation and also in other areas, does a few things differently than what we're used to from other frameworks. It relies on React to render the UI and if you're familiar with Next.js you can certainly spot a lot of similarities. However, there are also clear distinctions, like nested routes, handling of data fetching and data saving as well as error handling. Let's take a look at those concepts and how they compare to other techniques, currently used in popular frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application structure and routes
&lt;/h2&gt;

&lt;p&gt;The easiest way to get started with a new Remix project is by installing it through npx and following the interactive prompts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-remix@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we're done with that, our project's structure is already set up for us and we're good to go. If we compare Remix to Next.js, we'll see that with Remix we're also&lt;br&gt;
writing client side and server ide code inside our route files. However, Remix gives us a little more control to fine-tune things like caching and this also shows in having two separate files for handling requests  — &lt;code&gt;entry.client&lt;/code&gt; and &lt;code&gt;entry.server&lt;/code&gt; that represent our entry points and therefore determine what's run first on the server and client respectively. We also get a &lt;code&gt;root.tsx&lt;/code&gt; which holds the root component to our app and renders the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;, first &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tags, and so on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── ...
├── app
│   ├── entry.client.tsx
│   ├── entry.server.tsx
│   ├── root.tsx
│   ├── routes
│   │   └── index.tsx
│   ├── styles
│   │   └── global.css
│   └── utils.server.tsx
├── jsconfig.json
├── package.json
├── public
├── remix.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also see a framework-specific &lt;code&gt;remix.config.js&lt;/code&gt; which allows to to configure a lot off different details about oour application, such as the default public directory, development ports and much more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nested routing
&lt;/h2&gt;

&lt;p&gt;A very neat mechanism in Remix is the ability to render parts of a page based on the route we're on. When thinking of other frameworks, this would come down to either a separate route with its own &lt;code&gt;index&lt;/code&gt; file or specifically matching a route to one or more components. We're used to binding parts of our URL to different routes or components already — the way Remix does it, is best described as nested layouts, where each part of the URL is by definition bound to a route file. Here's an example from their official site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Ne-P0iR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://allround.io/storage/remix-nested-routes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Ne-P0iR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://allround.io/storage/remix-nested-routes.png" alt="Remix JS nested routes" width="880" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The route shown above (&lt;code&gt;/sales/invoices&lt;/code&gt;) would therefore be represented by three files&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;routes/sales.jsx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;routes/sales/index.jsx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;routes/sales/invoices.jsx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our first file is the wrapper that gets called first and based on the rest of the URL decides which "sub-components" should be rendered. The initial state&lt;br&gt;
would be &lt;code&gt;routes/sales/index.jsx&lt;/code&gt; and when navigating to /invoices, our wrapper pulls in the code from &lt;code&gt;routes/sales/invoices.jsx&lt;/code&gt;. The way this is realized in code is not through regular components, but through an &lt;code&gt;&amp;lt;Outlet /&amp;gt;&lt;/code&gt; which is part of &lt;code&gt;react-router-dom&lt;/code&gt; and allows for this mapping of nested layouts to routes (route components) rather than regular components.&lt;/p&gt;

&lt;p&gt;Under the hood this allows Remix to preload the different parts on a page, which makes it &lt;em&gt;really&lt;/em&gt; fast and lets us eliminate loading states as much as possible. There are probably some more interesting things we can do here that I haven't fully explored yet.&lt;/p&gt;
&lt;h2&gt;
  
  
  Styling pages and components
&lt;/h2&gt;

&lt;p&gt;Styling components is fairly straightforward with Remix, because it's very close to how it works on the web since forever. Remix brings its own &lt;code&gt;LinksFunction&lt;/code&gt; which can be used to import CSS files on a per-route basis. That's also where we have to be a little careful and separate our CSS into global CSS that should be available to every route and specific CSS that will not be loaded outside a certain route at all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stylesUrl&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../styles/index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LinksFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylesheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stylesUrl&lt;/span&gt; &lt;span class="p"&gt;}];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;IndexRoute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Index&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again Remix relies heavily on how the web already works, so if we wanted to use preprocessors or frameworks like Tailwind, we'd want to pass the compiled resources paths to Remix, just like we would with vanilla CSS files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading data
&lt;/h2&gt;

&lt;p&gt;To get data inside a route component in Remix, we can use a &lt;code&gt;loader&lt;/code&gt;, which is just an async function that returns the requested data. Inside our components, we can then access it through a hook called &lt;code&gt;useLoaderData&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useLoaderData } from "remix";

export let loader = async () =&amp;gt; {
  return getData(); // does the heavy lifting, DB calls etc. and returns data
}

// Component function starts here
export default function Component() {
    let allData = useLoaderData(); // data is now available inside our component
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the function is always called &lt;code&gt;loader&lt;/code&gt; by convention and is only executed server-side, which means we also have access to all &lt;code&gt;node&lt;/code&gt; features and libraries to connect to databases and fetch data, like we're used to on the server.&lt;/p&gt;

&lt;p&gt;If we're passing parameters to our routes, like a dynamic URL often times requires, the loader also has access to that, by passing in the request parameters like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Storing data
&lt;/h2&gt;

&lt;p&gt;If we want to send new user-generated data back to the backend, to save it to a database for example, Remix lets us use so-called &lt;code&gt;actions&lt;/code&gt;. Actions rely on forms for the actual data input and are also only executed server-side, despite being in your route file.&lt;br&gt;
The functions are — again by convention — called &lt;code&gt;action&lt;/code&gt; and can also trigger (return) a redirect. Let's look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slug&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createPost&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// actual call to store data...&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;NewPost&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Form&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/label&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="nx"&gt;Slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slug&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/label&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that the &lt;code&gt;action&lt;/code&gt; function takes the &lt;code&gt;request&lt;/code&gt; as a parameter and thereby has access to everything our form sends over to the server. From there we're free to use any &lt;code&gt;node&lt;/code&gt; code to store our data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling errors
&lt;/h2&gt;

&lt;p&gt;The way Remix handles errors is quite unique, as it allows us to create &lt;code&gt;ErrorBoundary&lt;/code&gt;s that will be shown in case something with our route  components didn't work as expected and an error is thrown. That way, if we're using Remix's nested routes, we might see a single  throwing&lt;br&gt;
and error, but not necessarily the whole page. The smart thing about error boundaries is that they bubble up (the routes) to the closest error boundary. So the easiest case would be having one error boundary at the root level, comparable to a full 404. However, the image below nicely&lt;br&gt;
demonstrates how having multiple small error boundaries (one per route component for examaple) can leave the rest of an application intact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cdU8JRDM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://allround.io/storage/error-boundary.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cdU8JRDM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://allround.io/storage/error-boundary.png" alt="Remix JS error boundary" width="880" height="695"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ErrorBoundary&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Something&lt;/span&gt; &lt;span class="nx"&gt;went&lt;/span&gt; &lt;span class="nx"&gt;wrong&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/title&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Meta&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Links&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/head&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="nx"&gt;anything&lt;/span&gt; &lt;span class="nx"&gt;we&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="nx"&gt;know&lt;/span&gt; &lt;span class="nx"&gt;goes&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/body&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/html&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implementing an error boundary  is as simple as adding an &lt;code&gt;ErrorBoundary&lt;/code&gt; function to our route components as shown above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;At the time of this writing, Remix has really only been released yesterday, so there is still a lot to learn and some things might even change drastically with newer versions.&lt;/p&gt;

&lt;p&gt;If you're looking for more resources and want to dive deeper, there's a fantastic tutorial on &lt;a href="https://remix.run/docs/en/v1/tutorials/blog"&gt;building a blog&lt;/a&gt; and a small &lt;a href="https://remix.run/docs/en/v1/tutorials/jokes"&gt;dad jokes applicaiton&lt;/a&gt; in the &lt;a href="https://remix.run/docs/en/v1"&gt;Remix docs&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to write a custom event system in JavaScript</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Fri, 19 Nov 2021 07:18:01 +0000</pubDate>
      <link>https://dev.to/codestructio/how-to-write-a-custom-event-system-in-javascript-4em5</link>
      <guid>https://dev.to/codestructio/how-to-write-a-custom-event-system-in-javascript-4em5</guid>
      <description>&lt;p&gt;When building complex applications it's always a good idea to take a step back and think through architectural choices from the get-go. One pattern that really forces us to do that is an event system or the closely related PubSub pattern, which we'll take a closer look at in this article.&lt;/p&gt;

&lt;p&gt;The biggest advantage of this pattern is that we get to decouple parts of our application and have them talk to each other through a middleman, or in simpler cases, we just broadcast an event and have a listener that executes when the event is triggered. A big advantage of this pattern is that all our events get routed through &lt;em&gt;the same&lt;/em&gt; logic before being picked up by the listeners, which allows us to do some extra work and extend all events in our system later on.&lt;/p&gt;

&lt;p&gt;Let's clear up some terms before we move into code. Given a simple example like on-page notifications, our core functionality that will be executed can be a simple &lt;code&gt;alert()&lt;/code&gt; . Now to not call it directly but actually use an event system, we need to implement an &lt;code&gt;Observer&lt;/code&gt; that will listen to incoming events, delegate our invocation and call all the right functions for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="na"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// We already know we want to be able to call our observer and&lt;/span&gt;
            &lt;span class="c1"&gt;// it will need to dispatch the actual event&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;

        &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Our observer will need to be able to listen itself for incoming events&lt;/span&gt;
            &lt;span class="c1"&gt;// that we'll notify the listeners about (via callbacks)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="p"&gt;}();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Observer pattern above will be our middleman and listen to events when we define them in like this: &lt;code&gt;Observer.on('eventName', callback)&lt;/code&gt;. At the same time, it allows us to trigger those events via &lt;code&gt;Observer.dispatch('eventName')&lt;/code&gt; whenever we want the receivers to be notified. The most important part inside our observer is the &lt;code&gt;events&lt;/code&gt; object  that will hold all callbacks in the form of &lt;code&gt;{[eventName: callback()]}&lt;/code&gt;. Let's go ahead and fill the functions with code to see how the Observer pattern works in action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the observer pattern
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="na"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;

        &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;on&lt;/code&gt; method is used to register our events and we need to call it before we can actually dispatch an event. it takes an event name and a callback as parameters and pushes both into our events object as described above.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;dispatch&lt;/code&gt; function that will be triggered to fire off an event, takes an event name as the only argument. In fact, this should be the same event name that we previously added to the events object when we registered the event with our &lt;code&gt;on&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;And with that, we have a working event system that can be used like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Listen to an event&lt;/span&gt;
&lt;span class="nx"&gt;Observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testevent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This will be executed when our event fires&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Fire our event&lt;/span&gt;
&lt;span class="nx"&gt;Observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testevent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind that this is a very minimal custom event system and there are more mature systems out there. If we were to expand this minimal example, we'd need to take proper care of error handling, unbinding events (&lt;code&gt;off&lt;/code&gt; function to our &lt;code&gt;on&lt;/code&gt;), and implement some general checks around passed arguments.&lt;/p&gt;

&lt;p&gt;If you want to dive deeper into the observer pattern or Pub Sub, here's a great resource for further reading with implementation details: &lt;a href="https://addyosmani.com/resources/essentialjsdesignpatterns/book/#mediatorpatternjavascript"&gt;https://addyosmani.com/resources/essentialjsdesignpatterns/book/#mediatorpatternjavascript&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A nifty alternative to box-shadows</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Wed, 07 Jul 2021 12:56:06 +0000</pubDate>
      <link>https://dev.to/codestructio/a-nifty-alternative-to-box-shadows-6dd</link>
      <guid>https://dev.to/codestructio/a-nifty-alternative-to-box-shadows-6dd</guid>
      <description>&lt;p&gt;Most folks know about the &lt;code&gt;box-shadow&lt;/code&gt; property and use it a lot already in their CSS, however there are certain scenarios where a box-shadow doesn't give us ideal results. There is however also a CSS filter called &lt;code&gt;drop-shadow&lt;/code&gt; that let's us do some cool things we cannot achieve with box-shadows. It's currently supported in all modern browsers and definitely worth a look. Here's how a drop-shadow looks like in CSS:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&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;h2&gt;
  
  
  What's the use case?
&lt;/h2&gt;

&lt;p&gt;While box-shadows are sufficient in most scenarios, they can only give us a shadow around the exact shape of an element, which is usually angular or round due to a &lt;code&gt;border-radius&lt;/code&gt;. With drop-shadows however, we can cast a shadow around elements and even images that stays in direct proximity to the non-transparent parts of the image or element.&lt;/p&gt;

&lt;p&gt;So in essence this works on regular HTML elements, SVGs and also transparent PNGs. Here's an example:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;triangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linear&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="nx"&gt;deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;yellow&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;transparent&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://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%2Ftupihr2fie8j7ntxojql.png" 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%2Ftupihr2fie8j7ntxojql.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One downside we can spot in the syntax here is that we're not able to set a spread parameter the shadow should have. Other than that, the parameters match what we're used to with box-shadows (x-offset, y-offset, blur, color).&lt;/p&gt;

&lt;p&gt;The real magic however becomes more obvious when we apply a drop-shadow to a transparent PNG, which gives us the same effect as seen above, instead of just putting a shadow on the whole image or container, we see the shadow aligned to the filled lines and shapes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    img &lt;span class="si"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"./waves.png"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&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%2Fbxjtiqqpz7c16zc32qw1.png" 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%2Fbxjtiqqpz7c16zc32qw1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned for more frontend-focused articles like this 👉 &lt;a href="https://allround.io" rel="noopener noreferrer"&gt;https://allround.io&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Writing reusable modules in JavaScript</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Wed, 09 Jun 2021 07:02:15 +0000</pubDate>
      <link>https://dev.to/codestructio/writing-reusable-modules-in-javascript-39a2</link>
      <guid>https://dev.to/codestructio/writing-reusable-modules-in-javascript-39a2</guid>
      <description>&lt;p&gt;As developers we often use a lot of libraries and packages and know very well how to use them. We're used to it, because packages and libraries are a huge part of the ecosystem and a great way to speed up development and free us from rather complicated, repetitive tasks.&lt;/p&gt;

&lt;p&gt;When it comes to writing libraries or reusable modules from scratch however, it's not always so clear where to start and how to make sure our libraries are not breaking anything else in an application. Making sure we're using our own scope, function names and such are only part of what makes a good module. Let's take a close look at how to write our own libraries that can be plugged into different projects without worrying about breaking any existing code.&lt;/p&gt;

&lt;p&gt;When we're  the developer who's using a library, we care about simplicity and ideally want to understand what's going on by the name of the function we're calling alone. We're also very used to a certain kind of syntax, which probably looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;option&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;option&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;Library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can initialize our library with some options and then just call pre-defined and hopefully well documented functions on the library, possibly passing in some arguments. Sometimes we'll get a return value or promise out of that function call, other times there might be a change in the DOM as a result of calling the function. Either way, we're very used to that kind of syntax when using libraries and so when writing our own we should try to imitate that.&lt;/p&gt;

&lt;p&gt;The object literal notation in JavaScript lets us do just that. It also has the added benefit of keeping everything inside our object and therefore we're not putting anything related to our module on the global scope, except the object itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Our Object literal can hold simple variables&lt;/span&gt;
  &lt;span class="na"&gt;someProperty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;someValue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// We can also declare further objects inside our object&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c1"&gt;// And of course declare regular, named functions&lt;/span&gt;
  &lt;span class="na"&gt;saySomething&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The module pattern
&lt;/h2&gt;

&lt;p&gt;We can take the object literal approach one step further with the module pattern, which allows us to declare public and private functions and variables, using closures. We're basically defining a public API that our library/module exposes, while keeping other internal states, variables and functions private and thereby inaccessible from the outside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;var&lt;/span&gt; &lt;span class="nt"&gt;Module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;function&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="err"&gt;let&lt;/span&gt; &lt;span class="err"&gt;secret&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;0;&lt;/span&gt;
    &lt;span class="err"&gt;let&lt;/span&gt; &lt;span class="err"&gt;publicNumber&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;2;&lt;/span&gt;

  &lt;span class="err"&gt;function&lt;/span&gt; &lt;span class="err"&gt;privateFunc(a)&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;console.log(a);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;function&lt;/span&gt; &lt;span class="nt"&gt;addOne&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;return&lt;/span&gt; &lt;span class="err"&gt;b&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;1;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;publicNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;publicNumber&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="o"&gt;)()&lt;/span&gt;

&lt;span class="nt"&gt;Module&lt;/span&gt;&lt;span class="nc"&gt;.addOne&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;Module&lt;/span&gt;&lt;span class="nc"&gt;.publicNumber&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As shown above we can now explicitly define what functions and variables should be accessible from the outside by returning an object with only those things what we want the outside to know about. This is great, because we can hide away a lot of the heavy lifting or things we don't want to expose because calling them directly would break things. We're basically exposing a little API that is consistent and well structured.&lt;/p&gt;

&lt;p&gt;While this pattern is great for frontend libraries and modules, it is also super convenient when writing modules in node. In fact most modules naturally follow this pattern in a way, because they have a (default) export statement. Here's how we can utilize the same structure in node&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MessageController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nl"&gt;receiveMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MessageController&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way we get to keep the clean structure of our object literal / module pattern, while being able to just import our module like we would with other modules. We also get to chosse what to export explicitly while we can keep other functions private. Here's how we'd import the above module in node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MessageController&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./controllers/message-controller.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stay tuned for a look at other useful JS design patterns like singletons or the factories 👉 &lt;a href="https://allround.io"&gt;https://allround.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Better CSS box shadows</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Mon, 03 May 2021 10:01:35 +0000</pubDate>
      <link>https://dev.to/codestructio/better-css-box-shadows-1ckd</link>
      <guid>https://dev.to/codestructio/better-css-box-shadows-1ckd</guid>
      <description>&lt;p&gt;Using shadows is a great way to avoid clunky borders in otherwise light layouts and they've long surpassed being "just for decoration" elements in websites and apps alike. Especially when creating different levels of elevation that make some elements appear closer to the user than others – like a stack of elements – the use of shadows can make a big difference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In general the closer something is to the user, the more attention it will get, just like the closest car in traffic (like buttons)&lt;/li&gt;
&lt;li&gt;Smaller shadows that are closer to the elemet are great for capturing attention, while more diffuse and wide shadows are better suited to separate an element form its surrounding (like overlays)&lt;/li&gt;
&lt;li&gt;Inset shadows can help create a feeling of plasticity or let elements appear bend inwards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make a layout with shadows as consistent as possible, we should make sure to pick an imaginary lighting position and stick to it whenever using shadows. Otherwise we risk inconsistencies that look weird to users. Elements casting shadows in different directions also make it harder for the eye to quickly see a hierarchy when it comes to eleviation (z-index).&lt;/p&gt;

&lt;p&gt;While those general guidelines are a solid start, the real magic of box shadows reveals itself when we use multiple shadows on the same element. In CSS a regular box shadow has the following properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;box-shadow&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;x-offset&lt;/span&gt; &lt;span class="nt"&gt;y-offset&lt;/span&gt; &lt;span class="nt"&gt;blur-radius&lt;/span&gt; &lt;span class="nt"&gt;spread-radius&lt;/span&gt; &lt;span class="nt"&gt;color&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can however add more shadows on the same element by comma-separating them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first shadow in this example is a box-shadow how it is often used, generally darker, close to the element and rather sharp with only a bit of blur – the classic way of using box-shadows.&lt;br&gt;
The second shadow however has a bigger blur, a higher vertical offset and is rather subtle, giving the element a lot more depth, making it look closer to how we see shadows on objects in real life. If we wanted to achieve a perceived higher elevation that shadow would have to be more subtle the closer it gets and more intense the further "down" it is supposed to be.&lt;/p&gt;

&lt;p&gt;While that's already a great improvement over simple box-shadows, we can go even further and create a fake plasticity by adding another shadow to the element. One brand that has incorporated this kind of plasticity into their overall appearance is Algolia. Here's a typical button, which adds a third (inset) shadow to the element, giving it a little edge on the bottom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--namnGkJN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://allround.io/storage/algolia-button.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--namnGkJN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://allround.io/storage/algolia-button.jpg" alt="https://allround.io/storage/algolia-button.jpg"&gt;&lt;/a&gt;&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="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt; &lt;span class="m"&gt;35&lt;/span&gt; &lt;span class="m"&gt;66&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;40%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c"&gt;/* diffuse shadow behind the button */&lt;/span&gt;
    &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt; &lt;span class="m"&gt;13px&lt;/span&gt; &lt;span class="m"&gt;-3px&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt; &lt;span class="m"&gt;35&lt;/span&gt; &lt;span class="m"&gt;66&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c"&gt;/* shadow offset to the bottom for depth */&lt;/span&gt;
    &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;-3px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;#d6d6e7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* boottom "edge" of the button */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course we don't always want to make use of every technique just because we can. When shadows are part of the layout however, it is definitely worth spending a bit of time on nailing those basics to get a clean and consistent look.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Customizing Tailwind CSS</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Wed, 21 Apr 2021 13:28:04 +0000</pubDate>
      <link>https://dev.to/codestructio/customizing-tailwind-css-35m7</link>
      <guid>https://dev.to/codestructio/customizing-tailwind-css-35m7</guid>
      <description>&lt;p&gt;Just like in the golden days of Bootstrap, popular CSS frameworks like Tailwind involve the danger of many websites looking very similar. Especially with the UI components released as &lt;a href="https://tailwindui.com/"&gt;Tailwind UI&lt;/a&gt; it is super easy to get going with a beautiful default for almost every part of a website or application. Don't get me wrong, those are beautiful components throughout and using them to get something up quickly makes a lot of sense. The downside however is that your sites and applications will look very generic and close to others on the web, which means you're missing the chance to leave a lasting impression with you design and gain some brand awareness that a unique design can give.&lt;/p&gt;

&lt;p&gt;The irony is, Tailwind is really well suited as a base UI system which is also &lt;strong&gt;fairly easy to customize and make your own.&lt;/strong&gt; A lot of times people are underestimating the benefits of unique designs and put the customization somewhere in their backlog of things to do later. Let's change that! Let's take a look at how we can make Tailwind look different while keeping all the underlying goodies.&lt;/p&gt;

&lt;p&gt;If you've never worked with Tailwind CSS or utility classes before, there's an introduction article I wrote &lt;a href="https://allround.io/articles/introduction-to-tailwind-css-and-utility-classes"&gt;over here&lt;/a&gt;. If you're already familiar with Tailwind, great! Let's dive right in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To get started, let's set up a very basic project that consist of nothing but bare HTML / CSS and JavaScript. Setting up Tailwind with Frameworks like Vue, Laravel and others might vary, because there are better ways of integrating it into the existing build steps. It's worth checking out the official documentation, to get instructions on how to do that – it's pretty good. &lt;/p&gt;

&lt;p&gt;We'll keep it simple and start by creating the bare minimum we need from the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create our main HTML and CSS files as well as a bare PostCSS config file&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;index.html main.css postcss.config.js

&lt;span class="c"&gt;# Initialize project with npm&lt;/span&gt;
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Install tailwind with PostCSS, autoprefixer and PostCSS CLI&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss@latest postcss@latest postcss-cli autoprefixer@latest

&lt;span class="c"&gt;# Create a minimal Tailwind config file&lt;/span&gt;
npx tailwindcss init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to add the following base config to the PostCSS configuration file we just created, so it knows what to do when compiling our CSS. In general Tailwind is a PostCSS plugin and you can absolutely use it with other preprocessors too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// postcss.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;tailwindcss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="na"&gt;autoprefixer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we want to create an npm script that allows us to compile everything together by typing a single command. This is our build step for this tutorial and as mentioned above, when integrating Tailwind in different frameworks this might look different for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// package.json — to compile, run:&lt;/span&gt;
&lt;span class="c1"&gt;// $ npm run compile&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postcss main.css -o compiled.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Now we just need to make sure we include the &lt;code&gt;compiled.css&lt;/code&gt; in our HTML file and that's all we need in terms of boilerplate. Time to start the actual customization.&lt;/p&gt;

&lt;p&gt;When it comes to styling the base theme and changing defaults like colors, margins, border radius, fonts and such there is a single file we can use to customize all of that, and that's the &lt;code&gt;tailwind.config.js&lt;/code&gt; that was just created automatically in our setup step above. By default, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you're wondering why it's empty and where the actual default theme is coming from, or just want to dig a little deeper into the defaults, &lt;a href="https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js#L7"&gt;here is a link to the defaults&lt;/a&gt; that get applied if we don't customize anything. However, that's exactly what we're here for – customizing. So let's start doing that by adding our own brand color:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFF538&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFC233&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#C19A32&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to be able to use this new color class in our HTML, we'll have to run our build step once, by calling our PostCSS compiler from the terminal, like we defined above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sweet, we now have a new class at our fingertips called &lt;code&gt;primary&lt;/code&gt; which we can use with all the prefixes and modifiers we defined above (light / dark). Let's try it out and see it in action, by applying the new class to a button element and making the button darker on hover:&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="c"&gt;&amp;lt;!-- In our index.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn bg-primary hover:bg-primary-dark transition p-4 my-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    I'm a button
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Looking at spacing and breakpoints
&lt;/h2&gt;

&lt;p&gt;Another important aspect of every layout that we might need to modify or extend, depending on what we want to create are spacings and breakpoints. Luckily for us, creating them is not a whole lot harder than adding our own custom colors, like we just did above. There is a gotcha when it comes to breakpoints however, as they need to be declared in the right order. Let's put it all together and jump into the details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Let's see why we need this in a second!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tailwindcss/defaultTheme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#FFF538&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#FFC233&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#C19A32&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="c1"&gt;// Here we're adding a new breakpoint class&lt;/span&gt;
            &lt;span class="na"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;475px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;defaultTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;laaarge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1600px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="c1"&gt;// Here we're declaring our new spacing classes&lt;/span&gt;
            &lt;span class="na"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;small-bear&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mama-bear&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;15rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;papa-bear&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So just to recap what we just added: there's a new require statement at the top and two new blocks for the &lt;em&gt;spacing&lt;/em&gt; and breakpoints (&lt;em&gt;screens&lt;/em&gt;). Let's look at the spacings first, because they're rather similar to the color classes we defined earlier. In fact, they work just like our colors, except they don't take any modifiers like &lt;code&gt;light&lt;/code&gt; – because we don't need that for our spacings. So with those newly defined spacings, we can now add big margins, paddings etc. to our layout. By using the class &lt;code&gt;m-mama-bear&lt;/code&gt; for example, we'd add a margin of &lt;code&gt;15rem&lt;/code&gt; to all sides.&lt;/p&gt;

&lt;p&gt;When it comes to breakpoints there's a small caveat when creating our own ones, because just like in regular CSS (when writing media queries) the order matters. That same principle applies to Tailwind breakpoints: If we want to declare a breakpoint that is smaller than the default ones, which start at &lt;code&gt;sm&lt;/code&gt; 640px, we have to make sure to declare it &lt;em&gt;before&lt;/em&gt; the default breakpoints. That's why in the example above, we're using the require statement at the top to grab all the default breakpoints and then when setting up our breakpoints, we're inserting them after our new &lt;code&gt;xs&lt;/code&gt;. If we don't do that, our breakpoint will get overwritten just like media queries would be in a regular CSS file. Order matters!&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying and extending base styles
&lt;/h2&gt;

&lt;p&gt;So besides creating our own utility classes, we want to take a look at extending the Tailwind base styles. Because Tailwind does a full reset, you can quickly see that a regular &lt;code&gt;h1&lt;/code&gt; for example doesn't look much like a headline anymore, unless you start applying classes. That's by design and actually gives us a lot of flexibility. When we design complex components however, we might want to have base elements styled a certain way, even without applying a whole lot of classes. A good way of doing that is using the &lt;code&gt;@apply&lt;/code&gt; rule. It allows us to apply a set of rules to a given CSS selector like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Require the basic Tailwind CSS */&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-2xl;&lt;/span&gt; &lt;span class="c"&gt;/* Applying our text-2xl rule on the h1 */&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;font-bold;&lt;/span&gt;
    &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-primary;&lt;/span&gt; &lt;span class="c"&gt;/* We can even apply our custom classes! */&lt;/span&gt;

    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;monospace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* And we can mix with regular CSS */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-xl;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now without applying any classes directly in our HTML, we have added the predefined properties to our elements right in the CSS. That allows us to give every element a sane default without leaving our predefined system or repeating ourselves. This is great for more complex elements that require custom CSS or edge-cases where we don't want to make a whole new utility class, but just overwrite parts of our system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using and creating presets
&lt;/h2&gt;

&lt;p&gt;Now that we've got a good first look at how to technically customize Tailwind, one more concept that is really worth knowing about is how to use presets. In fact the default styles Tailwind ships with are just a preset as well. If we want to keep a single source of truth for things like color, font and such and work on different projects for the same client, presets are super helpful. They allow us to use a single &lt;code&gt;tailwind.config.js&lt;/code&gt; as the base and extend it, just like we just extended the default preset. So in fact, every config file is a preset itself. We can use other presets as the base for our project by stating it in our config file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tailwind.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./masters/tailwind-base.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because our presets variable is an array, you can already guess that we can also use multiple presets as our foundation and build on them. The important thing to keep in mind with the whole preset approach is that if there are overlapping rules defined, they will get overwritten in order you're requiring them — just like in regular CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;There's still a lot we haven't covered yet, even though all of the above already sets us up with everything we need to really create fully custom layouts with Tailwind. If you want to dig deeper, I'd recommend looking into &lt;strong&gt;plugins&lt;/strong&gt; and how to optimize Tailwind for use in production.&lt;/p&gt;

&lt;p&gt;Here's a great article on &lt;a href="https://www.nick-basile.com/blog/post/how-to-write-a-plugin-for-tailwind-css/"&gt;creating a useful plugin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and the official documentation is a good starting point to learn &lt;a href="https://tailwindcss.com/docs/optimizing-for-production"&gt;more about optimizing for production&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, you can also grab the full source code of everything we just created above over on GitHub: &lt;a href="https://github.com/allroundio/tailwind-example"&gt;https://github.com/allroundio/tailwind-example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>tailwindcss</category>
      <category>design</category>
    </item>
    <item>
      <title>An introduction to Tailwind CSS and utility classes</title>
      <dc:creator>codestruct.io</dc:creator>
      <pubDate>Wed, 07 Apr 2021 14:18:35 +0000</pubDate>
      <link>https://dev.to/codestructio/an-introduction-to-tailwind-css-and-utility-classes-5a7</link>
      <guid>https://dev.to/codestructio/an-introduction-to-tailwind-css-and-utility-classes-5a7</guid>
      <description>&lt;p&gt;If you haven't checked out Tailwind CSS yet or don't know what all the buzz regarding utility classes is all about, this article is for you. We'll take a first look at the advantages and get our hands just dirty enough to know what makes Tailwind a great CSS framework and what alternatives there are.&lt;/p&gt;

&lt;p&gt;In general when talking about utility classes, you can think of primitive utilities that don't do much individually. In fact they shouldn't do much by themselves but work well when combined with other utility classes. The goal is to have a set of pre-existing classes that we can use to style HTML without writing a lot of custom CSS, which allows us to move faster and re-use those classes as much as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping it simple
&lt;/h2&gt;

&lt;p&gt;We'll keep it simple and skip all the build-steps and setting up our tooling for now, even though it's an important and powerful part of Tailwind's magic. For now we'll just look at the concept of utility classes and see how they can help us reduce the required amount of custom CSS and allow us to style our content faster overall.&lt;/p&gt;

&lt;p&gt;So instead of setting up a build step, we'll start by simply requiring the Tailwind stylesheet into a blank HTML file. That's all we really need to get going.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start by looking at a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element and make it pretty! First, let's make sure it has a &lt;code&gt;background-color&lt;/code&gt; —&amp;gt; In Tailwind we get a lot of predefined &lt;a href="https://tailwindcss.com/docs/background-color"&gt;background colors&lt;/a&gt;, all created with rgba values, which allows our utility classes to change the colors based on the alpha, which we can set with a simple number in our class names 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;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-blue-700"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I'm a button&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, 700 sets the alpha and we can go lighter and darker from 50 to 900, where 50 is the only smaller step and the basic rule is that we can increase or decrease the alpha in hundreds. So if we wanted a lighter blue, we could set it to &lt;code&gt;bg-blue-500&lt;/code&gt;. This is great, because it already gives us a clue how we can make use of this for our hover effect! Let's check that out.&lt;/p&gt;

&lt;p&gt;In order to give our button a lighter blue on hover, we'll use one of Tailwind's prefixes: &lt;code&gt;hover:&lt;/code&gt; and combine it with the background, we've just used above: &lt;code&gt;hover:bg-blue-500&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Sweet! We have a button that changes its background color on hover! Let's improve it further, by adding a font-color that is easier to read on our blue background. Just like we set the background-color, we can use the class &lt;code&gt;text-&amp;lt;color&amp;gt;&lt;/code&gt; to set a color on our element. Again like the color palette for backgrounds, Tailwind comes with a set of &lt;a href="https://tailwindcss.com/docs/text-color"&gt;predefined text-colors&lt;/a&gt; which can be adjusted by changing the alpha of the base color.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"bg-blue-700 hover:bg-blue-500 text-white"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;I&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nt"&gt;m&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Side note: When using build tools we can also define our own colors, so we are not limited to the predefined palette.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's a pretty rad button already and we were pretty fast to get there. This simple button element already illustrates how utility classes can save us  a lot of time, as we have written exactly zero CSS so far, even though we changed the background color, text color and added a hover effect. And we're barely scratching the surface – let's dig a little deeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Digging a little deeper
&lt;/h2&gt;

&lt;p&gt;I'm a sucker for details when it comes to user interactions, so I'm already having a hard time looking at the button we just created. It needs a transition! Luckily Tailwind has our back and we can make use of multiple transition properties, or go with the &lt;code&gt;transition-all&lt;/code&gt; property, which defaults to the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;transition-property&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;all&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;transition-timing-function&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;cubic-bezier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;transition-duration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;150&lt;/span&gt;&lt;span class="nt"&gt;ms&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Making sure we adhere to best practices around the &lt;code&gt;reduced-motion&lt;/code&gt; property, we can even use a prefix called &lt;code&gt;motion-reduce:&lt;/code&gt; to only show the transition when reduced-motion is not activated. Let's put that together real quick:&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;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-blue-700 hover:bg-blue-500 text-white transition-all motion-reduce:transition-none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I'm a button&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point you probably got the underlying idea of utility classes, utilizing a standardized way of naming with prefixes, the actual class and predefined and adaptable modifiers: &lt;code&gt;{prefix}:{class}-{modifier}&lt;/code&gt;. One downside people complain about a lot with this expressive approach is that we're overloading our HTML that way and it actually becomes pretty unreadable. It's definitely a good idea to start formatting your HTML a little more according to that and let lines not run too long. The alternative however is probably a rather lengthy stylesheet, so there are always trade offs 🤷‍♂️&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;
   &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Heya!
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before wrapping up, let's take a look at the bigger picture of building sites with Tailwind: Layout, spacing and responsiveness. Tailwind comes with a ton of handy classes to support us in all those areas like floats, flexbox and positioning classes, allowing us to build more complex components and layouts quickly. Let's take a look at a classic horizontal navigation bar using flexbox and centering things inside.&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;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex justify-between items-center px-16 bg-blue-700 text-white h-14"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Navigation&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex justify-between w-56"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Link&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Link&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Link&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;There's a demo below the article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that wasn't too much to write and we got a pretty solid navigation bar! If we wanted to change things on smaller or bigger devices, we can make use of prefixes again. Tailwind, much like Bootstrap, comes with predefined breakpoints (media queries) that are named as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sm&lt;/code&gt; 640px&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;md&lt;/code&gt; 768px&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lg&lt;/code&gt; 1024px&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;xl&lt;/code&gt; 1280px&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those can be seen as replacements for media queries in your CSS and when introducing them, the unprefixed version we have used so far will only be applied &lt;strong&gt;above&lt;/strong&gt; the prefixed version. So if we were to use a class with the prefix &lt;code&gt;md:bg-blue&lt;/code&gt; and also have a class &lt;code&gt;bg-yellow&lt;/code&gt; applied to the same element, the background would only be blue for everything above 768px (md) and yellow below that breakpoint.&lt;/p&gt;

&lt;p&gt;Just like predefined breakpoints, Tailwind comes with a set of spacings for paddings and margins that can be applied to either one or multiple sides of an element, basically making it a great alternative to &lt;code&gt;margin-top: x;&lt;/code&gt; and similar declarations. All spacing adhere to the following syntax &lt;code&gt;m{t|r|b|l}-{size}&lt;/code&gt; which translates to a class like &lt;code&gt;mt-8&lt;/code&gt; for a margin top of "8", where 8 translates to &lt;code&gt;2rem&lt;/code&gt;. Those values are as mentioned predefined but can be adapted when using a real build step. It's definitely worth checking out the &lt;a href="https://tailwindcss.com/docs"&gt;Tailwind documentation&lt;/a&gt; for exact values and in general a good idea to get a more in depth understanding of everything described in this article.&lt;/p&gt;

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

&lt;p&gt;A lot of the advantages of Tailwind actually come from using a build step and creating our own &lt;a href="https://tailwindcss.com/docs/configuration"&gt;configurations&lt;/a&gt;. This step allows us to define new colors, spacings, fonts, and much more! It's like keeping all the benefits of the utility-first approach but making it your own and adjusting it to your design and requirements. A lot of people seem to skip this step, which is why we see a lot of sites out there these days that use the default Tailwind styles. Don't get me wrong – that's not a bad thing! But you are missing out when not making use of those customizations. In fact, I think it is so important, I want to dedicate another full article to customizing Tailwind.&lt;/p&gt;

&lt;p&gt;In the meantime, there are also other utility-first frameworks that came before Tailwind and there will probably be a bunch more to come. Here are some really interesting ones I recommend checking out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://basscss.com/"&gt;https://basscss.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tachyons.io/"&gt;https://tachyons.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://yogurtcss.netlify.app/"&gt;https://yogurtcss.netlify.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tedconf.github.io/shed-css/index.html"&gt;https://tedconf.github.io/shed-css/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://turretcss.com/"&gt;https://turretcss.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And lastly, here's a working demo to play around with, which contains the basic examples shown in the article.&lt;/em&gt;&lt;br&gt;
&lt;a href="https://codepen.io/allroundio/pen/VwPWaJa"&gt;https://codepen.io/allroundio/pen/VwPWaJa&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;More on creating custom layouts with Tailwind soon.&lt;br&gt;
In the meantime, feel free to check out all other articles at &lt;a href="https://allround.io"&gt;allround.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>css</category>
      <category>design</category>
    </item>
  </channel>
</rss>
