DEV Community

Cover image for My Honest Review of Tailwind, Radix UI, and Shadcn UI
Timi
Timi

Posted on

My Honest Review of Tailwind, Radix UI, and Shadcn UI

My Honest Review Of These CSS Librarieis

In recent years, there has been a growing trend towards using CSS libraries to speed up and simplify the development of web applications. Three of the most popular CSS libraries today are Tailwind, Radix UI, and Shadcn UI.


Tailwind is a utility-first CSS framework that allows you to build custom styles with a minimal amount of code. It's very popular among developers because it's highly customizable and can be used to create a wide variety of designs. However, Tailwind can be a bit difficult to learn at first, and it can be easy to make mistakes if you're not careful.

Radix UI is a component-based CSS library that provides a set of ready-made components that you can use to build your web application. It's a good choice for developers who want to get started quickly without having to worry about writing custom CSS. However, Radix UI can be a bit limiting if you need to create custom components, and it can be more expensive than other CSS libraries.

Shadcn UI is a relatively new CSS library that combines the best features of Tailwind and Radix UI. It's highly customizable like Tailwind, but it also provides a set of ready-made components like Radix UI. Shadcn UI is a good choice for developers who want the flexibility of Tailwind with the convenience of a component library.

Here is a table that summarizes the advantages, disadvantages, and key features of each CSS library:

Tailwind Advantages Disadvantages Key Features
Tailwind Highly customizable, can be used to create a wide variety of designs Can be difficult to learn at first, easy to make mistakes Utility-first CSS framework, allows you to build custom styles with a minimal amount of code
Radix UI Ready-made components, easy to get started Can be limiting if you need to create custom components, more expensive than other CSS libraries Component-based CSS library, provides a set of ready-made components that you can use to build your web application
Shadcn UI Highly customizable, ready-made components, easy to learn Not as widely used as Tailwind or Radix UI Combines the best features of Tailwind and Radix UI, highly customizable, provides a set of ready-made components

Installation

Here is a quick overview of how to set up each library:

  • Tailwind: To set up Tailwind, you need to install the tailwindcss package and the postcss package. You can do this with the following command:
npm install tailwindcss postcss
Enter fullscreen mode Exit fullscreen mode

Once you have installed the packages, you need to create a tailwind.config.js file in the root directory of your project. This file will contain the configuration settings for Tailwind. You can find more information about the configuration settings in the Tailwind documentation


  • Radix UI: To set up Radix UI, you need to install the radix-ui/themes package, then any other package that follows. Today I'll show you how to install the followinng

  • radix-ui/themes

  • radix-ui/react-alert-dialog

Getting Started

Installation

1. Install Radix Themes

Install the package from your command line.

npm yarn pnpm
npm install @radix-ui/themes yarn add @radix-ui/themes pnpm install @radix-ui/themes

2. Import the CSS file

Import the global CSS file at the root of your application.

import '@radix-ui/themes/styles.css'; 
Enter fullscreen mode Exit fullscreen mode

3. Add the Theme component

Wrap the root of your application in a Theme component.

import { Theme } from '@radix-ui/themes';

export default function () {
  return (
    <Theme>
      <MyApp />
    </Theme>
  );
}
Enter fullscreen mode Exit fullscreen mode

4. Start building

You are now ready to use Radix Themes components.

import { Flex, Text, Button } from '@radix-ui/themes';

export default function MyApp() {
  return (
    <Flex direction="column" gap="2">
      <Text>Hello from Radix Themes :)</Text>
      <Button>Let's go</Button>
    </Flex>
  );
}
Enter fullscreen mode Exit fullscreen mode

Customizing your theme

Learn More


Installing react-alert-dialog with radix-ui


Install the Component

npm install @radix-ui/react-dialog 
Enter fullscreen mode Exit fullscreen mode

Usage

//index.tsx

import React from 'react';
import * as AlertDialog from '@radix-ui/react-alert-dialog';
import './styles.css';

const AlertDialogDemo = () => (
  <AlertDialog.Root>
    <AlertDialog.Trigger asChild>
      <button className="Button violet">Delete account</button>
    </AlertDialog.Trigger>
    <AlertDialog.Portal>
      <AlertDialog.Overlay className="AlertDialogOverlay" />
      <AlertDialog.Content className="AlertDialogContent">
        <AlertDialog.Title className="AlertDialogTitle">Are you absolutely sure?</AlertDialog.Title>
        <AlertDialog.Description className="AlertDialogDescription">
          This action cannot be undone. This will permanently delete your account and remove your
          data from our servers.
        </AlertDialog.Description>
        <div style={{ display: 'flex', gap: 25, justifyContent: 'flex-end' }}>
          <AlertDialog.Cancel asChild>
            <button className="Button mauve">Cancel</button>
          </AlertDialog.Cancel>
          <AlertDialog.Action asChild>
            <button className="Button red">Yes, delete account</button>
          </AlertDialog.Action>
        </div>
      </AlertDialog.Content>
    </AlertDialog.Portal>
  </AlertDialog.Root>
);

export default AlertDialogDemo;
Enter fullscreen mode Exit fullscreen mode

Using Default CSS


/* styles.css */

@import '@radix-ui/colors/black-alpha.css';
@import '@radix-ui/colors/mauve.css';
@import '@radix-ui/colors/red.css';
@import '@radix-ui/colors/violet.css';

/* reset */
button {
  all: unset;
}

.AlertDialogOverlay {
  background-color: var(--black-a9);
  position: fixed;
  inset: 0;
  animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
}

.AlertDialogContent {
  background-color: white;
  border-radius: 6px;
  box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 90vw;
  max-width: 500px;
  max-height: 85vh;
  padding: 25px;
  animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
}
.AlertDialogContent:focus {
  outline: none;
}

.AlertDialogTitle {
  margin: 0;
  color: var(--mauve-12);
  font-size: 17px;
  font-weight: 500;
}

.AlertDialogDescription {
  margin-bottom: 20px;
  color: var(--mauve-11);
  font-size: 15px;
  line-height: 1.5;
}

.Button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  padding: 0 15px;
  font-size: 15px;
  line-height: 1;
  font-weight: 500;
  height: 35px;
}
.Button.violet {
  background-color: white;
  color: var(--violet-11);
  box-shadow: 0 2px 10px var(--black-a7);
}
.Button.violet:hover {
  background-color: var(--mauve-3);
}
.Button.violet:focus {
  box-shadow: 0 0 0 2px black;
}
.Button.red {
  background-color: var(--red-4);
  color: var(--red-11);
}
.Button.red:hover {
  background-color: var(--red-5);
}
.Button.red:focus {
  box-shadow: 0 0 0 2px var(--red-7);
}
.Button.mauve {
  background-color: var(--mauve-4);
  color: var(--mauve-11);
}
.Button.mauve:hover {
  background-color: var(--mauve-5);
}
.Button.mauve:focus {
  box-shadow: 0 0 0 2px var(--mauve-7);
}

@keyframes overlayShow {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes contentShow {
  from {
    opacity: 0;
    transform: translate(-50%, -48%) scale(0.96);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}
Enter fullscreen mode Exit fullscreen mode

Using Component with Tailwind CSS


//index.tsx

import React from 'react';
import * as AlertDialog from '@radix-ui/react-alert-dialog';

const AlertDialogDemo = () => (
  <AlertDialog.Root>
    <AlertDialog.Trigger asChild>
      <button className="text-violet11 hover:bg-mauve3 shadow-blackA7 inline-flex h-[35px] items-center justify-center rounded-[4px] bg-white px-[15px] font-medium leading-none shadow-[0_2px_10px] outline-none focus:shadow-[0_0_0_2px] focus:shadow-black">
        Delete account
      </button>
    </AlertDialog.Trigger>
    <AlertDialog.Portal>
      <AlertDialog.Overlay className="bg-blackA9 data-[state=open]:animate-overlayShow fixed inset-0" />
      <AlertDialog.Content className="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[500px] translate-x-[-50%] translate-y-[-50%] rounded-[6px] bg-white p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none">
        <AlertDialog.Title className="text-mauve12 m-0 text-[17px] font-medium">
          Are you absolutely sure?
        </AlertDialog.Title>
        <AlertDialog.Description className="text-mauve11 mt-4 mb-5 text-[15px] leading-normal">
          This action cannot be undone. This will permanently delete your account and remove your
          data from our servers.
        </AlertDialog.Description>
        <div className="flex justify-end gap-[25px]">
          <AlertDialog.Cancel asChild>
            <button className="text-mauve11 bg-mauve4 hover:bg-mauve5 focus:shadow-mauve7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]">
              Cancel
            </button>
          </AlertDialog.Cancel>
          <AlertDialog.Action asChild>
            <button className="text-red11 bg-red4 hover:bg-red5 focus:shadow-red7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]">
              Yes, delete account
            </button>
          </AlertDialog.Action>
        </div>
      </AlertDialog.Content>
    </AlertDialog.Portal>
  </AlertDialog.Root>
);

export default AlertDialogDemo;
Enter fullscreen mode Exit fullscreen mode

  • Shadcn UI: To set up Shadcn UI, you need to initialize a new shadcn project with yours, shadcn comes with a CLI that integrates with your favorite frameworks, example are Next.js, Vite, Remix, Gatsby, Astro etc. Pick your favorite framework and run the CLI

Example using Next.js

  1. Create project:

Start by creating a new Next.js project using create-next-app

pnpm create next-app@latest my-app --typescript --tailwind --eslint
Enter fullscreen mode Exit fullscreen mode
  1. Run the CLI:

Run the shadcn-ui init command to setup your project:

pnpm dlx shadcn-ui@latest init
Enter fullscreen mode Exit fullscreen mode
  1. Configure components.json:

You will be asked a few questions to configure components.json:

Would you like to use TypeScript (recommended)? no / yes
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › › app/globals.css
Do you want to use CSS variables for colors? › no / yes
Where is your tailwind.config.js located? › tailwind.config.js
Configure the import alias for components: › @/components
Configure the import alias for utils: › @/lib/utils
Are you using React Server Components? › no / yes
Enter fullscreen mode Exit fullscreen mode
  1. App structure:
.
├── app
│   ├── layout.tsx
│   └── page.tsx
├── components
│   ├── ui
│   │   ├── alert-dialog.tsx
│   │   ├── button.tsx
│   │   ├── dropdown-menu.tsx
│   │   └── ...
│   ├── main-nav.tsx
│   ├── page-header.tsx
│   └── ...
├── lib
│   └── utils.ts
├── styles
│   └── globals.css
├── next.config.js
├── package.json
├── postcss.config.js
├── tailwind.config.js
└── tsconfig.json
Enter fullscreen mode Exit fullscreen mode
  • I place the UI components in the components/ui folder.

  • The rest of the components such as <PageHeader /> and <MainNav /> are placed in the components folder.

  • The lib folder contains all the utility functions. I have a utils.ts where I define the cn helper.

  • The styles folder contains the global CSS.

  1. That's it:

You can now start adding components to your project.

pnpm dlx shadcn-ui@latest add button
Enter fullscreen mode Exit fullscreen mode

The command above will add the Button component to your project. You can then import it like this:

import { Button } from "@/components/ui/button"

export default function Home() {
  return (
    <div>
      <Button>Click me</Button>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Key Features

Sure, here are the key features of Tailwind, Radix UI, and Shadcn UI:

Tailwind

  • Highly customizable
  • Can be used to create a wide variety of designs
  • Easy to learn
  • Can be used with any JavaScript framework
  • Provides a wide range of utility classes
  • Can be used to create custom components

Radix UI

  • Ready-made components
  • Easy to get started
  • Provides a wide range of components
  • Supports a variety of screen sizes
  • Well-documented
  • Actively maintained

Shadcn UI

  • Combines the best features of Tailwind and Radix UI
  • Highly customizable
  • Provides a set of ready-made components
  • Easy to learn
  • Actively maintained

Here is a table that summarizes the key features of each CSS library:

Tailwind Highly customizable, can be used to create a wide variety of designs, easy to learn, can be used with any JavaScript framework, provides a wide range of utility classes, can be used to create custom components
Radix UI Ready-made components, easy to get started, provides a wide range of components, supports a variety of screen sizes, well-documented, actively maintained
Shadcn UI Combines the best features of Tailwind and Radix UI, highly customizable, provides a set of ready-made components, easy to learn, actively maintained

My recommendation

Sure, here is a summary of the three CSS libraries, along with my recommendation for which is the easiest to set up and understand:

  • Tailwind is the most customizable library, but it can also be the most difficult to learn and set up. It's a good choice for developers who want to have complete control over their CSS, but it may not be the best choice for beginners.

  • Radix UI is the easiest library to set up and understand. It provides a set of ready-made components that you can use to build your web application, without having to write any custom CSS. However, Radix UI is not as customizable as Tailwind, so it may not be the best choice for developers who need a lot of control over their CSS.

  • Shadcn UI is a good compromise between Tailwind and Radix UI. It's more customizable than Radix UI, but it's also easier to set up and understand than Tailwind. Shadcn UI is a good choice for developers who want a balance of customization and ease of use.

My recommendation for the easiest library to set up and understand is Shadcn UI. It's a good choice for developers of all levels, and it provides a good balance of customization and ease of use.

Top comments (5)

Collapse
 
shimbarks profile image
Shimbarks

Radix UI is absolutely not what you described. It's a headless UI library, meaning it's unstyled. So it's totally suitable for developers who want to customize their components, and it's definitely not a CSS library. They did add themes recently, but the core of the library are the headless primitive components.

I suspect at least part of this article was composed (incorrectly) by AI, a lot of repetitions and comparison tables that use exactly the same expressions over and over again.

Collapse
 
diomededavid profile image
David Diomede

Calling Shadcn UI and Radix a CSS library is very misleading and incorrect. Both are either not opinionated or less opinionated about the css.

Collapse
 
redbar0n profile image
Magne

How would you compare Shadcn (uses Tailwind) vs something like Park UI (uses Panda CSS which is the successor to Chakra UI) ?

Collapse
 
zerinoid profile image
Leonardo Zerino

You should at least clean up GPT's responses my dude.

Collapse
 
mamakawama profile image
James Hobbs

ChatGPT slime article. Plus poorly edited. Naughty, naughty.