<?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: Valik Ulyanov</title>
    <description>The latest articles on DEV Community by Valik Ulyanov (@mr150).</description>
    <link>https://dev.to/mr150</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%2F1103839%2F971c689a-57a6-4a3d-aa22-70cb8c037489.jpg</url>
      <title>DEV Community: Valik Ulyanov</title>
      <link>https://dev.to/mr150</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mr150"/>
    <language>en</language>
    <item>
      <title>Atomic CSS Deep Dive</title>
      <dc:creator>Valik Ulyanov</dc:creator>
      <pubDate>Fri, 09 Aug 2024 16:08:39 +0000</pubDate>
      <link>https://dev.to/mr150/atomic-css-deep-dive-1hee</link>
      <guid>https://dev.to/mr150/atomic-css-deep-dive-1hee</guid>
      <description>&lt;p&gt;Hello, comrades! My name is Valik and today we are going to talk about Atomic CSS approach, tool development and related topics.&lt;/p&gt;

&lt;p&gt;Let's briefly recall the basics - why Atomic CSS. Let's consider popular solutions to work in this approach and compare them with my invention - &lt;a href="https://github.com/mlutcss/mlut" rel="noopener noreferrer"&gt;mlut&lt;/a&gt;. We'll analyze the problems of well-known tools and see how I solved them in mine. There will be interesting architectural solutions, technical details and some hardcore.&lt;/p&gt;

&lt;p&gt;Those who do frontend development will be able to look at Atomic CSS in a different way and perhaps adopt a new tool. And those who write system code and tooling will get inspiration and learn from unconventional experience.&lt;/p&gt;

&lt;p&gt;This is a transcript of my talk from HolyJS Spring 2024.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few words about myself
&lt;/h2&gt;

&lt;p&gt;I'm a developer, in IT for over 8 years. For the last 2, I've been mostly doing backend on Node.js and tooling, and before that, I worked more with frontend. Doing my own open source project. I speak at IT events and lead a local IT community of 500+ people in St. Petersburg.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why exactly am I going to talk about Atomic CSS?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In topic since 2018, when Tailwind was still a noname library&lt;/li&gt;
&lt;li&gt;Watched all relevant tools that have more than 20 stars on github&lt;/li&gt;
&lt;li&gt;3 years of career with a lot of frontend&lt;/li&gt;
&lt;li&gt;I've invested well over 1000 hours in the development of my tool&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basics about Atomic CSS
&lt;/h2&gt;

&lt;p&gt;Let me remind you that Atomic CSS is a layout methodology in which we use small atomic CSS rules, each of which does one action. These classes are also called &lt;em&gt;utilities&lt;/em&gt;. They often apply a single CSS property (like changing the color of text), but not necessarily one. In code, it looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxdpx6uvsp0w0t0yxjx8k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxdpx6uvsp0w0t0yxjx8k.jpg" alt="Markup in Atomic CSS" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The main advantages of the approach are
&lt;/h3&gt;

&lt;p&gt;Compared to handwritten CSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Waste less mind fuel&lt;/strong&gt;. No need to think about unique entity names, whether it's a BEM block or BEM element, what kind of catalog structure to use, etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less CSS on the client&lt;/strong&gt;. At a certain point in development, styles stop being added. We reuse the same utilities all the time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faster to write styles&lt;/strong&gt;. Especially if we use short utility names. Plus, we have a lot less need to switch between files&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of you have probably remembered the typical myths about Atomic CSS, some of which can be seen in the illustration below. Of course, I won't deal with them in this article, because here we are more about system code and tools. But we will definitely come back to them in my next talk on this topic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjw4cztv7tjlk32a4hinf.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjw4cztv7tjlk32a4hinf.jpeg" alt="Myths about Atomic CSS" width="500" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  State of Atomic CSS
&lt;/h2&gt;

&lt;p&gt;Let's analyze the current situation on the market. Let's take 3 current and quite popular tools for working in Atomic CSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwindcss&lt;/a&gt; - the best known and most popular one&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://unocss.dev/" rel="noopener noreferrer"&gt;UnoCSS&lt;/a&gt; - not just a framework, but an engine for creating your own framework.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://acss.io/" rel="noopener noreferrer"&gt;Atomizer&lt;/a&gt; - a good old Yahoo tool that has a lot to boast about&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite the fact that we have at least 3 tools, the following problems remain relevant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-consistent naming&lt;/li&gt;
&lt;li&gt;Uncomfortable writing complex utilities&lt;/li&gt;
&lt;li&gt;Working with handwritten CSS &lt;/li&gt;
&lt;li&gt;Uncomfortable to extend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below we look at these problems in more detail&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-consistent naming
&lt;/h3&gt;

&lt;p&gt;A few examples of utilities from popular libraries&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;flex&lt;/code&gt; =&amp;gt; &lt;code&gt;display: flex&lt;/code&gt;, but &lt;code&gt;flex-auto&lt;/code&gt; =&amp;gt; &lt;code&gt;flex: 1 1 auto&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tracking-wide&lt;/code&gt; =&amp;gt; &lt;code&gt;letter-spacing: 0.025em&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;normal&lt;/code&gt;: line-height, font-weight or letter-spacing?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Complex utilities
&lt;/h3&gt;

&lt;p&gt;This is roughly how we are encouraged to write non-standard &lt;code&gt;@media&lt;/code&gt; expressions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[@media(any-hover:hover){&amp;amp;:hover}]:opacity-100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Turns this into the following CSS:&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="k"&gt;@media&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;any-hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;@media&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;any-hover&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="err"&gt;\&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="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:opacity-100:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&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;It's not all smooth sailing with complex selectors either:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[&amp;amp;:not(:first-child)]:rounded-full 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:rounded-full:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9999px&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 various at-rules also leave a lot to be desired:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supports-[margin:1svw]:ml-[1svw] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@supports&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;svw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.supports-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;margin&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;svw&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:ml-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;svw&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;svw&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;h3&gt;
  
  
  Working with handwritten CSS
&lt;/h3&gt;

&lt;p&gt;It's worth revealing a terrible secret about Atomic CSS here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In most projects, some part of the CSS you'll have to write by hand!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And it is normal, because such code will be in the limit of 10%, as practice shows.&lt;/p&gt;

&lt;p&gt;Now for the problem itself. Let's look at the following code sample on Tailwind:&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="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="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* #5 */&lt;/span&gt;
  &lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* #7 */&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c"&gt;/* #9 */&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;What we're seeing here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conflicts with CSS&lt;/strong&gt;. Not so long ago CSS introduced &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@layer" rel="noopener noreferrer"&gt;cascading layers&lt;/a&gt;, which are declared via at-rule &lt;code&gt;@layer&lt;/code&gt;. And Tailwind has its own &lt;code&gt;@layer&lt;/code&gt; (line #5), which works somehow in its own way&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Files structure&lt;/strong&gt;. By default, you can only work in a single CSS file in Tailwind. To work on more than one, you will need to use the PostCSS plugin&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use utility values&lt;/strong&gt;. If you want to get utility values to use in some property, you will need a special &lt;code&gt;theme&lt;/code&gt; function (line #7). That said, you'll need to know how to get to the right value in the theme dictionary, and that's not always obvious (line #9)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No preprocessor features&lt;/strong&gt;. This is rather a minus with an asterisk, because not everyone needs these features, and some of them can be obtained with PostCSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another interesting point to this topic. At one time there was such a clone of Tailwind - Windi CSS. The guys there started to make their own language or preprocessor to solve the issue with handwritten CSS. Here &lt;a href="https://windicss.org/posts/language.html" rel="noopener noreferrer"&gt;here&lt;/a&gt; you can check it out, looks funny.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F43440vp6nx4gd9sairp3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F43440vp6nx4gd9sairp3.jpg" alt="Windi Lang Draft" width="705" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Uncomfortable to extend
&lt;/h3&gt;

&lt;p&gt;This is how we are prompted to add a relatively simple utility:&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="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;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;tabSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// map with values&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="nf"&gt;plugin&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;matchUtilities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;matchUtilities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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="na"&gt;tabSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&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;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tabSize&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to add your own &lt;em&gt;variant&lt;/em&gt; (a modifier to make the utility work by hover, for example), you have to write something 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="nx"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="c1"&gt;// hover:&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matcher&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hover:&lt;/span&gt;&lt;span class="dl"&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;matcher&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;matcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:hover`&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;h3&gt;
  
  
  Actual solution
&lt;/h3&gt;

&lt;p&gt;As a solution to the above problems, I bring to your attention my tool: &lt;a href="https://github.com/mr150/mlut" rel="noopener noreferrer"&gt;mlut&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F162589935%2F18a4c523-9690-4f80-89e6-a19c86b43349" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F162589935%2F18a4c523-9690-4f80-89e6-a19c86b43349" alt="mlut is an abbreviation for My Little UI Toolkit" width="1280" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Atomic CSS toolkit with &lt;strong&gt;Sass&lt;/strong&gt; and ergonomics for creating styles of any complexity&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every word matters in this message, but now I will explain why Sass is highlighted in particular&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F6525jrcg50uqnfp8bl93.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F6525jrcg50uqnfp8bl93.jpg" alt="No, it's not Tailwind in Sass" width="556" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some might think: "Sass is a legacy technology, vanilla CSS is already wow: custom properties, cascading layers etc". But I wouldn't be in a hurry to bury it.&lt;/p&gt;

&lt;p&gt;Yes, as CSS has evolved, some of its features have become less relevant, but despite that it is steadily evolving, and it has &lt;a href="https://www.npmjs.com/package/sass" rel="noopener noreferrer"&gt;more&lt;/a&gt; downloads per week on npm than Tailwind. And Sass is not just being maintaned, it's having features added to it: there have been at least 4 minor releases in the last six months!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fezrymu1gguttpbisnuo8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fezrymu1gguttpbisnuo8.jpg" alt="Sass release stats" width="755" height="709"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next let's get to the technical part, get ready!&lt;/p&gt;

&lt;h2&gt;
  
  
  How utilities are structured
&lt;/h2&gt;

&lt;p&gt;We are going to talk quite a lot about the structure of utilities, so I will start with a general scheme of their structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-all.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-all.svg" alt="Schematic diagram of the utility structure" width="344" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is not very clear to you now, but we will analyze it in more detail later. For now, it will accompany us as a kind of mini-map, which will help us to orientate ourselves: at what stage of learning utilities we are at. And first of all, we will talk about naming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-naming.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-naming.svg" alt="Namin part" width="344" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a look at how things are going for popular tools&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind
&lt;/h3&gt;

&lt;p&gt;There is no consistent naming here. Utilities have opinionated names that are consonant with CSS properties or values. Let's consider a couple of examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;justify-*&lt;/code&gt;: content, items, self?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bg-none&lt;/code&gt; - remove all background? &lt;strong&gt;Nope&lt;/strong&gt;, only &lt;code&gt;background-image&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flex&lt;/code&gt; =&amp;gt; &lt;code&gt;display: flex&lt;/code&gt;, but &lt;code&gt;flex-auto&lt;/code&gt; =&amp;gt; &lt;code&gt;flex: 1 1 auto&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UnoCSS
&lt;/h3&gt;

&lt;p&gt;Let me remind you that UnoCSS is an engine, not just a framework. It allows you to build your own framework from so-called &lt;em&gt;presets&lt;/em&gt;. There are already &lt;a href="https://unocss.dev/presets/" rel="noopener noreferrer"&gt;many&lt;/a&gt; ready-made presets, or you can write your own. In particular, by plugging in one of these presets you can use the syntax of some popular libraries. Most often Tailwind is used&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F54jznrrtp112k605i4nk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F54jznrrtp112k605i4nk.jpg" width="613" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But in this example we will take a preset with &lt;a href="https://github.com/tachyons-css/tachyons" rel="noopener noreferrer"&gt;Tachyons&lt;/a&gt;, a once popular library. But here the naming is even more deplorable:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;br-0&lt;/code&gt; =&amp;gt; &lt;code&gt;border-right-width: 0&lt;/code&gt;, but &lt;code&gt;br1&lt;/code&gt; =&amp;gt; &lt;code&gt;border-radius:.125rem&lt;/code&gt;&lt;br&gt;
&lt;code&gt;b&lt;/code&gt;: bottom, border, &lt;code&gt;display: block&lt;/code&gt;? &lt;strong&gt;Nope&lt;/strong&gt;, this is &lt;code&gt;font-weight:bold&lt;/code&gt;!&lt;br&gt;
&lt;code&gt;normal&lt;/code&gt;: line-height, font-weight, letter-spacing?&lt;/p&gt;
&lt;h3&gt;
  
  
  Atomizer
&lt;/h3&gt;

&lt;p&gt;Here the situation with naming is better. &lt;a href="https://emmet.io/" rel="noopener noreferrer"&gt;Emmet&lt;/a&gt; abbreviations are used as the basis and new ones are added, in their likeness. It looks quite consistent:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Js(c)&lt;/code&gt; =&amp;gt; &lt;code&gt;justify-self: center&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Bg(n)&lt;/code&gt; =&amp;gt; &lt;code&gt;background: none&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Bgbm(c)&lt;/code&gt; =&amp;gt; &lt;code&gt;background-blend-mode: color&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  mlut
&lt;/h3&gt;

&lt;p&gt;mlut uses a single algorithm for all abbreviations. Some examples:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Js-c&lt;/code&gt; =&amp;gt; &lt;code&gt;justify-self: center&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Bdr&lt;/code&gt; =&amp;gt; &lt;code&gt;border-right: 1px solid&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Bdrd1&lt;/code&gt; =&amp;gt; &lt;code&gt;border-radius: 1px&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I am well aware that abbreviations is a controversial topic. They have their pros and cons&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Concise code&lt;/td&gt;
&lt;td&gt;There's a threshold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easier to write&lt;/td&gt;
&lt;td&gt;Not for everyone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slightly less code size&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqr55b7wllp2xu7ciq973.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqr55b7wllp2xu7ciq973.jpeg" alt="Concise code, easier to write..." width="500" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some people won't like them at all, purely aesthetically, and that's okay too. In their defense, abbreviations is all around us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In languages: &lt;code&gt;const&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;char&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In command line: &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;pwd&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Low-level: &lt;code&gt;Ldar&lt;/code&gt;, &lt;code&gt;Star&lt;/code&gt;, &lt;code&gt;SubSmi&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  extra credit question
  &lt;p&gt;Write in the comments who recognises the latest abbreviations&lt;/p&gt;



&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the abbreviation algorithm?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Avoid collisions with new properties and values in CSS, as it has been evolving rapidly in recent years&lt;/li&gt;
&lt;li&gt;The ability to output properties "in your mind" rather than having to memorize them. Once you've do this way and used the utility a couple of times, you'll quickly bring it to automaticity, and you won't need to spend any more mind fuel on remembering it again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reader can say that there are already ready-made abbreviations &lt;a href="https://emmet.io/" rel="noopener noreferrer"&gt;Emmet&lt;/a&gt;, which someone even managed to learn) Yes, they are not bad, but their problem is that there is no clear algorithm there. This was confirmed by Sergey Chikuyonok - the creator of Emmet (I asked him about it). So they do not solve the first problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it was
&lt;/h3&gt;

&lt;p&gt;Few people know, but there is such a NPM package: &lt;a href="https://www.npmjs.com/package/mdn-data" rel="noopener noreferrer"&gt;mdn-data&lt;/a&gt;. It contains several large json, which contain data about almost all CSS. About the properties, their syntaxes, media features and much more. I constantly turned to him during research.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fugb9npdpzs4v9szm33ot.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fugb9npdpzs4v9szm33ot.jpg" alt="JSON with all CSS properties" width="775" height="1059"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, I studied &lt;a href="https://www.w3.org/style/css/current-work" rel="noopener noreferrer"&gt;specs&lt;/a&gt; CSS. A lot of specs: both stable and drafts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9x0cqw0ia5ur4dnmedaz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9x0cqw0ia5ur4dnmedaz.jpg" alt="Some specs, that I saw" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The data from &lt;a href="https://chromestatus.com/metrics/css/popularity" rel="noopener noreferrer"&gt;Chrome Platform Status&lt;/a&gt; also helped me a lot. These are stats on the frequency of use of CSS properties on the Internet. Yes, this is also.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3kxiwepb40l52ffesgk3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3kxiwepb40l52ffesgk3.jpg" alt="Chrome platform status" width="800" height="838"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result of the research, I have this table for all the properties, where they are categorized into groups and most are given a popularity rating (this is the finished table with abbreviations):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxtqaxudy0oxrttabllln.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxtqaxudy0oxrttabllln.jpg" alt="Table of CSS properties and their abbreviations" width="754" height="938"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So of course it's been weeks of reflection, trial and error, and that's about it....&lt;/p&gt;

&lt;p&gt;Thus was born the abbreviation algorithm that we will now study&lt;/p&gt;

&lt;h3&gt;
  
  
  General algorithm for abbreviations
&lt;/h3&gt;

&lt;p&gt;The whole thing is described in &lt;a href="https://docs.mlut.style/section-concepts.html#kssref-concepts-naming" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, and here we'll go over the top of it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find properties that start with the same letter&lt;/li&gt;
&lt;li&gt;Rank them by popularity (mostly, but not only)&lt;/li&gt;
&lt;li&gt;Select groups with the same first word&lt;/li&gt;
&lt;li&gt;Make abbreviations within the groups&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The last screenshot with the table shows the result of this algorithm. It should be clarified that the general algorithm is used primarily for composing new abbreviations. That is, the abbreviations that are already there will not change anymore. This means that in practice, you will use the algorithm to abbreviate one entity, which we will consider next. And the general one is needed more for general understanding, so to speak.&lt;/p&gt;

&lt;h3&gt;
  
  
  Algorithm for reducing a single entity
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;I.&lt;/strong&gt; Shorten the name to the first letter of the property/value: &lt;code&gt;color&lt;/code&gt; =&amp;gt; &lt;code&gt;C&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;II.&lt;/strong&gt; If the name is of several words, the first letter of each word is taken: &lt;code&gt;color-adjust&lt;/code&gt; =&amp;gt; &lt;code&gt;Ca&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;III.&lt;/strong&gt; If two names have the same initial letter, a letter is added to the next name when sorting them by rating&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;color&lt;/code&gt; =&amp;gt; &lt;code&gt;C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cursor&lt;/code&gt; =&amp;gt; &lt;code&gt;Cs&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;IV.&lt;/strong&gt; If the title is of several words, the letter is added in the corresponding word in order&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;color&lt;/code&gt; =&amp;gt; &lt;code&gt;C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cursor&lt;/code&gt; =&amp;gt; &lt;code&gt;Cs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;color-scheme&lt;/code&gt; =&amp;gt; &lt;code&gt;Csc&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Order of adding a letter
&lt;/h4&gt;

&lt;p&gt;In the previous algorithm, there was a point about adding a letter if the resulting abbreviation already exists. Now we will specify its order, because it is important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I.&lt;/strong&gt; The consonant of the next syllable: &lt;code&gt;cursor&lt;/code&gt; =&amp;gt; &lt;code&gt;Cs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If the next syllable starts on a vowel, the nearest &lt;strong&gt;previous consonant&lt;/strong&gt; from it is taken&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;II.&lt;/strong&gt; Next consonant&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;content&lt;/code&gt; =&amp;gt; &lt;code&gt;Сt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;contain&lt;/code&gt; =&amp;gt; &lt;code&gt;Cn&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;III.&lt;/strong&gt; Next vowel (without skipping over a consonant)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;content&lt;/code&gt; =&amp;gt; &lt;code&gt;Сt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;counter-increment&lt;/code&gt; =&amp;gt; &lt;code&gt;Coi&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let's practice! We haven't learnt so much about the abbreviation algorithm for nothing. Below you'll find a few spoilers: in the title - the abbreviation, and inside - the property that corresponds to it. Try to expand them in mind according to the entity abbreviation algorithm, taking into account the order of adding letters&lt;/p&gt;

&lt;p&gt;
  Ps
  &lt;br&gt;
  position&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  Fnw
  &lt;br&gt;
  font-weight&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  Tf
  &lt;br&gt;
  transform&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  Flg
  &lt;br&gt;
  flex-grow&lt;br&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Weak parts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The popularity of properties changes. It is quite possible that some new CSS property will appear and become popular. Then when composing its abbreviation in your head you may make mistakes, because the derived abbreviation will already be occupied by some old property. Although this disadvantage will be more relevant for new mlut users&lt;/li&gt;
&lt;li&gt;Rare long properties may be difficult to recall&lt;/li&gt;
&lt;li&gt;Controversial situations are possible as CSS evolves. The algorithm is formal enough to write a program that could turn properties from JSON into abbreviations. But the problem is that the primary source here is not JSON, but specs, and things are not so unambiguous there. You have to follow their development, see where certain properties/features are moving. And then use the algorithm based on these inputs. But so far there have been almost no disputable situations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Syntax
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-syntax.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-syntax.svg" alt="Syntax part" width="344" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's see what popular tools offer us&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind
&lt;/h3&gt;

&lt;p&gt;There is not even any semblance of a specification here. For the most part, the syntax is a set of ad-hoc solutions with kludges in the form of arbitrary parts. Let's briefly go through it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Utility and value:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;util-value&lt;/code&gt; - simple value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-util-2&lt;/code&gt; - negative value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;util-[42px]&lt;/code&gt; - arbitrary value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[css-prop:value]&lt;/code&gt; - arbitrary CSS propertie and value&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Variants:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;variant:util-value&lt;/code&gt; - selectors and some at-rules&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;group/name:util-value&lt;/code&gt; - named groups&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@md:util-value&lt;/code&gt; - container queries&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Arbitrary variants
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;variant-[.class]:util&lt;/code&gt; - arbitrary variant value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[&amp;amp;:nth-child(3)]:util&lt;/code&gt; - arbitrary variant&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@[17.5rem]:util&lt;/code&gt; - container queries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UnoCSS
&lt;/h3&gt;

&lt;p&gt;We skip this part because Uno most often uses the Tailwind syntax. At least, it is the most advanced one available there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atomizer
&lt;/h3&gt;

&lt;p&gt;Suddenly, there is a specification! But in fact, the syntax covers quite few CSS features.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[&amp;lt;context&amp;gt;[:&amp;lt;pseudo-class&amp;gt;]&amp;lt;combinator&amp;gt;]&amp;lt;Style&amp;gt;[(&amp;lt;value&amp;gt;,&amp;lt;value&amp;gt;?,...)][&amp;lt;!&amp;gt;][:&amp;lt;pseudo-class&amp;gt;][::&amp;lt;pseudo-element&amp;gt;][--&amp;lt;breakpoint_identifier&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're not going to study it now, of course. I just inserted it to show that it exists in principle. For comparison: in Tailwind I had to run all over the docs looking for all syntax. Here I went to one &lt;a href="https://acss.io/guides/syntax.html#syntax" rel="noopener noreferrer"&gt;page&lt;/a&gt;, parsed the spec and already have an idea of what utilities can be and what they can do.&lt;/p&gt;

&lt;h3&gt;
  
  
  mlut
&lt;/h3&gt;

&lt;p&gt;mlut implements the so-called &lt;em&gt;Components Syntax&lt;/em&gt;, thanks to which we can expand compact utilities into complex CSS rules&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@:ah_O1_h&lt;/code&gt; =&amp;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="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;any-hover&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:ah_O1_h:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&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;I realize now it was like a "How to draw an owl" meme, but don't worry: we'll break down this same example next&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcgm13p10xf9m5gkggpal.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcgm13p10xf9m5gkggpal.png" alt="How to draw an owl" width="614" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why design the syntax?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Main goal&lt;/strong&gt; is conceptual closeness with CSS to grow organically with it&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Less opinions, more standards! (c) Me&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A well-designed syntax allows us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teach less about "fantasy" entities&lt;/li&gt;
&lt;li&gt;Avoid (minimize) conflicts with CSS&lt;/li&gt;
&lt;li&gt;Maintain usability&lt;/li&gt;
&lt;li&gt;Gain high expressiveness to implement the largest number of CSS features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, we are already masters and we know how to research CSS. So let's take the previously mentioned tools and dive into the specs!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fo72tz8r2fztr9o7y7oeq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fo72tz8r2fztr9o7y7oeq.jpg" alt="CSS research process" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this time, I didn't just study spec drafts, but "drafts of drafts". That's what you can call thematic issues in the very &lt;a href="https://github.com/w3c/csswg-drafts" rel="noopener noreferrer"&gt;repository&lt;/a&gt; CSSWG where the specs discussion is going on. It's also there in the screenshot above&lt;/p&gt;

&lt;p&gt;
  Fun fact
  &lt;br&gt;
  Did you know that most of the CSS specs was written by 2 people? Tab Atkins and Elika Etemad&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;I designed the first version of the syntax for about 2 weeks and was often around this situation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fp0gw3do7tiq92o4o4g4l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fp0gw3do7tiq92o4o4g4l.jpeg" alt="The process of designing the mlut syntax" width="500" height="756"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is what I got.....&lt;/p&gt;

&lt;h3&gt;
  
  
  Utility components syntax
&lt;/h3&gt;

&lt;p&gt;A syntax that divides a utility into &lt;em&gt;components&lt;/em&gt;, each of which corresponds to a part of a CSS rule. By parts here we mean at-rules, selector, properties and their values. Now, let's go back to one of the previous examples and look at it in a different way:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0zeau716xuqq3zt5fx9f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0zeau716xuqq3zt5fx9f.jpg" width="777" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now it's time to deal with the utility device diagram that has accompanied us throughout this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme.svg" alt="Util scheme" width="344" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CSS at-rule&lt;/strong&gt;: breakpoints, &lt;code&gt;@supports&lt;/code&gt;, etc&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pre-states&lt;/strong&gt; - part of the selector before the utility class name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;post-states&lt;/strong&gt; - part of selector after the utility class name&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's worth stepping back a bit here and introducing a concept like &lt;em&gt;conversion&lt;/em&gt;, since it's going to be mentioned a lot further down the line.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conversion&lt;/em&gt; - turning the abbreviation from a class name into a real CSS entity. It is found in almost all parts of utilities: values, states, at-rules, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  States
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-states.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-states.svg" alt="States part" width="344" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we get back to utility syntax, we need to remember the complexity of selectors in CSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple selector&lt;/strong&gt; - with one condition: &lt;code&gt;.class&lt;/code&gt;, &lt;code&gt;#id&lt;/code&gt;, &lt;code&gt;element&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(Pseudo-)Compound selector&lt;/strong&gt; - several simple selectors without combinators: &lt;code&gt;.class[attr]&lt;/code&gt;, &lt;code&gt;element.class&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex selector&lt;/strong&gt; - several simple/compound with combinators: &lt;code&gt;.class:hover + .item&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selector list&lt;/strong&gt; - comma-separated list from simple, compound or complex: &lt;code&gt;.class, .item + .item, a.active&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, states in mlut are a simplified &lt;strong&gt;selector list&lt;/strong&gt;. That means we can use almost all CSS selector features with similar DX in them. Even multiple selector (via &lt;code&gt;,&lt;/code&gt;). The main syntax differences are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:&lt;/code&gt; - merge states&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;,&lt;/code&gt; - split into a list&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;empty&amp;gt;:&lt;/code&gt; - space in selector&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at a couple of examples&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0c3194149y4x97mwx0gb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0c3194149y4x97mwx0gb.png" alt="Utility with post states" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhj1b433bi7l4tuyaq0ob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhj1b433bi7l4tuyaq0ob.png" alt="Utility with pre states" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  At-rules
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-at-rules.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-at-rules.svg" alt="At-rules part" width="344" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before exploring the structure of at-rules in our syntax, let's recall some of their features in CSS. At-rules in CSS also vary in complexity. There are simple ones, like &lt;code&gt;@import&lt;/code&gt; and &lt;code&gt;@charset&lt;/code&gt;. There are nested ones, like &lt;code&gt;@layer&lt;/code&gt;. And the most complex ones are called &lt;em&gt;conditional&lt;/em&gt; at-rules - we'll talk about them further.&lt;/p&gt;

&lt;p&gt;What at-rules consist of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conditions&lt;/strong&gt; - the conditions themselves. They can consist of operators, parentheses, and features / queries, depending on the specs: &lt;code&gt;(hover) and (min-width: 20rem)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operators&lt;/strong&gt; - logical: &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Features&lt;/strong&gt; - expressions, functions, etc: &lt;code&gt;(pointer: fine), style(color: green)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the example below, we can see that we have &lt;code&gt;&amp;lt;supports-condition&amp;gt;&lt;/code&gt; which contains everything else:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fc92aois0qvfnmlcwixy2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fc92aois0qvfnmlcwixy2.jpg" alt="@supports syntax from the specs" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What else is worth understanding about at-rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The composition is very different&lt;/li&gt;
&lt;li&gt;You can build complex expressions using operators&lt;/li&gt;
&lt;li&gt;You can embed them in each other&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F29whbm7n5dtiz5qfrv6z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F29whbm7n5dtiz5qfrv6z.jpg" alt="@media syntax from the specs" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now about the at-rules in mlut. This includes breakpoints and at-rules themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Breakpoints&lt;/strong&gt; have a separate sub-syntax because they are used much more frequently than other at-rules variants. In addition to the standard behavior, where the utility is enabled only from a certain screen size, we may also want the utility to work only in a range of widths or up to a certain size. That's why we need a subsyntax here.&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;/* sm:md,xl_P2r */&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;520px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;767px&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1200px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.sm&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:md&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;xl_P2r&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&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 the &lt;strong&gt;rules&lt;/strong&gt; themselves: &lt;code&gt;@media&lt;/code&gt;, &lt;code&gt;@supports&lt;/code&gt; and others.&lt;/p&gt;

&lt;p&gt;To compose complex expressions in both syntaxes, the following operators are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:&lt;/code&gt; =&amp;gt; &lt;code&gt;and&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;,&lt;/code&gt; =&amp;gt; &lt;code&gt;,&lt;/code&gt; (or)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, let's look at how rules work in at-rules. Each rule has a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Abbreviation: &lt;code&gt;m&lt;/code&gt;, &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt; - made by a known algorithm&lt;/li&gt;
&lt;li&gt;Converter - turns abbreviations into a chain of CSS-expressions&lt;/li&gt;
&lt;li&gt;Custom values - aliases for frequently used chains. They can be added by the user through the config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, the at-rules syntax in mlut allows to close &lt;strong&gt;the whole class&lt;/strong&gt; of these features in CSS. This means that if a new at-rule is added to CSS, it is very likely that it can be implemented in mlut without changing the syntax or modifications in the core. Let's look at some examples below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fm1j3jyd6c94s2h7jymnr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fm1j3jyd6c94s2h7jymnr.png" alt="Utility with complex @media" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And yes, at-rules in mlut can be combined!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fh9zb3s7md0af2oycbm44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fh9zb3s7md0af2oycbm44.png" alt="Utility with several at-rules" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, the first reaction might be something like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fn7n83wu3a2qoeicbg341.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fn7n83wu3a2qoeicbg341.jpg" alt="Priests meme" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But in my opinion, the syntax is powerful) And despite this, it still has weaknesses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can't (yet) write an arbitrary pseudoselector. Now it will be converted like this: &lt;code&gt;D-f_:pseudo&lt;/code&gt; =&amp;gt; &lt;code&gt;.D-f pseudo {...}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Possible conflicts of custom aliases in at-rules (&lt;code&gt;-myQuery&lt;/code&gt;) with CSS &lt;a href="https://drafts.csswg.org/mediaqueries-5/#custom-mq" rel="noopener noreferrer"&gt;custom media&lt;/a&gt; or cutsom selector. But it's not certain, as it's still quite draft there&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Value conversion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-values.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F150.lv%2Ft%2Fmlut%2Fpictures%2Futil-scheme-values.svg" alt="Values part" width="344" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have already touched a bit on the concept of conversion. Let me remind you that this is the name of converting a class name abbreviation into a real CSS value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ml-1&lt;/code&gt; =&amp;gt; &lt;code&gt;margin-left: 0.5rem&lt;/code&gt;&lt;br&gt;
&lt;code&gt;D-f&lt;/code&gt; =&amp;gt; &lt;code&gt;display: flex&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;How are other &lt;del&gt;competitors&lt;/del&gt; instruments doing&lt;/p&gt;
&lt;h3&gt;
  
  
  Tailwind
&lt;/h3&gt;

&lt;p&gt;The conversion here is quite modest. Here's what he can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Substituting a value from the dictionary in the config (theme)&lt;/li&gt;
&lt;li&gt;Color transparency: &lt;code&gt;bg-sky-500/75&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Imperative conversion, which we write by hand when adding a utility via plugin&lt;/li&gt;
&lt;li&gt;Parts of custom values, such as: more convenient writing of custom properties&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  UnoCSS
&lt;/h3&gt;

&lt;p&gt;It's about the same as Tailwind here&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F54jznrrtp112k605i4nk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F54jznrrtp112k605i4nk.jpg" width="613" height="339"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Atomizer
&lt;/h3&gt;

&lt;p&gt;There are a couple interesting places here, but nothing special either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Substitution of meaning from dictionary + RTL by design&lt;/li&gt;
&lt;li&gt;Color transparency: &lt;code&gt;C(#fff.5)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Convenient syntax for custom properties&lt;/li&gt;
&lt;li&gt;Multiple values(!): &lt;code&gt;Bgp(20px,50px)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Substituting custom values from config&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  mlut
&lt;/h3&gt;

&lt;p&gt;In mlut I developed a conversion system for almost arbitrary values. A few examples to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ml-1/7&lt;/code&gt; =&amp;gt; &lt;code&gt;margin-left: -14.3%&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Bdrd1r;2/5p&lt;/code&gt; =&amp;gt; &lt;code&gt;border-radius: 1rem 2px / 5%&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Why a conversion system?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;CSS property values are tricky. A little further on you'll see for yourself&lt;/li&gt;
&lt;li&gt;We want to stay close to the platform - remember the previous principles of tool design&lt;/li&gt;
&lt;li&gt;We want all this to be easy to write&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are the difficulties of working with CSS values? We should start with the fact that there is a special Value Definition Syntax to describe them (and not only for that)! And in the values themselves we can have: different data types, units of measurement, functions and many other things....&lt;/p&gt;

&lt;p&gt;But we are not afraid of difficulties, so let's go to &lt;a href="https://www.w3.org/TR/css-values-4/#value-defs" rel="noopener noreferrer"&gt;specs&lt;/a&gt; - study Value Definition Syntax...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fss670ef65l8nr03ajisd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fss670ef65l8nr03ajisd.jpg" alt="Value Definition Syntax в спеке" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now, when we look at the description of CSS properties in mdn-data, we'll understand what values it can take. And by looking at a few of these properties, we'll start to see patterns and commonalities, which will help design our conversion system closer to reality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F5lgo35bwidc2vuibeuvh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F5lgo35bwidc2vuibeuvh.jpg" width="700" height="44"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.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%2Folhoxnsg9aasbiv00xj7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Folhoxnsg9aasbiv00xj7.jpg" width="677" height="41"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.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%2Fimsxqyy75765iwo3m07q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fimsxqyy75765iwo3m07q.jpg" width="604" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An interesting point is that mdn-data also has JSON, where syntaxes that are reused in different properties (and not only properties) are placed. This has helped a lot in identifying patterns in values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ft8ihgwqs4w7plvhtkasb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ft8ihgwqs4w7plvhtkasb.jpg" alt="JSON with CSS syntaxes" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Basic concepts of conversion
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Converter&lt;/em&gt; - a function that converts a value from an abbreviated class to a real CSS value.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Transformer&lt;/em&gt; - a function that can still somehow change the converted CSS value. It is specified in the utility options.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conversion type&lt;/em&gt; - list of converters that are applied to the utility value. Each utility has it, and if it is not explicitly specified in the utility options, the default one is applied.&lt;/p&gt;

&lt;p&gt;For further understanding, it is worth to understand a bit how mlut utilities are represented in the code. All utilities are stored in a single &lt;em&gt;registry&lt;/em&gt;. Let's simplify it a bit, but it's basically a big dictionary, where keys are utility names and values are options. The options can be a property name, conversion type, and many other things.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;Apcr&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aspect-ratio&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'conversion'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'num-length'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="n"&gt;conversion&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the registry, there is a common config for utilities. It stores some settings related to all or large groups of utilities. In particular, conversion types are stored here. This is a dictionary where keys are the name of the type and values are a chain of converters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;conversion-types&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
  &lt;span class="s1"&gt;'num-length'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'num-length'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'global-kw'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'cust-prop'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;converters&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  General scheme of conversion
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The full utility value is broken down (by space or delimiter) into simple values&lt;/li&gt;
&lt;li&gt;Each simple value goes through a chain of converters until 1 of them not to trigger&lt;/li&gt;
&lt;li&gt;A transformer is applied to the CSS value&lt;/li&gt;
&lt;li&gt;The final value is substituted into the CSS rule&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let's look at converters in a little more detail. These are ordinary functions with the following signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@function&lt;/span&gt; &lt;span class="nf"&gt;convert-uv-number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$data&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="cm"&gt;/* ... */&lt;/span&gt;
  &lt;span class="k"&gt;@return&lt;/span&gt; &lt;span class="nv"&gt;$new-value&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;ul&gt;
&lt;li&gt;
&lt;code&gt;$value&lt;/code&gt; - initial value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$data&lt;/code&gt; - dictionary with additional data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main features of converters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The part of the name after &lt;code&gt;convert-uv-&lt;/code&gt; is used in conversion types&lt;/li&gt;
&lt;li&gt;Applied one after another&lt;/li&gt;
&lt;li&gt;Internally can use other converters&lt;/li&gt;
&lt;li&gt;Can write your own&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a couple more words should be said about the peculiarities of transformers. By signature, they are the same as converters. The main difference: they are applied once to the whole CSS value and return the new final value in its entirety. A typical case: converting a value into a CSS function, for example, into a filter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case: Gradient Utility
&lt;/h3&gt;

&lt;p&gt;We've explored a lot of individual concepts, and now it's worth seeing how it all works together. Let's take a case study: a CSS gradient utility, probably the most complex in mlut. It has the following options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;-Gdl&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;background-image&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'transformer'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'gradient'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'css-function'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'linear-gradient'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'conversion'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'gradient'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'multi-list-separator'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'keywords'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'position'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'gradient'&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="o"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, there is both a special conversion type and a transformer. And here is how this conversion type is described in the general config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;conversion-types&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
  &lt;span class="s1"&gt;'gradient'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'keyword'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'color'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'cust-prop'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Pl'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'number'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'angle'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'global-kw'&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="o"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a rather long chain of converters (and &lt;em&gt;pipeline&lt;/em&gt; is an advanced feature), but the following is notable. I didn't have to write a ton of imperative code to get a fairly complex conversion logic. I just made such a chain from the available converters and got the desired behavior. Here is how this utility works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsx1eva8ygzcbhf22399w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsx1eva8ygzcbhf22399w.png" alt="Utility for CSS gradients" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first reaction might be something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcttekrqphdlrgadoq8pz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcttekrqphdlrgadoq8pz.png" alt="WAT?" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But in my opinion, the utility turned out to be a masterpiece&lt;/p&gt;

&lt;h3&gt;
  
  
  Weak parts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No first-class support for CSS functions (yet): &lt;code&gt;calc()&lt;/code&gt;, &lt;code&gt;clamp()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the future, CSS values may take over the special characters used: &lt;code&gt;;&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Configuration refers to the customization of the tool. Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding values: colors, fonts, keywords&lt;/li&gt;
&lt;li&gt;Creating utilities&lt;/li&gt;
&lt;li&gt;Changing settings: breakpoints, new states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What do the known tools have to offer us?&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind
&lt;/h3&gt;

&lt;p&gt;Adding a value for utility is kind of easy.&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="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;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;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oswald, ui-serif&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But to add a utility, you have to write a plugin! At the same time, there are static and dynamic utilities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Static utilities
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Manually write CSS(-in-JS)-rules&lt;/li&gt;
&lt;li&gt;Variants will be available
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;plugin&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;addUtilities&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;addUtilities&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.content-auto&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="s1"&gt;content-visibility&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="s1"&gt;auto&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="s1"&gt;.content-hidden&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="s1"&gt;content-visibility&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="s1"&gt;hidden&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Dynamic utilities
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;You can add a dictionary with values&lt;/li&gt;
&lt;li&gt;Arbitrary syntax will be available&lt;/li&gt;
&lt;li&gt;Variants will be available
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;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;tabSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// map with values&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="nf"&gt;plugin&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;matchUtilities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;matchUtilities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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="na"&gt;tabSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&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;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tabSize&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  UnoCSS
&lt;/h3&gt;

&lt;p&gt;Adding values here is also quite simple:&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="nx"&gt;theme&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="nl"&gt;colors&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="s1"&gt;veryCool&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="s1"&gt;#0000ff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// class="text-very-cool"&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;But the situation with utilities is worse. There is a nice and concise api for this purpose here. The simplest utilities can be added in one line! But for something more complex you will have to write regexps and imperative conversion:&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="nx"&gt;rules&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;m-1&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="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.25rem&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="sr"&gt;/^p-&lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&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;d&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="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;rem`&lt;/span&gt; &lt;span class="p"&gt;})],&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  mlut
&lt;/h3&gt;

&lt;p&gt;In mlut all extensions are done in one config and as a rule: with a couple lines of code.&lt;/p&gt;

&lt;p&gt;How to add a new utility?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'mlut'&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;utils-data&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'utils'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="s1"&gt;'registry'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'Mm'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;margin-magick&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="o"&gt;),&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boilerplate is a bit bigger, but the simple utility is just as added in one line. That said, here's what it can do out of the box, in terms of conversion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number value: &lt;code&gt;Mm1r&lt;/code&gt; =&amp;gt; &lt;code&gt;margin-magick: 1rem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Global keywords: &lt;code&gt;Mm-ih&lt;/code&gt; =&amp;gt; &lt;code&gt;inherit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Custom properties: &lt;code&gt;Mm-$myCard?200&lt;/code&gt; =&amp;gt; &lt;code&gt;var(--ml-myCard, 200px)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Several values: &lt;code&gt;Mm10p;1/3&lt;/code&gt; =&amp;gt; &lt;code&gt;10% 33.3333%&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dispatching&lt;/p&gt;

&lt;p&gt;Now we'll digress a bit and recall the concept of "dispatching" from programming. &lt;em&gt;Dispatching&lt;/em&gt; is finding and choosing which function will be called for a certain type of data. It can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static - at the compile time&lt;/li&gt;
&lt;li&gt;Dynamic - at runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an example of static dispatching, here is an example in C++. Yes, suddenly we've moved from CSS to C++&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Calculator&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"5 + 3 = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// #17&lt;/span&gt;

  &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"5 - 3 = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&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;Here we have a structure with a pointer to a function. Already at the compilation stage it will be clear which function implementation to call on line #17.&lt;/p&gt;

&lt;p&gt;If you write in dynamic languages, you encounter dynamic dispatching (hereinafter referred to as DD) almost every day. Here you can think of the usual method search through a chain of prototypes in JavaScript. But there are different variants of DD and one more of them is often encountered: DD based on a virtual table. The idea is that we have some table in memory, in which it is prescribed that for such data type this and that function implementation should be called. For a general understanding of the question, I will give you the following code:&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;class&lt;/span&gt; &lt;span class="nc"&gt;Toad&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sleep&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Lizard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sleep&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// #14&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Toad&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;lull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toad&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Imagine that this is not JavaScript, but some other language with classes. On line #14, how to understand: which implementation of the sleep method to call?&lt;/p&gt;

&lt;p&gt;Now the question is: How can we use these concepts when designing our program? Let's look at an example from mlut, which uses an approach similar to DD with a virtual table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* _at-rules.scss */&lt;/span&gt;
&lt;span class="nv"&gt;$at-rules-db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'media'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'alias'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'m'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'default'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'supports'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'alias'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'s'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'container'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'alias'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="o"&gt;,&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="cm"&gt;/* _mk-ar.scss */&lt;/span&gt;
&lt;span class="k"&gt;@mixin&lt;/span&gt; &lt;span class="nf"&gt;-generate-ar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$at-rules&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this-util&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$ar-list&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cur-index&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$last-index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* ... */&lt;/span&gt;

  &lt;span class="nv"&gt;$converter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$at-rules-db&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$ar-name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'converter'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$ar-name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$converter&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$ar-str&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this-util&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&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;Here we have an excerpt from the code in which at-rules conversion takes place. We have &lt;code&gt;$at-rules-db&lt;/code&gt; - a config with data about all at-rules: their abbreviations, converters etc. We can use this config as a kind of virtual table. Then, in the &lt;code&gt;-generate-ar&lt;/code&gt; mixin, we see which at-rule we are working with (&lt;code&gt;$ar-name&lt;/code&gt;), and based on that, we get the necessary converter from the config. Next, we apply it to the &lt;code&gt;$ar-str&lt;/code&gt; abbreviation chain.&lt;/p&gt;

&lt;p&gt;What are the advantages of this approach? It gives us good extensibility. When adding a new at-rule, we don't need to go to the kernel code and fix something. That is, a new at-rule can be added simply from the config, when connecting the library. We will consider such an example further on.&lt;/p&gt;

&lt;p&gt;Some time ago I received an &lt;a href="https://github.com/mr150/mlut/issues/51" rel="noopener noreferrer"&gt;issue&lt;/a&gt; with a question about container queries support. I answered it with a ~20 lines snippet of code that could be used to add basic support for this feature via config!&lt;/p&gt;

&lt;p&gt;In comparison, to add container queries to Tailwind, the guys had to come up with a new syntax and write a 70 line &lt;a href="https://github.com/tailwindlabs/tailwindcss-container-queries/blob/main/src/index.ts" rel="noopener noreferrer"&gt;plugin&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  JIT engine
&lt;/h2&gt;

&lt;p&gt;Lastly, let's talk about JIT engines in Atomic CSS tools. But first, let's remember a bit of history.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Flg88w970ywvr97ryjtwt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Flg88w970ywvr97ryjtwt.jpg" alt="Ancient CSS frameworks" width="636" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How the old generation tools (Tailwind v1, Tachyons, etc) worked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate over9000 utilities for all occasions&lt;/li&gt;
&lt;li&gt;Use some of them in our markup&lt;/li&gt;
&lt;li&gt;Add a program to the build that looks at our markup and removes unused CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are the problems with this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is tedious or impossible to use arbitrary utility values&lt;/li&gt;
&lt;li&gt;Regularly have to edit config to add new utility values&lt;/li&gt;
&lt;li&gt;Large CSS bundle in development mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve these problems there is a new approach called &lt;em&gt;JIT&lt;/em&gt; mode. There is nothing in common with JIT compilers here, it's more of a marketing name. With JIT mode everything becomes easier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing (almost) arbitrary utilities in markup&lt;/li&gt;
&lt;li&gt;The JIT engine looks at our code and generates only the utilities we used&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Historical note
  &lt;p&gt;Some believe that the JIT engine first appeared in Windi CSS to solve Tailwind v2 problems. Then, the Tailwind team &lt;del&gt;stole&lt;/del&gt; adopted the solution. I think they were the ones who coined the term &lt;em&gt;JIT-engine&lt;/em&gt; back then.&lt;/p&gt;

&lt;p&gt;But few people know that the JIT engine was still in the first versions of the Atomizer, back in 2015! Knowing this, it was amusing to see the pathos statements of its aforementioned "reinventors", and the &lt;a href="https://antfu.me/posts/reimagine-atomic-css" rel="noopener noreferrer"&gt;musings&lt;/a&gt; of Anthony Fu on the topic&lt;/p&gt;



&lt;/p&gt;

&lt;p&gt;General scheme of JIT engine operation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find the content files&lt;/li&gt;
&lt;li&gt;Scan them and get the utilities&lt;/li&gt;
&lt;li&gt;Generate CSS for found utilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And already our regular column: review of current solutions&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind
&lt;/h3&gt;

&lt;p&gt;At the heart of the engine here is a big PostCSS plugin. This means we get both the pros and cons of PostCSS. It's easy to do integrations with bundlers and other plugins from the ecosystem. But you have to work with AST PostCSS and settle for medium performance.&lt;/p&gt;

&lt;p&gt;Although a new engine, Oxide, is planned for Tailwind v4, which will solve some of the weaknesses of the current one&lt;/p&gt;

&lt;h3&gt;
  
  
  UnoCSS
&lt;/h3&gt;

&lt;p&gt;It uses its own utility generator. Judging by &lt;a href="https://github.com/unocss/unocss/blob/main/bench/results/2023-11-08-07-53-41.md" rel="noopener noreferrer"&gt;benchmark&lt;/a&gt; and authors' statements: it is the fastest and there are a lot of optimizations. There is integration with the main popular bundlers. Also, there are many additional features, such as attributify and shortcuts&lt;/p&gt;

&lt;h3&gt;
  
  
  Atomizer
&lt;/h3&gt;

&lt;p&gt;This is also good: it uses its own utility generator. It is relatively simple, but with legacy dependencies like lodash. There are also integrations: for most bundlers there are plugins via &lt;a href="https://unplugin.unjs.io/" rel="noopener noreferrer"&gt;unplugin&lt;/a&gt;, and for some of them there are separate packages&lt;/p&gt;

&lt;h3&gt;
  
  
  mlut
&lt;/h3&gt;

&lt;p&gt;mlut has distinguished itself here too, but not for the better. Now let's understand why. Here we have almost like in compilers: there is a frontend and a backend&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front: TypeScript&lt;/th&gt;
&lt;th&gt;Back: Sass&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CLI / plugin&lt;/td&gt;
&lt;td&gt;Utilities generator and settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JIT engine&lt;/td&gt;
&lt;td&gt;CSS library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Sass compiler&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The main question here is: how to link Sass and JS? We need to somehow get data from Sass config, pass the collected utilities to the generator etc. To solve these problems we use an approach that I call: &lt;em&gt;Sass in JS&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnnn80g4e403r3t9s2fan.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnnn80g4e403r3t9s2fan.jpg" alt="Sass in JS" width="500" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The gist of it is this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load the code of the required Sass module&lt;/li&gt;
&lt;li&gt;Add the code to it&lt;/li&gt;
&lt;li&gt;Compile the final script in CSS&lt;/li&gt;
&lt;li&gt;(if necessary) Get data from the output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it looks like in code&lt;/p&gt;

&lt;p&gt;We take the contents of the user's input Sass file (Sass entry point), or the default config from the example below, if there is no input file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* default userConfig */&lt;/span&gt;
&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s2"&gt;"sass:map"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s2"&gt;"../sass/tools/settings"&lt;/span&gt; &lt;span class="nt"&gt;as&lt;/span&gt; &lt;span class="nt"&gt;ml&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we add some Sass code to the end of the input file, where we execute the logic. For example, get something from the settings. Compile the resulting code:&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;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;css&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compileStringAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;userConfig&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt; a{ all: map.keys(map.get(ml.$utils-db, "utils", "registry")); }&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="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;compressed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;loadPaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is this funny CSS rule, where the &lt;code&gt;all&lt;/code&gt; property contains a list of names of all utilities from the registry. Then, we just extract the target data from it&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Ps"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"T"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"R"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"-X"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"-Y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;"-I"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;/* etc */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few more interesting features of Sass as a language&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No rantime&lt;/strong&gt;. The code is simply compiled and some CSS is output. So this is like a classic PHP: for every style rebuild, "the world is re-created" - all the settings are loaded, including the utility registry of 2k+ lines. Yes, this is not particularly optimal, but thanks to the native &lt;a href="https://www.npmjs.com/package/sass-embedded" rel="noopener noreferrer"&gt;Dart-compiler&lt;/a&gt; Sass - works quite fast. On a small project, even faster than Tailwind v3, especially cold starts. Because every start here is like a cold start, although at some point, the JIT in the JS engine may turn on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Too few features in the language&lt;/strong&gt;. No classes and objects, not even regexp. But there are some things from FP: higher-order functions, immutable data structures, etc. It may seem strange, but writing in such a language is an interesting and even useful experience. Perhaps something similar is experienced by those who work with Clojure, but it's not certain, I haven't tried it yet. The idea is that when a language has few features, it forces you to combine a small number of basic elements to get complex logic. And that's one of the basic skills of a good engineer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maximum integration with CSS&lt;/strong&gt;. At one time I thought: "why do I keep writing a complex program in Sass, instead of rewriting everything in &lt;del&gt;Rust&lt;/del&gt; JS". One of the answers was precisely "maximum integration". Where authors of other generators had to write logic to work with CSS selectors, I took functions from the Sass standard library. Where in JS you have to take into account the units of measurement of numbers (1px, 1rem), in Sass such values are first-class citizens. The same can be said about translating Sass lists into CSS lists and many other things.&lt;/p&gt;

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

&lt;p&gt;Here are some of the insights I gained while working on the project:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't be afraid of crazy ideas&lt;/strong&gt;. For example, such as: "Write a complex program on the CSS preprocessor". It is quite possible that in the process you will create something innovative and outstanding. Or just get a very useful experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try to go all the way&lt;/strong&gt;, to get to the root of the problem. And having understood the root of the problem, come up with a solution that will eliminate the true cause so that the problem would not arise in principle. After all, often when we solve some problem, we stop at treating some consequence of a more fundamental problem or a semi-kludge solution. Usually business gives us limited resources and this is understandable. But as soon as the opportunity arises - try the above approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure is also a result&lt;/strong&gt;. As astrophysicist Konstantin Batygin used to say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;99% of a scientist's work is fails.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even if you didn't manage to make the fastest framework at the first attempt, you shouldn't be upset. You got useful experience that somehow changed and improve you. For example, you can make a good talk out of it and become a speaker at a tier 1 conference&lt;/p&gt;

&lt;p&gt;And lastly, I want to explain again why I did all this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I was trying to solve the problems&lt;/strong&gt; of the existing tools we looked at in the beginning. I wanted to try to maximize the potential of the Atomic CSS approach. I was excited about it because I had dreamed of working with such a tool, but at that moment, there was no such tool on the market.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I want to show the community&lt;/strong&gt; all these original ideas and interesting technical details that mlut has. I think it will help the industry at least a little bit. So right now I'm promoting the tool and ideally want it to make it into the State of CSS survey. So would appreciate any feedback and help on this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I have a dream&lt;/strong&gt;: I want to become a full-time open source developer. I see the project as the beginning of my career in this field and a "warm-up before the big game". I should add that I have no goal to "take over the world" with mlut or "kill" Tailwind. I am well aware that the tool is rather niche and doesn't have such potential by design. But I would like to confidently enter the market, fight with the top analogues, find my audience and benefit them!&lt;/p&gt;

&lt;p&gt;That's it! Subscribe to me on X, put stars on &lt;a href="https://github.com/mlutcss/mlut" rel="noopener noreferrer"&gt;github&lt;/a&gt; mlut, well I'll be glad to see your comments!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>mlut - a new word in the Utility-First CSS approach</title>
      <dc:creator>Valik Ulyanov</dc:creator>
      <pubDate>Sun, 02 Jul 2023 18:54:16 +0000</pubDate>
      <link>https://dev.to/mr150/mlut-a-new-word-in-the-utility-first-css-approach-gbl</link>
      <guid>https://dev.to/mr150/mlut-a-new-word-in-the-utility-first-css-approach-gbl</guid>
      <description>&lt;p&gt;Today I want to tell you about my open source project: &lt;a href="https://github.com/mr150/mlut" rel="noopener noreferrer"&gt;mlut&lt;/a&gt;. This is an Atomic CSS toolkit with &lt;a href="https://sass-lang.com/" rel="noopener noreferrer"&gt;Sass&lt;/a&gt; and ergonomics for creating styles of any complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Main features

&lt;ul&gt;
&lt;li&gt;🔠 Strong naming convention
&lt;/li&gt;
&lt;li&gt;🎨 Almost arbitrary by design
&lt;/li&gt;
&lt;li&gt;✋ Great ergonomics
&lt;/li&gt;
&lt;li&gt;🔨 Easiest utils generation
&lt;/li&gt;
&lt;li&gt;🧩 Handy extension
&lt;/li&gt;
&lt;li&gt;👀 And something else...
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;How I came to it&lt;/li&gt;

&lt;li&gt;Weak parts and plans&lt;/li&gt;

&lt;li&gt;Wrap up&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslytb8vecnhhentzyaeq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslytb8vecnhhentzyaeq.gif" alt="GIF animation with usage example" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Main features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Strong naming convention
&lt;/h3&gt;

&lt;p&gt;❌ &lt;strong&gt;Tailwindcss&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.justify-*&lt;/code&gt;: content, items or self?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.flex&lt;/code&gt; =&amp;gt; &lt;code&gt;display: flex&lt;/code&gt;, but &lt;code&gt;.flex-auto&lt;/code&gt; =&amp;gt; &lt;code&gt;flex: 1 1 auto;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.bg-none&lt;/code&gt; - reset all background? Nope, only &lt;code&gt;background-image&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;Tachyons&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.br-0&lt;/code&gt; =&amp;gt; &lt;code&gt;border-right-width: 0&lt;/code&gt;, but &lt;code&gt;.br1&lt;/code&gt; =&amp;gt; &lt;code&gt;border-radius:.125rem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.normal&lt;/code&gt;: line-height, font-weight or letter-spacing?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.b&lt;/code&gt;: bottom, border or &lt;code&gt;display: block&lt;/code&gt;? Nope, it is &lt;code&gt;font-weight:bold&lt;/code&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;mlut&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.Jc-c&lt;/code&gt; =&amp;gt; &lt;code&gt;justify-content: center&lt;/code&gt;, &lt;code&gt;.Js-c&lt;/code&gt; =&amp;gt; &lt;code&gt;justify-self: center&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.Bdr&lt;/code&gt; =&amp;gt; &lt;code&gt;border-right: 1px solid&lt;/code&gt;, &lt;code&gt;.Bdrd1&lt;/code&gt; =&amp;gt; &lt;code&gt;border-radius: 1px&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://mr150.github.io/mlut/section-concepts.html#kssref-concepts-naming" rel="noopener noreferrer"&gt;One algorithm&lt;/a&gt; for all. If you know CSS, you almost know mlut.&lt;/p&gt;

&lt;h3&gt;
  
  
  Almost arbitrary by design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://mr150.github.io/mlut/section-concepts.html#kssref-concepts-values" rel="noopener noreferrer"&gt;values&lt;/a&gt;: &lt;code&gt;.Ml-1/7&lt;/code&gt; =&amp;gt; &lt;code&gt;margin-left: -14.3%&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mr150.github.io/mlut/section-concepts.html#kssref-concepts-states" rel="noopener noreferrer"&gt;states&lt;/a&gt;: &lt;code&gt;Bgc-red200_h,f&lt;/code&gt; =&amp;gt; &lt;code&gt;.Bgc-red200_h\,f:hover, .Bgc-red200_h\,f:focus {...}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mr150.github.io/mlut/section-concepts.html#kssref-concepts-at_rules" rel="noopener noreferrer"&gt;at-rules&lt;/a&gt;: &lt;code&gt;@:p-c,w&amp;gt;=80r_D-f&lt;/code&gt; =&amp;gt; &lt;code&gt;@media (pointer: coarse), (min-width: 90rem) {...}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You no need to special arbitrary syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  Great ergonomics
&lt;/h3&gt;

&lt;p&gt;Shorter class names:&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;!-- Example from https://www.shopify.com/ --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Tailwindcss --&amp;gt;&lt;/span&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;"hidden md:block md:col-span-6 md:col-start-7 lg:col-span-5 lg:col-start-8 pb-6 relative md:max-h-[130vh] reduced-motion:translate-y-0 will-change-transform duration-1000 ease-in-out transition-all reduced-motion:opacity-100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- mlut --&amp;gt;&lt;/span&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;"D-n md_D md_Gc-s1 md_Gcs7 lg_Gc-s5 lg_Gcs8 Pb6u Ps md_Mxh130vh Tf @:pfrm_-Try0 Wlc-tf Tsd1s Tstf-eio Ts-all @:pfrm_O1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&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;Convenient syntax for complex values, states and at-rules.&lt;br&gt; It is like Vim for CSS.&lt;/p&gt;

&lt;h4&gt;
  
  
  ❌ Tailwindcss:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[@media(any-hover:hover){&amp;amp;:hover}]:opacity-100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;text-[color:var(--my-var,#333)]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;supports-[margin:1svw]:ml-[1svw]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ✅ mlut:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@:ah_O1_h&lt;/code&gt; =&amp;gt; &lt;code&gt;@media (any-hover){ .\@\:ah_O1_h:hover{ opacity: 1 }}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C-$myVar?#333&lt;/code&gt; =&amp;gt; &lt;code&gt;color: var(--ml-myVar, #333)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@s_Ml1svw&lt;/code&gt; =&amp;gt; &lt;code&gt;@supports (margin-left: 1svw) { .\@s_Ml1svw { margin-left: 1svw } }&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Easiest utils generation
&lt;/h3&gt;

&lt;p&gt;JIT mode planned but here is what we have now:&lt;/p&gt;

&lt;h4&gt;
  
  
  Range &lt;a href="https://mr150.github.io/mlut/section-how_to.html#kssref-how_to-mk_utils-range" rel="noopener noreferrer"&gt;syntaxes&lt;/a&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'mlut'&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;utils&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'Bdw'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;2u&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;4&lt;/span&gt;&lt;span class="o"&gt;],),&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// result CSS&lt;/span&gt;
&lt;span class="nc"&gt;.Bdw2u&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.Bdw3u&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.Bdw4u&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&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;h4&gt;
  
  
  Components syntax
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'mlut'&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;utils&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'D'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'xl _ib_ b af'&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// result CSS&lt;/span&gt;
&lt;span class="nc"&gt;.D-ib&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;D-ib_b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;D-ib_af&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1200px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.xl_D-ib&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&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;h4&gt;
  
  
  Groups
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'mlut'&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;utils&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'Paddings'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;150&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// result CSS&lt;/span&gt;
&lt;span class="nc"&gt;.P150&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.Pt150&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.Pr150&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Top-level apply
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@include&lt;/span&gt; &lt;span class="nd"&gt;ml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'^0:+_-MyPad1.5;3u -Gdl-r,#0f0;30p,#00f;80p,red'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// result CSS&lt;/span&gt;
&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;-Ctx0&lt;/span&gt;&lt;span class="err"&gt; + .\^&lt;/span&gt;&lt;span class="na"&gt;0&lt;/span&gt;&lt;span class="err"&gt;\&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="n"&gt;_-MyPad1&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="mi"&gt;.5&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nt"&gt;3u&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;--ml-myPad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="mi"&gt;.5rem&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.-Gdl-r&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nn"&gt;#0f0&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nt"&gt;30p&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nn"&gt;#00f&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nt"&gt;80p&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;red&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;#0f0&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;#00f&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handy extension
&lt;/h3&gt;

&lt;p&gt;Add utilities, states and custom at-rules with few lines of code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'mlut'&lt;/span&gt; &lt;span class="nt"&gt;as&lt;/span&gt; &lt;span class="nt"&gt;ml&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;add&lt;/span&gt; &lt;span class="nt"&gt;utilities&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;utils-data&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'utils'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="s1"&gt;'registry'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'Mil'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;margin-inline&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'Ir'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
          &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;image-rendering&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="s1"&gt;'keywords'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'p'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;pixelated&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="o"&gt;),&lt;/span&gt;

  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;add&lt;/span&gt; &lt;span class="nt"&gt;states&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;utils-config&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'states'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="s1"&gt;'custom'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'are'&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'[aria-expanded=“true”]'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;),&lt;/span&gt;
  &lt;span class="o"&gt;),&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@include&lt;/span&gt; &lt;span class="nd"&gt;ml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Mil-15_-are Ir-p'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// result CSS&lt;/span&gt;
&lt;span class="nc"&gt;.Mil-15_-are&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;aria-expanded&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nt"&gt;true&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;margin-inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.Ir-p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;image-rendering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pixelated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  And something else...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;⚡️ Written in Sass and includes all its benefits&lt;/li&gt;
&lt;li&gt;🔧 &lt;strong&gt;Fully customizable&lt;/strong&gt;: change tokens, utilities names and any settings&lt;/li&gt;
&lt;li&gt;✨ &lt;strong&gt;Easy to integrate&lt;/strong&gt; in existing project. No name collisions with your CSS in the most projects. Increasing specificity in &lt;a href="https://mr150.github.io/mlut/section-settings.html#kssref-settings-utils-other-up_specificity" rel="noopener noreferrer"&gt;one line&lt;/a&gt; or for &lt;a href="https://mr150.github.io/mlut/section-concepts.html#kssref-concepts-states-special-tu" rel="noopener noreferrer"&gt;one&lt;/a&gt; utility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I came to it
&lt;/h2&gt;

&lt;p&gt;Now, I'll tell you a little story. &lt;br&gt;&lt;br&gt;
The first developments were back in 2018: I started making it for myself and the team. Tailwind was in its infancy then, and other analogs did not suit me. At some point, I decided to make it a full-fledged open source. Used it myself, sometimes with the team. Had a few releases, but no time to promote it after that.&lt;/p&gt;

&lt;p&gt;At one time I surpassed Tailwind in features (and even now we almost on par, without JIT), but alas, I missed my chance to get hype. Maybe the relevance of the project has lost a bit, but I think it's not worth leaving it in the drawer.&lt;/p&gt;

&lt;p&gt;And if I overcome the following weaknesses, mlut can fight with the top analogues and in some ways will be better than them!&lt;/p&gt;

&lt;h2&gt;
  
  
  Weak parts and plans
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;no CLI - planned first thing&lt;/li&gt;
&lt;li&gt;no JIT-mode - also planned. The backend for it is already implemented as a top-level apply&lt;/li&gt;
&lt;li&gt;as a consequence: for the production build, in addition to Sass, 1-2 other packages are recommended&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;You can find instructions on how to get started with mlut and other details in the &lt;a href="https://mr150.github.io/mlut/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;. Perhaps in the future I will write separate technical articles on working with mlut. Let me know if you would be interested)&lt;/p&gt;

&lt;p&gt;Thank you for reading my story! I would be very grateful for any feedback on the project. If you like it, please put a star on the &lt;a href="https://github.com/mr150/mlut" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. Also, you can share &lt;a href="https://twitter.com/mr150_/status/1654194960369963020" rel="noopener noreferrer"&gt;this&lt;/a&gt; tread on Twitter. All this will help a lot to promote the project!&lt;/p&gt;

</description>
      <category>css</category>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
