Building TailwindCSS with Sass
Tags: tailwindcss, css, webdev, programming
Published: 2021-12-01 13:27:08

---
canonical_url: https://dpnkr.in/blog/building-tailwind
description: Minimal way to build your own TailwindCSS with Sass
---

According to the 2020 state of CSS report, Tailwind CSS stood out as one of the tools with the highest satisfaction ratio (86%). Tailwind has become a go-to solution to build web applications. And the reason is justified you can build and ship websites faster and still have 100% control over the styling unlike other CSS frameworks (Bulma, bootstrap, etc).

I was always curious about how tailwind generates [3645.2kB](https://tailwindcss.com/docs/optimizing-for-production) of CSS which is full of utility classes from "p-0 , mx-1 ... pt-40" to the color variants and all.

This blog covers how you can build TailwindCSS utility classes in a very minimal way and doesn't cover the plugin/config ecosystem it provides.

We will be building it with the help of Sass (SCSS) or syntactically awesome stylesheets. If you don't know what this is you can watch this [video](https://youtu.be/akDIJa0AP5c) to get an overview. Using Sass will help us to write CSS code more efficiently and programmatic.

A short demo:

![Tailwind Sass demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x7221sufibktcpknvf8.gif)

Browser doesn't understand what Sass actually is, so we need to compile it to CSS. We will use a bunch of tools to accomplish that. Now let's start by setting up our project.

```bash
yarn init -y
# or
npm init -y
```

This would create a minimal `package.json` file for our project. Now we will add some `devDependencies`

```bash
yarn add -D autoprefixer node-sass postcss postcss-cli
# or
npm install autoprefixer node-sass postcss postcss-cli --save-dev
```

A brief explanation of what these actually do:

- `node-sass` helps in compiling `.scss / .sass` files to `css`
- `postcss` parser which tokenizes CSS code to create an abstract syntax tree, we will be using it's plugins
- `autoprefixer` plugin of postcss, adds vendor prefixes to CSS rule

Now, will add some scripts in `package.json`, feel free to modify the input and output of your build.

```json
"scripts": {
    "build": "rm -rf build && yarn build-sass",
    "build-sass": "node-sass --output-style expanded src/index.scss ./build/index.css  && yarn  build-autoprefix",
    "build-autoprefix": "postcss --use autoprefixer --map --output ./build/index.css ./build/index.css"
}
```

- `build` clears build directory and runs `build-sass`
- `build-sass` compiles scss and build css in a new directory then runs `build-autoprefix`
- `build-autoprefix` adds vendor prefixes and generates source maps

Now let's create our input file `src/index.scss`, if you write some valid `scss` code and run `yarn build` you should see the compiled css created.

Now that our project is setup we will look into creating [text-color](https://tailwindcss.com/docs/text-color) & [background-color](https://tailwindcss.com/docs/background-color) variants of tailwind. The base idea is to loop over all colors you have and generate utility classes (text-gray-100, bg-gray-100 ... etc).

Let's start by first creating a new directory `utils` and a file inside it `_colors.scss`. Adding a leading underscore in scss files is called [partials](https://sass-lang.com/documentation/at-rules/import#partials) this helps us in modularizing the code and importing it into other files.

To declare our colors we will use [Maps](https://sass-lang.com/documentation/values/maps) which is provided by SASS to declare key-value pairs.

```scss
// utils/_colors.scss
$colors: (
  'gray-100' #f7fafc,
  'gray-200' #edf2f7,
  'gray-300' #e2e8f0,
  'gray-400' #cbd5e0,
  'gray-500' #a0aec0,
  'gray-600' #718096,
  'gray-700' #4a5568,
  'gray-800' #2d3748,
  'gray-900' #1a202c
);
```

Now to loop over these we will use `@each` rule this helps us to evaluate code for each element of a lists/maps to generate repetitive styles which is exactly what want to do.

```scss
// utils/_colors.scss
@each $name, $hex in $colors {
  .text-#{$name} {
    color: $hex;
  }
  .bg-#{$name} {
    background-color: $hex;
  }
}
```

Now let's import this partial in our input file

```scss
// src/index.scss
@import '../utils/colors';
```

On running `yarn build` you should be able to see all your utility classes being generated.

```css
/* build/index.css */
.text-gray-100 {
  color: #f7fafc;
}

.bg-gray-100 {
  background-color: #f7fafc;
}

.text-gray-200 {
  color: #edf2f7;
}

.bg-gray-200 {
  background-color: #edf2f7;
}

... and so on
```

Moving on to the next part we will look into creating [margin](https://tailwindcss.com/docs/margin) , [padding](https://tailwindcss.com/docs/padding) utility classes. We will be using [lists](https://sass-lang.com/documentation/values/lists) data type in this case.

Let's start by creating a new partial `_spacing.scss` and we will create 2 lists, 1st one would be `$spaces` which will be used to calculate the spacing (For eg: m-4 -> margin: '1rem') and the 2nd one being `$sides` which is basically the direction of spacing to create margin-(top, right, left, bottom) variants.

```scss
// utils/_spacing.scss
$spaces: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
  20;

$sides: 'top', 'right', 'bottom', 'left';
```

Now that we have our values all we have to do is now loop over them with the help of the `@each` rule. To generate margin/padding-top,left,bottom,right utility classes we will nest another `@each` rule to map over `$sides` lists. We will also use [`str-slice`](https://sass-lang.com/documentation/modules/string#slice) which returns the slice of string.

```scss
// utils/_spacing.scss
@each $space in $spaces {
  .m-#{$space} {
    margin: #{$space/4}rem;
  }

  .mx-#{$space} {
    margin-left: #{$space/4}rem;
    margin-right: #{$space/4}rem;
  }

  .my-#{$space} {
    margin-top: #{$space/4}rem;
    margin-bottom: #{$space/4}rem;
  }

  .px-#{$space} {
    padding-left: #{$space/4}rem;
    padding-right: #{$space/4}rem;
  }

  .py-#{$space} {
    padding-top: #{$space/4}rem;
    padding-bottom: #{$space/4}rem;
  }

  .p-#{$space} {
    padding: #{$space/4}rem;
  }

  @each $side in $sides {
    .m#{str-slice($side, 0, 1)}-#{$space} {
      margin-#{$side}: #{$space/4}rem;
    }

    .p#{str-slice($side, 0, 1)}-#{$space} {
      padding-#{$side}: #{$space/4}rem;
    }
  }
}
```

Make sure to import the partials in our input file.

```scss
// src/index.scss
@import '../utils/colors' , '../utils/spacing';
```

Now if you build it you should see the spacing variants generated.

```css
/* build/index.css */
.m-0 {
  margin: 0rem;
}

.p-0 {
  padding: 0rem;
}

.mx-0 {
  margin-left: 0rem;
  margin-right: 0rem;
}

.my-0 {
  margin-top: 0rem;
  margin-bottom: 0rem;
}

... and so on
```

Using the same approach you can create breakpoints, typography, literally any kind of utility classes you want! I hope you found this article informative I thought this was cool enough implementation to share with you folks.

You can refer the code in this [Github repo](https://github.com/Deep-Codes/tailwind-sass).

Let me know what you think about it, feel free to connect with me on [Twitter](https://twitter.com/DeepankarBhade) if you have any questions. Cheers!