Bluecloud

Bluecloud

LWC and Tailwind CSS

Frontend

In this guide, I will demonstrate how to effectively combine Lightning Web Components (LWC) with Tailwind CSS. LWC is a framework used by Salesforce Developers to create customized pages and functions on the Salesforce platform. Tailwind CSS, on the other hand, is a utility-first CSS framework that facilitates the rapid development of modern websites without the need to depart from your HTML. Note: While implementing this functionality, there are not just one but two distinct approaches available. The first option is simpler but lacks flexibility, while the second option provides greater customization opportunities, although it is more intricate and time-consuming.

Easy way

You can just upload tailwind.min.css from unpkg.org to your static resource.

import resourceName from '@salesforce/resourceUrl/tailwind';
import { loadStyle, loadScript } from 'lightning/platformResourceLoader';

loadStyle(this, resourceName + '/tailwind.min.css')

Using this approach:

  • You can’t customize Tailwind’s default theme
  • You can’t use any directives like @apply, @variants, etc.
  • You can’t enable additional variants like group-focus
  • You can’t install third-party plugins
  • You can’t tree-shake unused styles

Right way

It will require some skill and knowledge in Salesforce and Node.Js

Before Installation

Make sure you have folowing:

  1. Node.Js + npm
  2. Empty Salesforce project

Installation

  1. Go to your salesforce project folder root and run npm init
  2. Install tailwindcss and it dependencies npm install -D tailwindcss postcss autoprefixer postcss-cli cssnano
  3. Make sure that tailwind.config.js and postcss.config.js were created, if no, create them manually
touch tailwind.config.js && touch postcss.config.js

postcss.config.js:

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
    require('cssnano')({
      preset: 'default'
    })
  ]
};

tailwind.config.js:

module.exports = {
  purge: {
    mode: 'layers',
    layers: ['base', 'components', 'utilities'],
    content: [
      '**/aura/**/*.cmp',
      '**/aura/**/*.js',
      '**/lwc/**/*.html',
      '**/lwc/**/*.js'
    ]
  },
  theme: {
    fontFamily: {
      primary: ['var(--lwc-fontFamily)', 'sans-serif'],
      header: ['var(--lwc-fontFamilyHeader)', 'sans-serif']
    },
    extend: {
      colors: {
        'lwc-text': 'var(--lwc-colorTextDefault)',
        'lwc-nav-text': 'var(--lwc-brandNavigationColorText)',
        'lwc-detail': 'var(--lwc-colorTextWeak)',
        'lwc-brand': 'var(--lwc-colorBrand)',
        'lwc-link': 'var(--lwc-colorTextLink)',
        'lwc-overlay': 'var(--lwc-colorTextInverse)',
        'lwc-border': 'var(--lwc-colorBorder)',
        'lwc-bg': 'var(--lwc-colorBackground)',
        'lwc-nav-bg': 'var(--lwc-brandNavigationBackgroundColor)'
      }
    }
  },
  variants: {},
  plugins: []
};
  1. Create the css folder in your root directory
  2. Create an empty css tailwind.dev.css file inside
  3. Now you need to override all the elements you want to use using the @apply. For the details please see the tailwind documentation site. As example we can use this code.

tailwind.dev.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

/* Typography */

body * {
  @apply font-primary font-normal
}

body h1, body h2, body h3, body h4, body h5, body h6 {
  @apply font-header font-bold text-lwc-text
}

body h1 {
  @apply font-bold text-xl mt-8 mb-4
}

body h2 {
  @apply font-bold text-lg mt-4 mb-2
}

body h3 {
  @apply font-bold text-base mt-2 mb-0
}

body p {
  @apply font-primary text-base text-lwc-text mt-2 mb-0
}

/* Links */

body a {
  @apply text-lwc-link no-underline
}

body a:active, body a:hover, body a:focus {
  @apply underline
}

/* Standard Content Layouts */

.comm-layout-column.slds-col_padded,
.comm-layout-column.slds-col--padded {
  @apply p-4
}

/* Global Navigation Bar */

header .forceCommunityGlobalNavigation {
  @apply bg-lwc-nav-bg
}

header .forceCommunityGlobalNavigation .slds-list_vertical {
  @apply bg-lwc-nav-bg
}

header .forceCommunityGlobalNavigation .slds-p-vertical--xx-small.slds-p-horizontal--small.slds-grid {
  @apply px-0
}

header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item a,
header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item button {
  @apply font-primary font-normal text-base text-lwc-nav-text px-4 py-4
}

@screen md {
  header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item a,
  header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item button {
    @apply py-2
  }
}

header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item a:hover,
header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item a:focus,
header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item button:hover,
header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item button:focus {
  @apply bg-lwc-nav-bg underline
}

header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item button:focus {
  @apply shadow-none
}

header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item a.slds-is-active:not([data-type="home"]),
header .forceCommunityGlobalNavigation .comm-navigation__list .slds-list__item .comm-navigation__item button.slds-is-active:not([data-type="home"]) {
  @apply bg-lwc-nav-bg
}

/* Global Search Input */

header .forceCommunityGlobalSearchInput .forceSearchInputDesktop .contentWrapper {
  @apply border-none rounded-none
}

header .forceCommunityGlobalSearchInput .forceSearchInputDesktop .contentWrapper.focused {
  @apply border-none shadow-none
}

header .forceCommunityGlobalSearchInput .forceSearchInputDesktop .slds-input__icon.inputIcon {
  @apply text-lwc-brand
}

header .forceCommunityGlobalSearchInput .forceSearchInputDesktop .uiInput .uiInputTextForAutocomplete {
  @apply text-base rounded-none transition-none;
  padding-top: 2px;
  padding-bottom: 2px;
}

header .forceCommunityGlobalSearchInput .forceSearchInputDesktop .uiInput .uiInputTextForAutocomplete:focus {
  @apply border-0 border-b-2 border-solid border-lwc-brand pb-0
}

/* User Profile Menu */

header .selfServiceUserProfileMenu .login a .linkLabel {
  @apply font-primary font-normal text-base text-right text-lwc-nav-text
}

header .selfServiceUserProfileMenu .login a:hover .linkLabel,
header .selfServiceUserProfileMenu .login a:focus .linkLabel {
  @apply underline
}

header .selfServiceUserProfileMenu .selfServiceProfileMenuTrigger a.trigger-link {
  @apply flex justify-end items-center font-primary font-normal text-base text-lwc-nav-text p-0
}

header .selfServiceUserProfileMenu .selfServiceProfileMenuTrigger a.trigger-link:focus {
  @apply border-none shadow-none
}

header .selfServiceUserProfileMenu .selfServiceProfileMenuTrigger .profileIcon {
  @apply flex-shrink-0
}

header .selfServiceUserProfileMenu .selfServiceProfileMenuTrigger .profileName {
  @apply max-w-none font-normal text-base pl-2 pr-1
}

header .selfServiceUserProfileMenu .menuList .uiMenuItem {
  @apply text-base
}

Your file structure should look like this aftetr installation:

.
├── css
│   └── tailwind.dev.css
├── force-app 
│   └── ...
├── package-lock.json 
├── package.json 
├── postcss.config.js #postcss configuration
├── sfdx-project.json 
└── tailwind.config.js #tailwind configuration

That is it with installation, now we can add a build script to the package.json

Build

We need to add a build script to the package.json. postcss will process tailwind.dev.css and put minified .css file to the output folder.

  1. Add this code to the package.json
  "scripts": {
    "build": "postcss css/tailwind.dev.css -o css/tailwind.prod.css"
  },
  1. Run this command in terminal
npm run build

The file should be generated and placed to the /css/tailwind.prod.css

Usage

Locate css/tailwind.prod.css and load it into the Static Resources. From this point, you have options for how to use the CSS file

1. Using TailwindCSS in Theme Layout

Load the global CSS file containing the TailwindCSS utility classes and other custom style definitions in the theme layout component. This makes the classes available to the layout itself and all the other components on the page. This should work for both Aura and LWR (Lightning Web Runtime) - just use the appropriate Theme Layout.

2. Using TailwindCSS in Lightning Web Components

Web components included in a page using the TailwindCSS theme layout can automatically access the style definitions provided by the global CSS file. You can also manually import the CSS file from the static resource and reuse it in other components.