DEV Community

Cover image for mlut - a new word in the Utility-First CSS approach
Valik Ulyanov
Valik Ulyanov

Posted on

mlut - a new word in the Utility-First CSS approach

Today I want to tell you about my open source project: mlut. This is an Atomic CSS toolkit with Sass and ergonomics for creating styles of any complexity.

Table of Contents

GIF animation with usage example

Main features

Strong naming convention

❌ Tailwindcss:

  • .justify-*: content, items or self?
  • .flex => display: flex, but .flex-auto => flex: 1 1 auto;
  • .bg-none - reset all background? Nope, only background-image

❌ Tachyons:

  • .br-0 => border-right-width: 0, but .br1 => border-radius:.125rem
  • .normal: line-height, font-weight or letter-spacing?
  • .b: bottom, border or display: block? Nope, it is font-weight:bold!

βœ… mlut:

  • .Jc-c => justify-content: center, .Js-c => justify-self: center
  • .Bdr => border-right: 1px solid, .Bdrd1 => border-radius: 1px

One algorithm for all. If you know CSS, you almost know mlut.

Almost arbitrary by design

  • values: .Ml-1/7 => margin-left: -14.3%
  • states: Bgc-red200_h,f => .Bgc-red200_h\,f:hover, .Bgc-red200_h\,f:focus {...}
  • at-rules: @:p-c,w>=80r_D-f => @media (pointer: coarse), (min-width: 90rem) {...}

You no need to special arbitrary syntax.

Great ergonomics

Shorter class names:

<!-- Example from https://www.shopify.com/ -->

<!-- Tailwindcss -->
<div class="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">...</div>

<!-- mlut -->
<div class="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">...</div>
Enter fullscreen mode Exit fullscreen mode

Convenient syntax for complex values, states and at-rules.
It is like Vim for CSS.

❌ Tailwindcss:

  • [@media(any-hover:hover){&:hover}]:opacity-100
  • text-[color:var(--my-var,#333)]
  • supports-[margin:1svw]:ml-[1svw]

βœ… mlut:

  • @:ah_O1_h => @media (any-hover){ .\@\:ah_O1_h:hover{ opacity: 1 }}
  • C-$myVar?#333 => color: var(--ml-myVar, #333)
  • @s_Ml1svw => @supports (margin-left: 1svw) { .\@s_Ml1svw { margin-left: 1svw } }

Easiest utils generation

JIT mode planned but here is what we have now:

Range syntaxes

@use 'mlut' with (
  $utils: (
    'Bdw': ([2u, 4],),
  )
);

// result CSS
.Bdw2u {
  border-width: 0.5rem;
}

.Bdw3u {
  border-width: 0.75rem;
}

.Bdw4u {
  border-width: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

Components syntax

@use 'mlut' with (
  $utils: (
    'D': ('xl _ib_ b af'),
  )
);

// result CSS
.D-ib {
  display: inline-block;
}

.D-ib_b::before {
  display: inline-block;
}

.D-ib_af::after {
  display: inline-block;
}

@media (min-width: 1200px) {
  .xl_D-ib {
    display: inline-block;
  }
}
Enter fullscreen mode Exit fullscreen mode

Groups

@use 'mlut' with (
  $utils: (
    'Paddings': (150),
  )
);

// result CSS
.P150 {
  padding: 150px;
}

.Pt150 {
  padding-top: 150px;
}

.Pr150 {
  padding-right: 150px;
}

// etc.
Enter fullscreen mode Exit fullscreen mode

Top-level apply

@include ml.apply(
  '^0:+_-MyPad1.5;3u -Gdl-r,#0f0;30p,#00f;80p,red'
);

// result CSS
.-Ctx0 + .\^0\:\+_-MyPad1\.5\;3u {
  --ml-myPad: 1.5rem 0.75rem;
}

.-Gdl-r\,\#0f0\;30p\,\#00f\;80p\,red {
  background-image: linear-gradient(to right, #0f0 30%, #00f 80%, red);
}
Enter fullscreen mode Exit fullscreen mode

Handy extension

Add utilities, states and custom at-rules with few lines of code

@use 'mlut' as ml with (
  // add utilities
  $utils-data: (
    'utils': (
      'registry': (
        'Mil': margin-inline,
        'Ir': (
          'properties': image-rendering,
          'keywords': (
            'p': pixelated,
          ),
        ),
      ),
    ),
  ),

  // add states
  $utils-config: (
    'states': (
      'custom': (
        'are': '[aria-expanded=β€œtrue”]',
      ),
    ),
  ),
);

@include ml.apply('Mil-15_-are Ir-p');

// result CSS
.Mil-15_-are[aria-expanded=β€œtrue”] {
  margin-inline: -15px;
}

.Ir-p {
  image-rendering: pixelated;
}
Enter fullscreen mode Exit fullscreen mode

And something else...

  • ⚑️ Written in Sass and includes all its benefits
  • πŸ”§ Fully customizable: change tokens, utilities names and any settings
  • ✨ Easy to integrate in existing project. No name collisions with your CSS in the most projects. Increasing specificity in one line or for one utility.

How I came to it

Now, I'll tell you a little story.

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.

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.

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

Weak parts and plans

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

Wrap up

You can find instructions on how to get started with mlut and other details in the documentation. Perhaps in the future I will write separate technical articles on working with mlut. Let me know if you would be interested)

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 Github. Also, you can share this tread on Twitter. All this will help a lot to promote the project!

Top comments (5)

Collapse
 
sarahokolo profile image
sahra πŸ’«

Really great work Valik, although, i have a few thoughts floating through my mind right now, and I'd be honest, the first question is "what does mlut mean"?πŸ˜… like is it an abbreviation for something, if not, what made you name it that? Basic curiosity here. Second, I don't know, the project is great and all, but it just feels like an overly complicated abbreviation of the CSS properties and values, and i feel like using it for a large project might get very dreadful. As the code doesn't seem to be quite self explanatory when using it, making the whole code look so much like congested gibberish, like taking a look at this piece of mlut code you provided:

<div class="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">...</div>
Enter fullscreen mode Exit fullscreen mode

This would probably be like a nightmare when implemented on 200 lines of code or more. I love the idea of abbreviations and all, but I think this is a little too vague at first glance, and would require quite a few brain cells to decode, wasting the developers time even moreπŸ€·β€β™€οΈ. I would have suggested not making everysingle thing abbreviated and still keep some words for better understanding, but then it would just be like tailwind.

Collapse
 
mr150 profile image
Valik Ulyanov

Thanks for the feedback! mlut is short for My Little UI Toolkit) And about the abbreviated classes I answered below, see previous comments

Collapse
 
lyqht profile image
Estee Tey

Reading this article on mlut, I find it much easier to read tailwindcss classes than the acronymized classes in mlut / tachyons. Unless the autocomplete/ intellisense is very strong so that when I type say 'justify-content', there's also autocomplete for 'Jc-c', I think the mental hurdle makes this css framework unviable for dev teams.

Collapse
 
mr150 profile image
Valik Ulyanov

Thanks for the feedback! Yes, abbreviated classes have a threshold and not everyone will like them. But if you know them, they become very pleasant and convenient to work with! And learning them is much easier than you think, because they are all made according to a clear algorithm. Knowing the algorithm and the CSS property, you can easily compose the name of the class in your head, without having to learn it by heart!

Collapse
 
adriansalvatori profile image
Adrian Salvatori • Edited

I gotta agree with Estee.

I mean, this is a beautiful approach, if you're Wolverine. Not so much if you're Cyclops and you need to see for your whole team. That's pretty much the reason why Tailwind has stuck with devs in the late years.