Tailwind Tips

Quick Notes

TailwindCSS is a utility-first CSS framework that helps to minimize your effort building out responsive designs while maximizing your flexibility make adjustments on the fly.

The framework provides several in-built configurations for almost every CSS rule for modern browsers and can be easily modified in just one configuration file.

Benefits

  • One configuration file for all defined CSS rules

This one file can be shared and collaborated on between developers and UI & UX designers in order to create one holistic design system for the project as opposed to multiple stylesheets scattered around a project.

Thus, discussions on how to move forward with the project’s theme can be easily understood between members of differing coding expertise or familiarity with the setup of an existing project.

  • Control over Styling

TailwindCSS does not come with a default theme that you have to use and adapt your project to in order to use it to its full potential.

TailwindCSS is already at its full potential and can go even further beyond with the developer and designers input on how they want to then theme their project.

Thus, TailwindCSS is highly un-opinionated on how you style your project and hence, your project can really stand out from other sites that probably use the same framework.

  • Several CSS rules are provided to developers without having to predefine them

Colors, spacing, typographies, transitions and animations and more all come in-built with the base configuration from TailwindCSS.

This means developers do not have to spend time creating multiple stylesheets for global classes to be used in multiple HTML templates on their project.

  • Responsive Design

Out of the box, TailwindCSS comes with modifiers on all their classes to allow for designing your webpages with responsive design in mind from the start.

Tailwind Tips

Let’s get into some tips that could help you out if you’re considering using TailwindCSS.

Keep in mind, their default configuration will be in use on installation.

Mobile First with Responsive Design

TailwindCSS classes can be applied conditionally with a breakpoint defined from the screens property in the configuration in order to achieve Responsive Design.

This template below demonstrates different background colors being applied at different breakpoints through resizing the window viewport.

<div class="text-white bg-blue sm:bg-green xl:bg-orange">
  My background color changes at different viewports
</div>

Keep in mind:

  • Tailwind classes without the breakpoint prepended to them will be initially applied
  • Tailwind classes with breakpoints prepended to them will override those of the same class without breakpoints at that viewport and higher
  • Tailwind classes with breakpoints higher than those of the same class will override the stylings of the lower breakpoints

Also, you can override or extend the screens property in your tailwind configuration as needed.

Using keyword functions

TailwindCSS provides some functions and directives that can be used in the stylesheets section of your project. This way, you can still separate the many potential Tailwind classes from all being in your HTML templates and instead being in your stylesheets. I’ll mention two functions which have been vastly useful:

  • @apply

This function can be applied under a class to apply several Tailwind classes for that class

.applied-class {
  @apply tw-text-black tw-bg-orange;
}

Thus, you could have an element that uses .applied-class and apply several many tailwind classes now which all reside in your stylesheets.

  • @screen

This function can be applied under a class to apply Tailwind classes for that class that would only be applied for that breakpoint or higher

.responsive-class {
  color: theme("colors.white.DEFAULT");
  background: theme("colors.blue.DEFAULT");

  @screen sm {
    background: theme("colors.green.DEFAULT");
  }

  @screen xl {
    background: theme("colors.orange.DEFAULT");
  }
}

Creating your own aggregate classes

Using the @apply function from TailwindCSS, we can create a stylesheet that aggregates several Tailwind classes that we can then use globally around the project.

For example, we could aggregate classes for flexbox related properties in order to have one global class for these properties

.flexbox-col-align-center-justify-center {
  @apply flex flex-col items-center justify-center;
}

.flexbox-row-align-center-justify-between-wrap {
  @apply flex flex-row items-center justify-between flex-wrap;
}

In a few short lines, several properties are being applied to a single class that we can then use all around the project for flexbox related stylings.

Using a prefix

TailwindCSS allows for their provided classes to be prefixed with a string within your project.

Ideally, this prefix string should be short and easily distinguishable to eliminate added effort while building out webpages.

This practice could be helpful for your project to prevent potential overlapping of class names from TailwindCSS and other class implementations from your project or other CSS frameworks.

Also, prefixing Tailwind classes could be helpful to properly apply them to production builds where a minifying or purging system for excessive CSS classes may be in use.

Using a preset

Although TailwindCSS uses their default configuration on installation which can be overridden or extended through the project’s own configuration, this practice can be even further extended.

Presets is a property on the project’s configuration which takes in a valid Tailwind configuration. This allows your project to then utilize the provided configuration as the basis for your project’s configuration.

This way, you could have a default base configuration somewhere in another project or repository and import that configuration into a new project and place this configuration in this presets property.

Thus, you would not have to repeat your configuration properties again on new projects and keep a shared configuration abstracted away from your project.

Referencing in JavaScript

TailwindCSS provides a function called resolveConfig which takes in a given Tailwind configuration to return an object of that Tailwind configuration theme in JavaScript files.

This means, your project could have functionality which conditionally triggers based on a specific Tailwind class being applied.

import resolveConfig from 'tailwindcss/resolveConfig'
import tailwindConfig from './tailwind.config.js'

const fullConfig = resolveConfig(tailwindConfig)

console.log('Small screen value is ', fullConfig.theme.screens.sm);

In the example above, we are grabbing the Tailwind configuration and printing out the value for the configuration definition of sm in the screens section of the Tailwind configuration.

Thus, we could extend this further to write functions that could grab the current breakpoint of the screen based on a provided key in the screens object.

function getCurrentBreakpointByKey(key) {
  const breakpoint = fullConfig.theme.screens[key];
  if (breakpoint) {
    return {
      key,
      valueString: breakpoint,
      value: parseInt([breakpoint.split('px')], 10),
    };
  }
  return null;
},

We can go even further beyond by checking the window width at the time of function call to know what the current breakpoint is.

function getCurrentBreakpoint() {
  let currentBreakpoint;
  const breakpointsArray = Object.entries(fullConfig.theme.screens);

  breakpointsArray.sort((a, b) => {
    const valA = [a[1].split('px')][0][0];
    const valB = [b[1].split('px')][0][0];
    const valAInt = parseInt(valA, 10);
    const valBInt = parseInt(valB, 10);
    if (valAInt > valBInt) {
      return 1;
    }
    if (valAInt < valBInt) {
      return -1;
    }
    return 0;
  });

  for (let i = 0; i < breakpointsArray.length; i += 1) {
    const breakpointValue = parseInt([breakpointsArray[i][1].split('px')], 10);
    if (window.innerWidth >= breakpointValue) {
      currentBreakpoint = breakpointsArray[i];
    } else {
      if (!currentBreakpoint) {
        [currentBreakpoint] = breakpointsArray;
      }
      break;
    }
  }
  
  return {
    key: currentBreakpoint[0],
    valueString: currentBreakpoint[1],
    value: parseInt([currentBreakpoint[1].split('px')], 10),
  };
},

Thus, we can write these helper functions to a class or a plugin to conditionally change and adapt script functionality based on the current viewport the window is in on the fly.