Everyone uses CSS frameworks today

Anytime the “what’s your favorite CSS framework” question pops up, you read the same comments: a bunch of developers expressing their love for framework X or Y, and others stating they don’t use frameworks.

Some of the reasons why some developers say they don’t use CSS frameworks:

  1. Frameworks are opinionated.
  2. Why would I need a framework when I can write clean CSS myself?
  3. Frameworks are bloated with stuff I don’t need.

But what is a framework, exactly?

A framework is a supporting structure around which something can be built.

A framework doesn’t need to be opinionated. Its CSS can be as clean as yours (or it could literally be yours). It can be super slim, to the point where it includes only a bunch of reusable rules.

If you do one of the following, you’re using a framework even if you say you don’t:

  1. You have a bunch of utility classes that you copy and paste from project to project.
  2. You have a set of basic rules (e.g., for typography and spacing) that you copy into new projects, and then tweak to accommodate different needs.
  3. You have a boilerplate for the style of buttons and forms that is easy to customize.
  4. In general, in any case where you reuse something across different projects.

There’s only one case when you can say you don’t use a CSS framework, and it’s the truth: if you start a project with your CSS files completely blank.

But seriously, why would you do that? 🤔

I know I’m being pedantic. “When I say I don’t use a CSS framework, I’m referring to Bootstrap, not 20 lines of code!”, I hear you scream. However, I think there’s a misleading message that is delivered to young developers: “Frameworks are bad. If you were a good developer, you’d write clean CSS from scratch”. And yet millions of developers download Bootstrap every month. Are they all making a mistake? Not at all.

You could use a super slim framework or create one yourself, and it would be fine. You could use a heavier framework or create one yourself, and it would be fine.

Starting from (literally) scratch every time does not prove you’re a good developer.

Let me walk you through the main problems a framework helps you solve and why we all need one.

Global styles and abstraction

When Claudia and I started working on the CodyHouse Components project (a library of HTML, CSS, JS web components), we soon realized how important it is to have global styles and abstract rules.

A global style is a rule that, when modified, affects all the components it crosses (e.g., a buttons.scss file where you store the style of your buttons).

A CSS abstraction is a rule that gives the same result regardless of the element it is applied to (e.g., utility classes).

Global styles make your project customizable. For example, if you create a reusable typography.scss file where you define the type scale, you can 1) edit the type scale and affect all the components of your current project or 2) set a custom type scale for your next project.

:root {  
  // type scale
  --text-scale-ratio: 1.2;
  --text-xs: calc((1em / var(--text-scale-ratio)) / var(--text-scale-ratio));
  --text-sm: calc(var(--text-xs) * var(--text-scale-ratio));
  --text-md: calc(var(--text-sm) * var(--text-scale-ratio) * var(--text-scale-ratio));
  --text-lg: calc(var(--text-md) * var(--text-scale-ratio));
  --text-xl: calc(var(--text-lg) * var(--text-scale-ratio));
  --text-xxl: calc(var(--text-xl) * var(--text-scale-ratio));
  --text-xxxl: calc(var(--text-xxl) * var(--text-scale-ratio));
}

Type scale as set in the CodyHouse Framework

CSS abstractions make it easier to create component variations without the headaches caused by naming things. For example, imagine you create a new component. If you want to create two class modifiers where the text is aligned in the center or right, you end up doing the following:

.compontentOne--text-center {
  text-align: center;
}

.compontentOne--text-right {
  text-align: right;
}

Then you create another component and have the same ‘issue’. Once again, you create two new class modifiers:

.compontentTwo--text-center {
  text-align: center;
}

.compontentTwo--text-right {
  text-align: right;
}

An alternative approach would be creating 3 utility classes (abstractions):

.text-left {
  text-align: left;
}

.text-center {
  text-align: center;
}

.text-right {
  text-align: right;
}

Now you can have infinite components and apply the same utility classes to align text.

I’m not suggesting you should create utility classes for everything (even though some frameworks do so, and developers love them). Find your own balance, create the abstractions you need.

Do not reinvent the wheel

If you come up with a pattern that works, why wouldn’t you extend it to new projects (and include it in your framework)? For example, you start working on accessibility and soon realize how handy it is the .sr-only utility class:

.sr-only { // content made available only to screen readers
  position: absolute;
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  width: 1px;
  height: 1px;
  overflow: hidden;
  padding: 0;
  border: 0;
  white-space: nowrap;
}

Is there any reason why you shouldn’t use it in all your projects? Nope.

Getting back to your old projects doesn’t need to be THAT painful

Opening up an old CSS project is a pain; we all know that. However, it doesn’t need to be THAT painful. Using the same framework across multiple projects means working with patterns you’re already familiar with. If you use the same mixins, global settings, grid rules, and utility classes, you’ll need less time figuring out how to do stuff.

For example, let’s imagine you have created a scale of spacing values:

:root {
  --space-unit:  1em;
  --space-xxxxs: calc(0.125 * var(--space-unit)); 
  --space-xxxs:  calc(0.25 * var(--space-unit));
  --space-xxs:   calc(0.375 * var(--space-unit));
  --space-xs:    calc(0.5 * var(--space-unit));
  --space-sm:    calc(0.75 * var(--space-unit));
  --space-md:    calc(1.25 * var(--space-unit));
  --space-lg:    calc(2 * var(--space-unit));
  --space-xl:    calc(3.25 * var(--space-unit));
  --space-xxl:   calc(5.25 * var(--space-unit));
  --space-xxxl:  calc(8.5 * var(--space-unit));
  --space-xxxxl: calc(13.75 * var(--space-unit));
  --component-padding: var(--space-md);
}

You know you can go ahead and modify a component using one of the scale values:

.component {
  padding: var(--space-md);
}

The spacing values may vary in different projects, but the way you apply them is the same. You go ahead and set padding: var(--space-md). If it’s too small/big, you can pick another value (or edit the scale).

The alternative approach would be:

  1. First, figure out how spacing rules were set when the project was initiated.
  2. Then, apply the spacing rules.

That extra step makes all the difference in the world. It’s where the frustration lies: figuring out things when you, or someone else you work with, already went through that process before.

Frameworks evolve and get updated (e.g., when you learn new patterns and replace old ones). There will be cases when you still need to remember how/why some rules were set in the first place. It sucks, but working with reusable patterns (framework) means reducing the number of times this happens.

Learn by building reusable patterns

One more advantage of creating your own framework is learning to identify reusable patterns. You find that piece of your CSS puzzle that could work across multiple projects, and decide to store it in a safe place (your framework).

Or, you can learn from frameworks created by other developers. Question why that rule was abstracted. If you can’t come up with an answer, google it; or ask the author.

The process of questioning what you do and discovering the mechanics behind a decision is what makes you learn. Not the assumption that you have to come up with all the solutions yourself.

Conclusion

A CSS framework is a tool. It’s not good or bad, and it doesn’t define you as a developer. When you find a pattern that works, save it. If you find a framework that ticks all your boxes, use it. As long as you learn in the process, nothing bad comes from using it. Quite the opposite.