How to Build a CSS Library with Vite.js

Creating a reusable CSS library can supercharge your web development workflow. Instead of writing custom styles from scratch for each new project, you can build a library of styles once and efficiently apply them everywhere.

In this guide, we‘ll walk through how to harness the power of Vite.js to build a modern, optimized CSS library that can be shared across projects. Whether you‘re a web development team looking to enforce brand consistency or an open source enthusiast assembling a toolkit of your favorite styles, these techniques will set you on the path to CSS componentization.

What is a CSS Library?

A CSS library is a collection of pre-written stylesheets that provide a set of reusable components, layouts, and utility classes. Popular examples include Bootstrap, Bulma, Tailwind CSS, and more.

The key benefits of CSS libraries are:

  1. Consistency – Applying the same set of styles leads to a cohesive look and feel across pages and projects. This is crucial for establishing a strong brand identity.

  2. Efficiency – With a CSS library, you spend less time writing custom CSS and debugging cross-browser issues. This lets you focus on building great content and experiences.

  3. Maintainability – Styles are kept in a single source of truth instead of being duplicated across projects. Updating the library automatically propagates changes everywhere it‘s used.

  4. Scalability – As your team and projects grow, a shared set of styles makes it easy to maintain consistent interfaces and onboard new developers.

CSS libraries can be open source, used within a company, or even kept to yourself. You have the freedom to structure them however best fits your needs.

Why Use Vite.js?

Vite.js is a next generation frontend build tool that‘s quickly gaining popularity. Some standout features that make it a great fit for building CSS libraries include:

  • Lightning fast dev server powered by native browser ES modules
  • Optimized production builds via rollup
  • Flexible plugin system to transform and extend functionality
  • Support for TypeScript, JSX, CSS preprocessors, and more out of the box
  • Simple, minimal configuration

By leveraging Vite, we can create a modern CSS library build pipeline that‘s easy to configure, produces lean bundles, and integrates seamlessly with our favorite tools and frameworks. Let‘s dive in!

Step 1: Set Up a New Vite Project

First, make sure you have a recent version of Node.js installed. Then open up your terminal and run:

npm init @vitejs/app

You‘ll be prompted to choose a project name and template. For our purposes, select the Vanilla template. This will give us a minimal setup we can customize to build our library.

Once the project is generated, navigate to the project root and install dependencies:

cd your-lib-name
npm install

To make sure everything is working, start up the dev server:

npm run dev 

And open up http://localhost:3000 in your browser. You should see a simple page with Vite + Vanilla in the center.

Step 2: Configure Vite to Build a Library

By default, Vite is set up to build a web application. We need to tweak the config slightly to output a library instead.

Create a vite.config.js file in your project root:

import { defineConfig } from ‘vite‘
import path from ‘path‘

export default defineConfig({
  build: {
    lib: {
      entry: path.resolve(__dirname, ‘src/main.js‘),
      name: ‘MyLib‘,
      fileName: (format) => `my-lib.${format}.js`
    },
  }
})

Here we‘re specifying that the entry point for our library is src/main.js. This file will serve as the root that Vite starts from when following imports and generating the final bundle.

We also provide a fileName factory function that will determine how the generated files are named based on the output format (ES modules or UMD).

With that config in place, update src/main.js to:

import ‘./style.css‘

export function myLib() {
  console.log(‘my-lib initialized‘)
}

And add some placeholder styles to src/style.css:

.my-lib-button {
  padding: 8px 12px;
  border-radius: 4px;   
  background-color: #646cff;
  color: white;
}

Now when you run npm run build, Vite will generate a dist directory with my-lib.es.js and my-lib.umd.js – your bundled library code ready to be consumed by other projects!

Step 3: Use Sass for Styling

Sass is a popular CSS preprocessor that adds lots of powerful features on top of vanilla CSS like variables, nesting, functions, and more. Vite has built-in support for Sass, so we can easily incorporate it into our library.

First install Sass:

npm install -D sass

Then rename style.css to style.scss and update the import in main.js.

Let‘s leverage Sass color variables to allow for easy theming:

$primary-color: #646cff;

.my-lib-button {
  padding: 8px 12px;
  border-radius: 4px;
  background-color: $primary-color;  
  color: white;

  &:hover {
    background-color: darken($primary-color, 10%);
  }
}

After making these changes, re-run npm run dev and npm run build. Vite will handle compiling Sass to CSS and bundling it with your JavaScript.

Step 4: Handle Assets

To demonstrate handling of assets like images, let‘s add a background graphic to our button.

First, add an image to the src directory next to style.scss. For this example I‘ll use src/confetti.png.

Then reference the image in your Sass:

.my-lib-button {
  padding: 8px 12px;
  border-radius: 4px;
  background: $primary-color url(./confetti.png) no-repeat center right;
  background-size: 20px;
  color: white;

  &:hover {
    background-color: darken($primary-color, 10%);
  }  
}

If you run npm run build now, you might be surprised to find that confetti.png is nowhere to be found! By default, Vite ignores assets referenced in CSS.

To include the image in our final bundle, we need to move it to a special public directory:

my-lib/
├─ src/
│  ├─ main.js
│  └─ style.scss
└─ public/
   └─ confetti.png

Update the image URL in style.scss to point to /confetti.png and rebuild. This time the PNG will be copied to the dist directory alongside your JavaScript bundle.

The public directory is also useful for including other types of assets like fonts, SVGs, or additional CSS/JS files that you want to ship with your library.

Step 5: Package and Publish

Our CSS library is taking shape, but it‘s not very useful stuck in our local development environment. Let‘s package it up and distribute it via npm so other projects can install it as a dependency.

Open up package.json and add a "files" array that specifies which files should be included when the library is installed:

{
  "name": "my-lib",
  "files": [
    "dist"
  ]
  ...
}

Make sure to set the name of your package to something unique. You may also want to clean up extraneous properties like "devDependencies" and "scripts" that are only used internally.

Once you‘re ready, run npm publish to push your library up to the npm registry. Other projects can now install it by running:

npm install my-lib

And import it in their code:

import ‘my-lib/dist/style.css‘
import { myLib } from ‘my-lib‘

myLib()

That‘s it! You‘ve successfully built and distributed a CSS library using Vite. Pat yourself on the back.

Taking It Further

We‘ve covered the fundamentals of building a Vite-powered CSS library, but there‘s always room for enhancement. Here are some additional ideas to explore:

  • Export your styles as Sass in addition to compiled CSS, giving consumers more customization options
  • Use CSS modules to automatically scope your styles and prevent naming collisions
  • Add a TypeScript declaration file to provide type info and editor hints
  • Set up unit and visual regression testing to prevent accidental style changes
  • Automatically generate a style guide site from your source files

I hope this guide has inspired you to think modularly and leverage Vite to create your own arsenal of reusable styles. The CSS ecosystem is your oyster!

Similar Posts