Skip to main content

Command Palette

Search for a command to run...

TailwindCSS meets Express: A guide to effortles styling with pure JavaScript and without extra frameworks

Streamline your Node.js project with TailwindCSS for a powerful and lightweight styling solution—no extra frameworks required

Updated
8 min read
TailwindCSS meets Express: A guide to effortles styling with pure JavaScript and without extra frameworks
P

Writer and creator

I’m a big fan of keeping things simple. When it comes to building web applications, I tend to stick with technologies I know and trust. For years, I’ve relied on the combination of the Express JavaScript framework and Bootstrap for styling. It’s a reliable duo that gets the job done.

However, I’ve faced one recurring challenge: Bootstrap themes. While the framework is great, creating visually appealing themes from scratch isn’t my strong suit, and finding the perfect pre-made theme can be time-consuming.

That’s when I decided to explore alternatives. After some research, I landed on TailwindCSS - and I was immediately impressed. The websites built with TailwindCSS looked stunning, so I decided to give it a try.

A different philosophy

The first thing I noticed is that TailwindCSS works differently from Bootstrap. Let me explain:

  • Bootstrap is primarily a layout system. While it offers predefined components, you still need to write your own CSS to customize things like colors, typography, or specific UI elements.

  • TailwindCSS, on the other hand, uses "utility-first" CSS. It provides small, reusable utility classes that let you style elements directly in your HTML.

For example, with Bootstrap, you might start with a predefined button component and then add custom styles for size, colors, or corners. With TailwindCSS, you can define everything directly in the HTML by chaining utility classes. Need rounded corners, larger text, and a custom color? You simply add the relevant classes, and you’re good to go.

The power of TailwindCSS

Because TailwindCSS relies on utility classes, your CSS output can grow quite large. To solve this, Tailwind introduced a just-in-time (JIT) compiler. This tool generates only the CSS your project actually uses, based on your code, templates, and views.

That’s where things get interesting. Unlike Bootstrap, where you simply include the full CSS file in your project, Tailwind requires a build process to compile and optimize your CSS. This makes Tailwind a popular choice for modern frameworks like Vue, React, and Next.js.

But what if you’re not using those frameworks?

TailwindCSS with Express and pure JavaScript

I still prefer to keep things simple and stick with Express. So, I dug into the possibilities of using TailwindCSS without any additional UI frameworks. To my delight, it’s not only possible but also straightforward!

There are a few articles on this topic, but none I found provided detailed steps or worked correctly on the first try. In this guide, I’ll walk you through how to set up TailwindCSS in your Node.js project using pure JavaScript and Express. No Vue, no Next.js - just simple, effective styling in your familiar setup.

Ready to modernize your styling game while keeping your workflow simple? Let’s get started!

Step 1: Setting up your project

  1. Create a Node.js Project
    Start by creating a new Node.js project. Navigate to your project directory and run:

     npm init
    

    For the entry point, I typically name the file server.js.

  2. Install dependencies
    Next, install the necessary packages:

Install them with the following command:

    npm install express ejs tailwindcss @tailwindcss/postcss postcss postcss-cli autoprefixer
  1. Set up the project structure
    Create the following files and directories:

    • server.js - Your main server file.

    • assets/ - Directory for static files like styles and images.

    • assets/css/ - Subdirectory for CSS input and output files.

    • views/pages/ - Directory for EJS templates.

Your project structure should now look like this:

  1. Write the Express server code
    Add the basic Express configuration to server.js:

     const express = require('express');  
     const path = require('path');  
    
     const app = express();  
     const port = process.env.PORT || 3000;  
    
     // Set up EJS  
     app.set('view engine', 'ejs');  
     app.set('views', path.join(__dirname, 'views'));  
    
     // Serve static files from the 'assets' base directory
     app.use(express.static(path.join(__dirname, 'assets')));  
    
     // Define the root endpoint  
     app.get('/', (req, res) => {  
         res.render('pages/index', { title: 'TailwindCSS with Express!' });  
     });  
    
     // Start the server  
     app.listen(port, () => {  
         console.log(`Server is running at http://localhost:${port}`);  
     });
    
  2. Add the initial EJS template
    Create an index.ejs file in the views/pages/ directory and add a basic HTML5 structure:

     <!DOCTYPE html>  
     <html lang="en">  
     <head>  
         <meta charset="UTF-8">  
         <meta name="viewport" content="width=device-width, initial-scale=1.0">  
         <title>TailwindCSS with Express!</title>  
     </head>  
     <body>  
         <!-- Your content will go here -->  
     </body>  
     </html>
    

    At this stage, starting the server with node server.js will display an empty HTML page.

Step 2: Configuring TailwindCSS

Now, let’s set up and configure TailwindCSS in your project.

  1. Create required files
    Add the following files to your project:

    • tailwind.config.js - TailwindCSS configuration file.

    • postcss.config.mjs - PostCSS configuration file.

    • assets/css/tailwind.css - CSS file to import TailwindCSS into your project.

  2. Set up tailwind.config.js
    Add this content to the tailwind.config.js file - import Tailwindcss configuration and specify location of the files containing CSS:

     /** @type {import('tailwindcss').Config} */  
     module.exports = {  
         content: ['./views/pages/*.ejs'],  
         theme: {  
             extend: {},  
         },  
         plugins: [  
             {  
                 tailwindcss: {},  
                 autoprefixer: {},  
             },  
         ],  
     };
    

    Tip: The content property specifies where TailwindCSS should look for classes. Update the path to match the location of your EJS templates. Use glob patterns to include multiple directories or files if needed.

  3. Set up postcss.config.mjs
    Add this content to the postcss.config.mjs file:

     export default {  
         plugins: {  
             "@tailwindcss/postcss": {},  
         },  
     };
    

    Note: Since the project isn’t configured to use ES modules by default, the file must have a .mjs extension. If you enable "type": "module" in your package.json, you can rename it to .js.

  4. Set up tailwind.css
    In the assets/css/tailwind.css file, import TailwindCSS with this simple line:

     @import "tailwindcss";
    
  5. Add a build script
    Configure a script in package.json to generate the CSS file:

     "scripts": {  
         "tailwind:css": "postcss assets/css/tailwind.css -o assets/css/style.css"  
     }
    

    This script compiles TailwindCSS classes used in your EJS templates into a single style.css file located in assets/css/.

  6. Generate the CSS file
    Run the following command to build your CSS file:

     npm run tailwind:css
    

    This will create the style.css file in the assets/css/ directory, which contains all the necessary CSS for your project.

    By now, your project structure should resemble the following layout:

Step 3: Using TailwindCSS in EJS templates

To start using TailwindCSS in your EJS templates, follow these steps:

  1. Include the CSS file
    Update your index.ejs file to include the compiled style.css file. Add this line to the <head> section:

     <link href="./css/style.css" rel="stylesheet">
    

    Note: You don’t need to include assets in the path because it’s already set as the base directory for static files.

  2. Add TailwindCSS classes
    Let’s style a simple div using TailwindCSS classes. Add the following block to your index.ejs file:

     <div class="text-fuchsia-600 text-center py-10 text-2xl">  
         Hello, TailwindCSS!  
     </div>
    

    This will make the text fuchsia, center it, add padding to the top, and increase the font size.

  3. Rebuild and restart
    To see the changes, you’ll need to:

    • Rebuild the CSS file:

        npm run tailwind:css
      
    • Restart the server:

        node server.js
      

After restarting, open the app in your browser to see the styled text.

  1. Streamline the development workflow
    For a more convenient workflow, add scripts to your package.json to combine tasks. Update the scripts section with the following:

     "scripts": {  
         "start": "node server.js",  
         "tailwind:css": "postcss assets/css/tailwind.css -o assets/css/style.css",  
         "serve": "npm run tailwind:css && npm run start"  
     }
    

    Now, running npm run serve will build the CSS and start the server in one step.

Optional: Enable auto-restart with nodemon and live CSS updates

To further streamline development, you can set up two tools:

  • Nodemon to automatically restart the server when changes are made.

  • A PostCSS watch option to recompile CSS whenever files are updated.

Step 1: Install nodemon

Install Nodemon as a development dependency:

npm install --save-dev nodemon

Step 2: Update scripts in package.json

Add the following scripts to your package.json file:

"scripts": {  
    "start": "node server.js",  
    "tailwind:css": "postcss assets/css/tailwind.css -o assets/css/style.css",  
    "serve": "npm run tailwind:css && npm run start",  
    "tailwind:css-cont": "postcss assets/css/tailwind.css -o assets/css/style.css -w",  
    "serve-cont": "nodemon server.js"  
}

Here’s what these scripts do:

  • tailwind:css-cont: Runs PostCSS in watch mode (-w), which automatically recompiles the CSS whenever files change.

  • serve-cont: Uses Nodemon to restart the server automatically whenever server-side code changes.

Step 3: Run scripts in parallel

Start both scripts to enable live updates:

  1. Run the CSS watch script:

     npm run tailwind:css-cont
    
  2. Run the server watch script:

     npm run serve-cont
    

How it works

  • Any changes to your EJS templates or other files using TailwindCSS classes will trigger the CSS file to rebuild automatically.

  • Updates to the server code will restart the server without requiring manual intervention.

With this setup, your development cycle becomes much faster and more convenient. Changes to your project will be visible immediately in the browser.

Conclusion

Congratulations! You’ve successfully set up TailwindCSS in your Node.js project using Express and pure JavaScript. You can now leverage the power of TailwindCSS to style your web applications without the need for additional frameworks.

A quick recap of the required steps:

  • Set up the project structure: Create the necessary directories and files for Express.js and TailwindCSS integration

  • Install dependencies: Add Express.js, TailwindCSS, PostCSS, and supporting plugins to the project

  • Configure TailwindCSS: Set up TailwindCSS and PostCSS configuration files

  • Generate and include styles: Compile TailwindCSS into a usable stylesheet and linked it in the EJS templates

The complete source code is available in the examples directory on GitHub: https://github.com/keenthinker/blogpostscode.