headlessui
Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
Top Related Projects
A rugged, minimal framework for composing JavaScript behavior in your markup.
This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
The library for web and native user interfaces.
⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
Cybernetically enhanced web apps
Lit is a simple library for building fast, lightweight web components.
Quick Overview
Headless UI is a set of completely unstyled, fully accessible UI components for React, Vue, and Alpine.js. It provides the functionality and accessibility of common UI elements without any pre-defined styles, allowing developers to implement their own custom designs easily.
Pros
- Fully accessible components out of the box
- Framework-agnostic, supporting React, Vue, and Alpine.js
- Highly customizable with no pre-defined styles
- Lightweight and focused on core functionality
Cons
- Requires more initial setup and styling compared to pre-styled component libraries
- Limited number of components compared to some other UI libraries
- Learning curve for developers used to pre-styled components
- May require additional effort to ensure consistent styling across projects
Code Examples
- Using a Headless UI Dropdown in React:
import { Menu } from '@headlessui/react'
function MyDropdown() {
return (
<Menu>
<Menu.Button>Options</Menu.Button>
<Menu.Items>
<Menu.Item>
{({ active }) => (
<a
className={`${active && 'bg-blue-500'}`}
href="/account-settings"
>
Account settings
</a>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<a
className={`${active && 'bg-blue-500'}`}
href="/logout"
>
Logout
</a>
)}
</Menu.Item>
</Menu.Items>
</Menu>
)
}
- Using a Headless UI Dialog (Modal) in Vue:
<template>
<Dialog :open="isOpen" @close="closeModal">
<DialogPanel>
<DialogTitle>Deactivate account</DialogTitle>
<DialogDescription>
Are you sure you want to deactivate your account? All of your data will be permanently removed.
</DialogDescription>
<button @click="closeModal">Cancel</button>
<button @click="deactivateAccount">Deactivate</button>
</DialogPanel>
</Dialog>
</template>
<script>
import { ref } from 'vue'
import { Dialog, DialogPanel, DialogTitle, DialogDescription } from '@headlessui/vue'
export default {
components: { Dialog, DialogPanel, DialogTitle, DialogDescription },
setup() {
const isOpen = ref(false)
// ... rest of the component logic
}
}
</script>
- Using a Headless UI Switch in Alpine.js:
<div x-data="{ enabled: false }">
<Switch
x-model="enabled"
:class="enabled ? 'bg-blue-600' : 'bg-gray-200'"
class="relative inline-flex h-6 w-11 items-center rounded-full"
>
<span class="sr-only">Enable notifications</span>
<span
:class="enabled ? 'translate-x-6' : 'translate-x-1'"
class="inline-block h-4 w-4 transform rounded-full bg-white transition"
/>
</Switch>
</div>
Getting Started
To get started with Headless UI, first install the package for your framework:
For React:
npm install @headlessui/react
For Vue:
npm install @headlessui/vue
For Alpine.js:
npm install @headlessui/alpine
Then, import and use the components in your project as shown in the code examples above. Remember to style the components according to your design requirements.
Competitor Comparisons
A rugged, minimal framework for composing JavaScript behavior in your markup.
Pros of Alpine
- Lightweight and minimal, with a smaller learning curve
- Can be used without a build step, making it easier to integrate into existing projects
- More flexible and can be used for a wider range of UI interactions beyond just components
Cons of Alpine
- Less structured approach to building complex UI components
- Lacks built-in accessibility features and ARIA support
- May require more manual work for consistent styling across components
Code Comparison
Alpine:
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open">Content</div>
</div>
Headless UI:
import { Disclosure } from '@headlessui/react'
function MyDisclosure() {
return (
<Disclosure>
<Disclosure.Button>Toggle</Disclosure.Button>
<Disclosure.Panel>Content</Disclosure.Panel>
</Disclosure>
)
}
Summary
Alpine is a lightweight JavaScript framework for adding interactivity to web pages, while Headless UI is a set of unstyled, fully accessible UI components. Alpine offers more flexibility and ease of integration, but Headless UI provides a more structured approach to building complex, accessible components. The choice between them depends on project requirements, team expertise, and the desired level of control over component behavior and accessibility.
This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
Pros of Vue
- Full-featured framework with comprehensive ecosystem
- Gentle learning curve and excellent documentation
- Flexible and scalable for both small and large applications
Cons of Vue
- Larger bundle size compared to Headless UI
- More opinionated structure, potentially less flexibility for UI components
- May be overkill for projects only needing basic UI components
Code Comparison
Vue component example:
<template>
<button @click="count++">Count is: {{ count }}</button>
</template>
<script>
export default {
data() {
return { count: 0 }
}
}
</script>
Headless UI component example:
import { useState } from 'react'
import { Menu } from '@headlessui/react'
function MyDropdown() {
return (
<Menu>
<Menu.Button>Options</Menu.Button>
<Menu.Items>
<Menu.Item>
{({ active }) => (
<a className={`${active && 'bg-blue-500'}`} href="/account">
Account
</a>
)}
</Menu.Item>
</Menu.Items>
</Menu>
)
}
Vue provides a more complete framework with built-in state management and templating, while Headless UI focuses on providing unstyled, accessible UI components that can be easily customized.
The library for web and native user interfaces.
Pros of React
- Larger ecosystem and community support
- More comprehensive, handling entire UI development
- Wider range of use cases and applications
Cons of React
- Steeper learning curve for beginners
- Heavier bundle size, potentially impacting performance
- More opinionated about overall application structure
Code Comparison
React component:
function Button({ onClick, children }) {
return <button onClick={onClick}>{children}</button>;
}
Headless UI component:
import { Button } from '@headlessui/react'
function MyButton({ onClick, children }) {
return (
<Button onClick={onClick}>
{children}
</Button>
)
}
Key Differences
- React is a full-fledged UI library, while Headless UI focuses on unstyled, accessible components
- Headless UI is built on top of React, providing a more specialized toolset
- React requires more setup and configuration, whereas Headless UI offers ready-to-use components
- Headless UI emphasizes accessibility and customization, while React provides a broader foundation
Use Cases
- Choose React for building complex, full-scale applications
- Opt for Headless UI when prioritizing accessibility and design flexibility in React projects
⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
Pros of Preact
- Smaller bundle size and faster performance
- Compatible with React ecosystem
- Simpler API and easier learning curve
Cons of Preact
- Less extensive component library compared to Headless UI
- Fewer accessibility features out-of-the-box
- May require additional setup for advanced React features
Code Comparison
Preact:
import { h, render } from 'preact';
const App = () => <h1>Hello, World!</h1>;
render(<App />, document.body);
Headless UI:
import { Menu } from '@headlessui/react'
function MyDropdown() {
return (
<Menu>
<Menu.Button>Options</Menu.Button>
<Menu.Items>
<Menu.Item>
{({ active }) => (
<a className={`${active && 'bg-blue-500'}`} href="/account">
Account
</a>
)}
</Menu.Item>
</Menu.Items>
</Menu>
)
}
Preact focuses on providing a lightweight alternative to React with a similar API, while Headless UI offers unstyled, fully accessible UI components. Preact is ideal for projects prioritizing performance and small bundle sizes, whereas Headless UI is better suited for applications requiring robust, accessible UI components with full styling control.
Cybernetically enhanced web apps
Pros of Svelte
- Offers a complete framework for building web applications, not just UI components
- Compiles to highly efficient vanilla JavaScript, resulting in smaller bundle sizes
- Provides a simpler, more intuitive syntax with less boilerplate code
Cons of Svelte
- Smaller ecosystem and community compared to React-based solutions like Headless UI
- Less flexibility in terms of integration with other libraries or frameworks
- Steeper learning curve for developers already familiar with React or Vue
Code Comparison
Svelte component:
<script>
export let name = 'World';
</script>
<h1>Hello {name}!</h1>
Headless UI component (React):
import { Menu } from '@headlessui/react'
function MyDropdown() {
return (
<Menu>
<Menu.Button>Options</Menu.Button>
<Menu.Items>
<Menu.Item>
{({ active }) => (
<a className={`${active && 'bg-blue-500'}`} href="/account-settings">
Account settings
</a>
)}
</Menu.Item>
</Menu.Items>
</Menu>
)
}
The code comparison showcases Svelte's simplicity in component creation, while Headless UI demonstrates its focus on providing accessible, unstyled components for React applications.
Lit is a simple library for building fast, lightweight web components.
Pros of Lit
- Framework-agnostic: Works with any frontend framework or vanilla JavaScript
- Lightweight and fast: Smaller bundle size and better performance
- Web Components: Creates reusable custom elements that work across different frameworks
Cons of Lit
- Less opinionated: Requires more setup and configuration for complex UI components
- Smaller ecosystem: Fewer pre-built components and community resources compared to Headless UI
Code Comparison
Headless UI (React):
import { Menu } from '@headlessui/react'
function MyDropdown() {
return (
<Menu>
<Menu.Button>Options</Menu.Button>
<Menu.Items>
<Menu.Item>
{({ active }) => (
<a className={`${active && 'bg-blue-500'}`} href="/account">
Account
</a>
)}
</Menu.Item>
</Menu.Items>
</Menu>
)
}
Lit:
import { LitElement, html } from 'lit'
class MyDropdown extends LitElement {
render() {
return html`
<button @click=${this._toggleMenu}>Options</button>
<ul ?hidden=${!this.menuOpen}>
<li><a href="/account">Account</a></li>
</ul>
`
}
}
customElements.define('my-dropdown', MyDropdown)
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Headless UI
A set of completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
Documentation
For full documentation, visit headlessui.com.
Installing the latest version
You can install the latest version by using:
npm install @headlessui/react@latest
npm install @headlessui/vue@latest
Installing the insiders version
You can install the insiders version (which points to whatever the latest commit on the main
branch is) by using:
npm install @headlessui/react@insiders
npm install @headlessui/vue@insiders
Note: The insiders build doesn't follow semver and therefore doesn't guarantee that the APIs will be the same once they are released.
Packages
Name | Version | Downloads |
---|---|---|
@headlessui/react | ||
@headlessui/vue | ||
@headlessui/tailwindcss |
Community
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
For casual chit-chat with others using the library:
Join the Tailwind CSS Discord Server
Contributing
If you're interested in contributing to Headless UI, please read our contributing docs before submitting a pull request.
Top Related Projects
A rugged, minimal framework for composing JavaScript behavior in your markup.
This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
The library for web and native user interfaces.
⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
Cybernetically enhanced web apps
Lit is a simple library for building fast, lightweight web components.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot