All Posts

Let's Build: HTML5 Development Server & Build Tool With Webpack - Adding CSS Support

Welcome everyone to the second part of this tutorial series. Picking up from last week where we created our web server and our first page, today, we’re going to add CSS Support to our development server.

Without further ado, let’s get started.

Adding CSS Support

The first thing that we will be doing today is to setup our development server to serve CSS in our pages. As we continue from last week, let us do the following:

  1. Open your terminal, go inside the root directory of our development server and install these npm packages:
npm install css-loader style-loader --save-dev

  1. Next, let us add these lines inside our webpack.config.js.
  module: {
    rules: [
      //add this below after the object for the babel loader
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ]
      },
    ]
  },

What happened here is when webpack sees any css files in the depdency graph of each of the entry points, in our example the index entry point, it will put the css files through css-loader and style-loader. Yes, in that order.

We need to use css-loader so that webpack can understand css files. After that, we use style-loader so that after the resulting css after the process from css-loader will be injected into the webpage, inside the <head with <style>.

  1. Next, let us create an index.css file src/pages/index directory.
  2. Inside your index.css file, add this css:
.greeting {
  font-size: 45px;
  font-family: Arial, Helvetica, sans-serif;
  color: rgb(45, 156, 101);
  text-align: center;
}
  1. Going back to our index.html file, update the content inside the <body> with this html:
  <body class="home">
    <h1 class="greeting">
      Hello World! This is the home page!
    </h1>
    
    <!-- This is where the JS tags go from the output of the chunks defined in "new HTMLWebpackPlugin" -->
    <%= htmlWebpackPlugin.tags.bodyTags %>
  </body>
  1. Now let’s add CSS. Let’s go to index.js and add the following code:
import './index.css'

This may be weird, but this is how we add CSS. Instead of putting <style> inside your HTML, we import it inside our index entry script index.js, just like how we import a common JavasScript file.

  1. Go to back to your terminal, and run npm start. Visit your browser at http://localhost:3000 and you should now see something like this:

Image

Yay! CSS is now being injected inside our webpage. We can now modify how our text looks with how we did in the screenshot above.

Adding PostCSS & TailwindCSS

For this tutorial, I will also be using my personal choice when it comes to my CSS development toolchain with PostCSS and TailwindCSS. I use PostCSS because I prefer to keep my toolchain as close to the javascript ecosystem as possible and it can already to many things that Sass can do in the past. With TailwindCSS, I love to have a library of utility classes at my disposal.

To add PostCSS & TailwindCSS, let us do the following:

  1. Go to your terminal and install the following npm packages:
npm install postcss-loader tailwindcss postcss-mixins postcss-simple-vars postcss-nested autoprefixer postcss-preset-env postcss-calc postcss-rem cssnano
  1. Open your terminal and find for the loaders for css files(/\.css$/,) and add postcss-loader.
...
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader'
        ]
      },
...
  1. Open package.json, add browserslist entry.
...

  "dependencies": {},
  "browserslist": [
    "last 2 versions",
    "> 1%",
    "iOS >= 8",
    "Safari >= 8"
  ]
...

Browserslist is a standard configuration tool that returns list of target browsers and node environments. The reason we are adding this as early as now is because by having this, we are telling @babel/preset-env and postcss-preset-env to inject necessary modifications/additions to our code depending on which browsers that we are targeting according to our browserslist configuration. For more information visit browserslist.

  1. Create the PostCSS configuration file(postcss.config.js). Open it using your text editor and add these PostCSS configuration object that contains all the postcss plugins that we are using:
const path = require("path");

module.exports = {
  plugins: {
    'tailwindcss': {},
    'postcss-mixins': {
      // We'll be adding this directory later
      mixinsDir: path.join(__dirname, 'src/assets/css/mixins')
    },
    'postcss-simple-vars': {
      variables: function () {
        // We will be adding this file later
        return require('./src/assets/css/css-variables');
      }
    },
    'postcss-nested': {},
    'postcss-preset-env': {
      // Error fix for "Error: Expected an opening square bracket"
      // https://github.com/tailwindlabs/tailwindcss/issues/1190#issuecomment-546621554
      stage: 1,
      features: {
        'focus-within-pseudo-class': false
      }
    },
    'postcss-calc': {},
    'postcss-rem': {
      fallback: true,
    },
    'cssnano': {},
    'autoprefixer': {}
  }
}

In case you are wondering what these plugins does:

  • tailwindcss as self explanatory as this is, is a PostCSS plugin for TailwindCSS.
  • postcss-mixins allows you to have a mixins, similar to what you have in Less or Sass.
  • postcss-simple-vars enables you to set variables for you to use in your css files.
  • postcss-nested enables you to have nested syntax for your css, just like in Less or Sass.
  • postcss-preset-env is like @babel/preset-env for css, where it takes care of any fallbacks or polyfills for your target browsers listed in browserslist
  • postcss-calc allows you to do calculations within your CSS.
  • postcss-rem provides a rem($font-size) syntax that returns a font-size with rem and px unit as fallback. This is for those who prefers using relative units(rem, em etc.) over absolute units(px).
  • cssnano provides minification to CSS
  • autoprefixer adds necessary vendor-specific prefixes to certain CSS styles for better compatibility to browsers listed in your browserslist.

  1. Optional next step: You can add a tailwind.config.js if you want to modify TailwindCSS defaults.
module.exports = {
  purge: [],
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
}

Applying configuration changes to the webpage

Now that we’ve made enough changes to our development server’s configuration files, let’s do some changes in our code to see if these plugins do work.

  1. Because we added adding postcss-mixins in our postcss.config.js, let us created the mixins directory. Inside your terminal, within the project directory root, run:
mkdir -p ./src/assets/css/mixins
  1. Inside ./src/assets/css/mixins, create a mixins.css file.
cd ./src/assets/css/mixins
touch mixins.css
  1. Open mixins.css using your text editor and add these.
@define-mixin set-font-family {
  font-family: Arial, Helvetica, sans-serif;
}
  1. Now for the postcss-simple-vars in postcss.config.js that we added earlier, let us create the file that will contain the variables.
cd /your_project_root
touch ./src/assets/css/css-variables.js
  1. Open your /src/assets/css/css-variables.js file and add these:
module.exports = {
  colorPrimary: '#34d399',
  greetingFontSize: 45
}

These are the variables that we will be using for our quick PostCSS & TailwindCSS feature demo later.

Note: One limitation of the variables using postcss-simple-vars is whenever you add a new variable, you need to restart the development server.

  1. Now, let us go back inside ./src/pages/index/index.css, add replace all your CSS with these:
@tailwind base;
@tailwind components;
@tailwind utilities;

.greeting {
  font-size: rem($(greetingFontSize)px);
  @mixin set-font-family;
  color: $colorPrimary;
  text-align: center;
}

As you’ve probably noticed, our CSS has some new syntax going on. These are the syntax conventions provided by some of the PostCSS plugins that we are using.

  1. Lastly let’s open ./src/pages/index/index.html and add replace the <body> with:
<body class="home">
  <div class="bg-white rounded border-green-400 border-4 max-w-lg mt-8 p-8 mx-auto">
    <h1 class="greeting">
      Hello World! This is the home page!
    </h1>
  </div>
  
  <!-- This is where the JS tags go from the output of the chunks defined in "new HTMLWebpackPlugin" -->
  <%= htmlWebpackPlugin.tags.bodyTags %>
</body>

For those CSS classes with the wrapping <div> to the <h1> tag. Those are utility classes provided by TailwindCSS. Please check TailwindCSS’ website for more information.

  1. Now, go back once again to your terminal and start your development server.
npm run start
  1. Open your browser and visit http://localhost:3000. You should see something like this:

Image

Yay! With that, we now have PostCSS and TailwindCSS integrated to our development server.

Conclusion

That wraps up this part 2 of this series. I hope you learned something today about how to add CSS support, about PostCSS and TailwindCSS. I encourage you to investigate and understand everything that’s happening with these changes that we made and adjust this configuration to what suits your development style. For the complete source code of this tutorial, please visit this github link.

Next week, I will be sharing to you how to import static assets like images and fonts to our development server.

Have a blessed weekend everyone!


Hi! If you have any questions, suggestions, corrections, or constructive feedback about this post, please let me know. I will greatly appreciate it!💯