Frontend UI libraries - Finding A Bootstrap Replacement

Dave SlackFriday, October 4, 2024

For a new project what UI library should I use? I’ve used Bootstrap for a few years now and it’s time to look at some of the new libraries. I’ll test 7 of the ones I’ve heard about recently and will find the one that is best for a new project.

Huyton Web Services logo | Frontend UI libraries - Finding A Bootstrap Replacement title and logos for the frontend UI libraries

Over the years I’ve used many frontend libraries, UI libraries, toolkits, etc. Some great, some not so great. For a while now I’ve used Bootstrap and it’s perfect for most cases. I build a layout, create a design and Bootstrap allows me to do exactly what I need, then gets out of the way when I don’t need it. There is a huge library of usable components, there isn’t a massive amount of extra, useless classes and the code is separated and clean. Lovely. 

Lately, I’ve been using more and more React and where Bootstrap works well with React, it only allows me to bring in the full Bootstrap or nothing, no imports for only what I use (there is a React Bootstrap we can look at later). This isn’t great for bundle size and performance so I’m looking to find something that is. 

I’ve found a bunch of UI libraries and I’m going to test each one with the following test:

  • Responsive
  • Background colour: Black → Blue (#0C004E) → White
  • Front colour: White
  • Font colour: black
  • Font as Fredoka from Google fonts
  • Main menu with responsive version

The design will looks something close to this:

This is quite a simple test and design. It won’t win any awards, but should prove the UI library is a valid replacement for Bootstrap.

I've created a branch for each of the UI Libraries on the Next.js Huyton Web Services Repo so you can have a look at the code I've created for each. A link to each of the branches is available with each library. Below is the list of UI libraries I test, I look at:

NB. Tailwind might not belong on this list as it says it’s a ‘CSS Framework’ not a UI library, but as it could be a drop-in replacement for Bootstrap it may be a contender, so I’ve added it just to test its capabilities.

I have no real interest in a polished design at the moment, I am interested in time and difficulty. Let’s dig in.

MUI

MUI Github branch

Install

npm install @mui/material @emotion/react @emotion/styled
npm install @fontsource/jost
npm install @mui/icons-material

Installation is simple enough.

Colours

If you have 1 colour for your design, then there is a great colour tool to show complimentary colour and some other types. This will help build the colour pallet for the app.

Font

Fonts are installed the usual way using Next Google fonts import then adding to the theme. This is all done in the theme.js file:

import { Fredoka } from 'next/font/google';
const fredoka = Fredoka({
    weight: ['300', '400', '500', '700'],
    subsets: ['latin'],
    display: 'swap',
});
const theme = createTheme({
    typography: {
        fontFamily: fredoka.style.fontFamily,
    },
});

Image

Main image breaks out of the main container, fixed with an imageFix class in the global css.

.imageFix{
    max-width: 100%;
    height: auto;
    object-fit: cover;
}

Layout

I changed the CSS for the main container and body to set the colours. It worked as expected, so we can override styles as we need. This is great, allowing shadow and round corners or footer at the bottom.

Needed to force the scrollbar to stop the bounce on pages that are longer with and had to force the body to 100% height to stop the background colour finishing in a strange place:

html, body{
    min-height: 100vh;
}
body{
    overflow-y: scroll;
}

Main menu

Creating the main menu is not trivial and requires to slowly build up the menu from an App Bar and a menu. There is no mobile version, this must be built too.

Summary

MUI has some great components and is set up to work with React, however, there is a lot of work to get a page looking well designed. It does use import for each part, so nothing is added to the app without manually adding. This is great for keeping the app small. Code uses either JS or TS in the docs which is very useful. 

MUI is simple to use, but took a little longer for the main menu simply because there is no good version in the docs.

MUI works with the IDE out of the box, no installing extras.

Mantine

Mantine Github branch

Install

npm install @mantine/core @mantine/hooks
npm install --save-dev postcss postcss-preset-mantine postcss-simple-vars

Install was very easy.

Colours

There is a Mantine Colour Generator for default colours which is useful.

I did not try this but is should setup the colours for all components.

Font

Installing the font uses the normal Google font method, then add it to the theme:

import { Fredoka } from 'next/font/google';
const theme = createTheme({
    fontFamily: fredoka.style.fontFamily
});

Image

Changing the image import from “next/image” to “@mantine /core” gives us some options and we don’t need to use the imagefix CSS using this.

<Image
   src={content.main_image.url}
   alt={content.main_image.alt}
   fit="contain"
/>

Although removing the image width and height was a little strange and might need looking at.

Layout

Looking for layout and main containers is difficult to find, but it’s under Mantine Core and layout. This is not as good as some responsive layout and only supports up-to about 1000px resolution, anything lager doesn’t really count so this would need changing for larger monitors.

I needed to force the scrollbar to stop the bounce on pages that are longer with and had to force the body to 100% height to stop the background colour finishing in a strange place, but I had to do this for all libraries:

html, body{
    min-height: 100vh;
}
body{
    overflow-y: scroll;
}

The grid system seems simple enough and works well.

Main Menu

Adding the main menu was simple, but it does not create a mobile version as standard, this would need to be done manually.

Summary

This is a great piece of kit with lots of components, but there are issues working with the IDE causing errors. The documentation uses only TS without a JS version which will be an issue. IDE needs some installation plugins (if they exist) and newer code from Mantine is not supported correctly yet (if ever).

Using Mantine needs many code changes from the documentation to get a working version of examples.

Bootstrap

Bootstrap Github branch

Install

Installing Bootstrap is not a simple matter

npm i bootstrap@5.3.3
npm i sass

Create a Bootstrap component and add the code:

"use client";
import { useEffect } from "react";
export default function Bootstrap()
{
    useEffect(()=>{
       import("bootstrap/dist/js/bootstrap.esm");
    },[]);
}

Import the above component into _app.js.

Rename globals.css to globals.scss and import the SCSS below into the file:

@import "../node_modules/bootstrap/scss/bootstrap";

Because everything is added to the bundle we can remove unused styles with PurgeCSS. A useful blog post Removing unused CSS with PurgeCSS gives more information, but to get it to work we install with:

npm install --save-dev @fullhuman/postcss-purgecss
npm install postcss-flexbugs-fixes postcss-preset-env

Create the postcss.config.js file in the root of your app and add:

module.exports = {
   "plugins": [
       "postcss-flexbugs-fixes",
        [
           "postcss-preset-env",
            {
               "autoprefixer": {
                   "flexbox": "no-2009"
                },
               "stage": 3,
               "features": {
                   "custom-properties": false
                }
            }
        ],
        [
           '@fullhuman/postcss-purgecss',
            {
               content: [
                   './pages/**/*.{js,jsx,ts,tsx}',
                   './components/**/*.{js,jsx,ts,tsx}'
                ],
               defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
               skippedContentGlobs: ['./node_modules/prismjs/**'], // Fails :(
               safelist: {
                   standard: [
                       "html",
                       "body",
                       "figcaption",
                       "references",
                       "thankYou",
                       "w-25",
                       "grecaptcha-badge",
                       "aside",
                       "modelBack"
                    ],
                   deep: [/mx/],
                   greedy: [
                       /img/,
                       /mx/,
                       /block/,
                       /message/,
                       /PhotoView/,
                       /gifcontrol/,
                       /jsgif/,
                       /pre/,
                       /code/,
                       /numbers/,
                       /print/,
                       /token/,
                       /float/,
                       /col/,
                    ]
                }
            }
        ],
    ]
}

Installation is not trivial and as classes are used we need to add them to the safe list or they are stripped out.

Colours

There is no override app for the colours, so any colour must be added manually.

Font

We install the font in the usual way from Google, but we also add the font to <main>:

import { Fredoka } from 'next/font/google';
const fredoka = Fredoka({
    weight: '300', // 700 for bold
    subsets: ['latin'],
});
<main className={fredoka.className}>
</main>

Image

Added the imageFix CSS to the image to stop it breaking out of the container.

Layout

Layout is achieved with divs and classes. Very simple.

Main Menu

Main menu is quite simple it’s just the NavBar and once configured it has the mobile version built-in with no duplication. We simply override the colours.

Summary

Bootstrap is great for layout and quickly adding columns and rows, but it soon becomes messy with the CSS overrides. We can add the full library, but not import components as we need them, so there is a large file size. To make the CSS/JS smaller we need to install and configure PurgeCSS. Installation takes a long time and can be tricky. There are no components for React as Bootstrap is not built for it.

For a brand new project I would try to stay away from Bootstrap.

React Bootstrap

React Bootstrap Github branch

Install

npm i react-bootstrap bootstrap
npm i scss

Rename globals.css to globals.scss and add the import into the file:

@import '~bootstrap/scss/bootstrap';

Colours

To use dark mode for the whole app we need to create a Next.js _document.js page and add data-bs-theme="dark" to the html element. Very simple.

Font

We install the font in the usual way from Google and add the font to <main>:

import { Fredoka } from 'next/font/google';
const fredoka = Fredoka({
    weight: '300', // 700 for bold
    subsets: ['latin'],
});
<main className={fredoka.className}>
</main>

Image

We can use the import from react-bootstrap for the image instead of using the import from Next.js similar to Mantine. This gives us the option of using fluid and we don’t need the width and height.

//import Image from "next/image";
import Image from 'react-bootstrap/Image';

Layout

We add the layout using components and only import them as we need them. This is a much neater option over the full import on Bootstrap then using multiple classes. We can use most of the classes from Bootstrap for example rounded-top on the container.

Main Menu

Using the Navbar makes creating the main menu simple. The main menu also comes with a mobile version without duplication.

There are 2 versions of the mobile, one the usual burger menu that slides down an also a second type called Offcanvas that slides from the side. I went for the one that slides down and didn't try Offcanvas.

Summary

Simple setup, simple classes, gets out of the way when needed and good looking. Takes all the best parts of Bootstrap and makes it into components you import as needed. Oh, and on npm run dev this felt as fast as Bootstrap which feels the most performant of all the libraries here.

Chakra

Chakra Github branch

Install

npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion

After install import the Chakra and add the component around the app

import { ChakraProvider } from '@chakra-ui/react'
function App() {
  return (
   <ChakraProvider>
     <TheRestOfYourApplication />
   </ChakraProvider>
  )
}

Simple install.

Colours

First we need to create a theme.js, then a _document.js both in the pages/ folder. then we need to add quite a bit of code to get the dark theme working.

// pages/theme.js
import { extendTheme } from '@chakra-ui/react'
const config = {
    initialColorMode: 'dark',
   useSystemColorMode: false,
}
const theme = extendTheme({ config });
export default theme;

 

// pages/_document.js
import { ColorModeScript } from '@chakra-ui/react'
import NextDocument, { Html, Head, Main, NextScript } from 'next/document'
import theme from './theme'
export default class Document extends NextDocument {
    render() {
        return (
            <Html lang='en'>
               <Head />
               <body>
                   <ColorModeScript initialColorMode={theme.config.initialColorMode} />
                   <Main />
                   <NextScript />
               </body>
           </Html>
        )
    }
}

To get this to work I needed to remove the local storage data under Application → Clear site data.

Font

We install the font in the usual way from Google, but we also add the font to <main>:

import { Fredoka } from 'next/font/google';
const fredoka = Fredoka({
    weight: '300', // 700 for bold
    subsets: ['latin'],
});
<main className={fredoka.className}>
</main>

Layout

Everything is has to be re-thought as all html tags are reset e.g. <h1> is <Text fontSize='6xl' as='h1'> and <h2> is <Text fontSize='5xl' as='h2'>.This would not work with a CMS WYSIWYG as a CMS relies on html tags.

Main Menu

I didn’t get the chance to look at this in the time. It would need building from scratch as there is no Main Menu component we can simply use.

Summary

Does have a built in check for the Operating System colour scheme if you provide dark and light designs.

The Documentation is a bit random between JS and TS and sometimes we are not told if the code is TS or JS.

Chakra has a full reset of all styles e.g. <p>, <h1> and <h4> are all set to font-size: 16px.

Unfortunately, half a day is nowhere near enough time to look at this UI library. I could not see a way to add in the basic layout or the main menu without building from scratch. There are 3rd parties that can help with this (e.g. Chakra UI Templates ) but nothing that had a simple, responsive layout to use.

Personally, I like the idea of Chakra, but there is too much to do here compared to other UI libraries.

Tailwind

Tailwind Github branch

Install

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Update the config:

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
   "./app/**/*.{js,ts,jsx,tsx,mdx}",
   "./pages/**/*.{js,ts,jsx,tsx,mdx}",
   "./components/**/*.{js,ts,jsx,tsx,mdx}",
    // Or if using `src` directory:
   "./src/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Add the global css

// globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

Simple setup using the Tailwind guide.

Tailwind works with PHPStorm out of the box, so no changes to the IDE necessary.

To add back some of the html tag styles allowing us to use a CMS WYSIWYG we install a plugin:

npm install @tailwindcss/typography

Add the plugin to config:

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // ...
  },
  plugins: [
   require('@tailwindcss/typography'),
    // ...
  ],
}

Now we can use the class on our CMS content e.g.

<div className="prose" dangerouslySetInnerHTML={{ __html: content.body }} />

Colours

No matter what I did I could not get the Tailwind to switch to dark mode without creating a switch. For the design I need to start on dark mode and work from there. I found an answer on stackoverflow - force tailwind dark mode, forcing dark on the light the media query which works.

@media (prefers-color-scheme: light) {
    html {
        color-scheme: dark;
    }
}

Next create a pages/_document.js and add the class dark to the html tag:

import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
    return (
        <Html lang="en" className="dark">
            <Head />
           <body>
            <Main />
           <NextScript />
           </body>
        </Html>
    )
}

Font

Font is added in the usual way with Google fonts:

import { Fredoka } from 'next/font/google';
const fredoka = Fredoka({
    weight: '300', // 700 for bold
    subsets: ['latin'],
});
<main className={fredoka.className}>
</main>

Image

Our image works out of the box and resizes correctly without any fixes, we simply add it to a container. However, I did add the class break-after-column to keep the image on its own column.

Layout

Layout is created by adding classes into containers until we have the correct look. For example my main container needed to be responsive, white and rounded at the top:

<div className="container mx-auto bg-white p-4 rounded-t-md">

Tailwind works well and as the app gets larger our CSS won’t grow huge and we won’t have lot’s of overriding CSS classes and styles. It does have a LOT of classes in each tag though making the html rather ugly.

Main Menu

Some of the components are paid for on the Tailwind components website but some are free. There is a free main menu which works well and with a little time and effort I could probably get any type of menu working with it, however, there is duplication between the desktop and mobile versions 

Summary

Tailwind strips all styles, so won’t work with a CMS WYSIWYG i.e. if a user add <h2> to a heading there will be no difference to a <p>. If we add in a plugin called Typography we can use a class called prose that will allow us to use a CMS WYSIWYG again.

Some of the good components are paid for, which is something to think about when using Tailwind.

Shadcn

Shadcn Github branch

Install

To install this we need Tailwind, see the Tailwind section for this. Once Tailwind is working correctly add shadcn with:

npx shadcn@latest init -d

This is a setup script and the -d add the default answers so you don't get asked a bunch of questions we don't know the answers too.

We now have a components.json file with some config and a /lib/utils.js, we’ll need to add these to the git repo too. There are also a lot of interesting styles added to the globals.css.

Site Setup

For the Colours, Font, Image and Layout, we use Tailwind.

Main Menu

Shadcn does not have a “Main Menu” component, but does have Navigation bar and MenuBar components that would allow a build of a main menu. However, the Tailwind version works out of the box so I’ve not looked at building a brand new one using parts from these components.

Summary

Shadcn is a list of components that use Tailwind and they are similar to the paid versions offered by Tailwind. Starting with Tailwind to create the layout then using Tailwind components, but if we get stuck, we can always add shadcn later.

Finishing up

Chakra is not the correct library for most (if not all) my projects because I use a CMS and resetting the html element styles is a big no. I also tend to use JS, not TS, so the docs require careful changes to any code.

Shadcn is also out as it relies on Tailwind which has all the building blocks I need to create a well-designed layout. However, Tailwind does reset the html element styles, which I’m not so sure about, it feels like I removed the html tag styles then added them back with a plugin. On the one hand I know all browsers and devices will have the same styles, on the other, this is a duplication and makes the file size lager, so I'd probably stay away from Tailwind too.

This leaves Mantine, React Bootstrap or MUI.

Mantine has a good selection of full components and styles to create a great UI. It is also very pretty. The only issues are Mantine is overused (we see it all over the internet) and the documentation is in TS not JS. I would be happy to use it if a team wanted to use it because they had experience with it.

Bootstrap/React has everything I would need; it feels responsive and uses less code for the main menu than any of the other UI libraries. There are many Themes that can be purchased, lots of components that can be used to build up a great UI and there are also Themes to purchase.

Lastly, there is MUI. This has everything needed to build a UI, it allows us to build complex components, use components already built or purchase and use free themes. The MUI website has the most information of all these libraries and feels the most polished.

Out of all of these I will choose Bootstrap/React or MUI for all new projects. For the more app based I would use MUI, but for more web based I would go with Bootstrap/React. 

If you have any experience with these libraries or you have anything to add please comment and let us know. If you are looking for somone to build an app or site with one of these contact us and have a chat.

Leave a comment

If you don't agree with anything here, or you do agree and would like to add something please leave a comment.

We'll never share your email with anyone else and it will not go public, only add it if you want us to reply.
Please enter your name
Please add a comment
* Denotes required
Loading...

Thank you

Your comment will go into review and will go live very soon.
If you've left an email address we'll answer you asap.

If you want to leave another comment simply refresh the page and leave it.

We use cookies on Huyton Web Services.
If you'd like more info, please see our privacy policy