CSS Utility Belt
Purpose
There are so many choices when it comes to CSS libraries. Then inside of that library there are a ton of different ways to use it. Some of these libraries work well right out of the box, while others require reading about how to configure it to do what you need. The purpose of this library is to be as minimal as possible while still enabling complex UIs. This library won't get rid of all of your CSS, the goal is get rid of 90% of it and the remaining 10% would live at the component level.
What makes this different than other libraries?
To be honest, not a whole lot. In fact most other CSS libraries
already have a lot of this functionality, and more. So why would
anyone use this? Because sometimes a limited set of options is more
powerful than an infinite one. Limited options can help focus a
discussion and allow quick decisions to be made, while also preventing
people from focusing on trivial details.
Let's use a real
life example. I was once talking with a designer about the placement
of some text. They wanted the text to have a margin of 34px. We didn't
use that margin size anywhere else in the application. That could have
triggered an in-depth conversation about why 34px was necessary.
Instead I was able to say "We don't have a margin of 34px, but we have
32px. Will that work?" The designer said sure, and we moved on. Those
2px didn't matter at the end of the day. But from a code perspective
it would have created another one off style.
You could say
that this is an opinionated CSS library. I've taken all of CSS and
said "you will probably only need this". Will it limit your creative
freedom, yeah probably. Will it help you quickly create UIs without
having to decide if a 23px padding or a 24px padding looks better?
100% yes.
Getting Started
How do you get started? That's simple, in your project just run
npm install css-utility-belt. From there you should be
able to just import the CSS file into your main CSS file and you are
done. No compilation step, no configuring. For example, in an
app.scss you would add
@import 'css-utility-belt';
Configuration
Oh you want to configure it? Well the only things that are
configurable are the colors. The colors are easy to change though.
They are defined using
CSS Custom Properties. The variable names are the colors. So if you want to change the
global blue color for example, you just need to set
:root { --blue: #2E64FE } and you are done. Due to how
CSS cascades, you just need to define these colors after you import
the utility belt and it should "just work". This also means that the
colors will not work on browsers that do not support CSS custom
properties.
Questions
This section is to answer questions about some divergences from common CSS library practices and implementation details
- Why do you use the actual color names instead of the context that they should be used in? (i.e. text-red v.s. text-error)
-
Context classes make a ton of sense until suddenly they don't. For
instance, let's say you are making a graph and one of the labels
needs to be red. You could use the
text-errorclass, but this isn't an error. So now you have code that incorrectly indicates that this is an error. The other reason is the ease for new developers to learn the classes. If you have just started on a new team. Will you know that to get orange text you need to use thetext-tertiaryclass or istext-orangemore obvious? - Why are the class names so verbose?
-
This is to improve readability and code reviews. While shortening
the various words would save a couple of keystrokes, it also makes
it slightly harder to read the code. Developers spend way more time
reading code than they do actually writing it, so optimizing for
ease of reading v.s. ease of writing seemed to make the most sense.
It also allows someone who has no concept of what the class names do
without having to look at the rendered page. I think an example is
the best way to demonstrate this. Take a look at this code snippet
I bet you have pretty good idea of what this code looks like when it is rendered, and you have never used this library before. Compare this to:<section class="background-blue padding-2 flex-column"> <div class="border-1 border-red rounded-corners text-red padding-4 margin-bottom-2"> Box 1 </div> <div class="border-1 border-green rounded-corners text-green padding-4"> Box 2 </div> </section>
You could probably guess what the second code snippet does, but it would be a guess. Having confidence that you know what the code does is important. Code that you think you understand, but actually don't is where bugs start to creep in.<section class="bg-blue p-2 fx-column"> <div class="b-1 b-red rounded-corners text-red p-4 mb-2"> Box 1 </div> <div class="b-1 b-green rounded-corners text-green p-4"> Box 2 </div> </section> - Why does every class use
!important? - This is to make sure that nothing else overrides the style. Since these classes typically translate to one or two CSS styles, overriding a class should never be necessary. If you don't want an element to have a specific style, remove the class instead. This also almost guarantees that the HTML describes exactly what will be rendered. (Technically inline styles could override the class styles but that would mean the styles are still present in the HTML)
Examples
Background Classes
background-blackbackground-bluebackground-graybackground-greenbackground-orangebackground-redbackground-white
Border Classes
Border styles
border-1border-top-1border-right-1border-bottom-1border-left-1rounded-corners
Border Colors
border-blackborder-blueborder-grayborder-greenborder-orangeborder-redborder-white
Display Classes
display-block- display: block !important;
display-inline-block- display: inline-block !important;
display-none- display: none !important;
Flex Classes
flex-columnflex-rowjustify-content-startjustify-content-centerjustify-content-endjustify-content-space-betweenalign-items-startalign-items-centeralign-items-end
Overflow Classes
overflow-autooverflow-hidden
Size Classes
height-100min-height-0-
width-100min-width-0- min-width: 0 !important;
Spacing Classes
margin-0-
margin-1-
margin-2-
margin-3-
margin-4-
margin-5-
margin-auto-
margin-top-0-
margin-top-1-
margin-top-2-
margin-top-3-
margin-top-4-
margin-top-5-
margin-top-auto-
margin-right-0-
margin-right-1-
margin-right-2-
margin-right-3-
margin-right-4-
margin-right-5-
margin-right-auto-
margin-bottom-0-
margin-bottom-1-
margin-bottom-2-
margin-bottom-3-
margin-bottom-4-
margin-bottom-5-
margin-bottom-auto-
margin-left-0-
margin-left-1-
margin-left-2-
margin-left-3-
margin-left-4-
margin-left-5-
margin-left-auto-
margin-x-0-
margin-x-1-
margin-x-2-
margin-x-3-
margin-x-4-
margin-x-5-
margin-x-auto-
margin-y-0-
margin-y-1-
margin-y-2-
margin-y-3-
margin-y-4-
margin-y-5-
margin-y-auto-
padding-0- Text
padding-1- Text
padding-2- Text
padding-3- Text
padding-4- Text
padding-5- Text
padding-top-0- Text
padding-top-1- Text
padding-top-2- Text
padding-top-3- Text
padding-top-4- Text
padding-top-5- Text
padding-right-0- Text
padding-right-1- Text
padding-right-2- Text
padding-right-3- Text
padding-right-4- Text
padding-right-5- Text
padding-bottom-0- Text
padding-bottom-1- Text
padding-bottom-2- Text
padding-bottom-3- Text
padding-bottom-4- Text
padding-bottom-5- Text
padding-left-0- Text
padding-left-1- Text
padding-left-2- Text
padding-left-3- Text
padding-left-4- Text
padding-left-5- Text
padding-x-0- Text
padding-x-1- Text
padding-x-2- Text
padding-x-3- Text
padding-x-4- Text
padding-x-5- Text
padding-y-0- Text
padding-y-1- Text
padding-y-2- Text
padding-y-3- Text
padding-y-4- Text
padding-y-5- Text
Text Classes
text-align-center-
Text
text-bold- Text
text-italic- Text
text-black- Text
text-blue- Text
text-gray- Text
text-green- Text
text-orange- Text
text-red- Text
text-white- Text