Headless UI
Unstyled, fully accessible UI components by Tailwind Labs designed to integrate with Tailwind CSS for React and Vue.
Websites Using Headless UI
No websites detected yet. Analyze a website to contribute data.
What Is Headless UI?
Headless UI is a set of completely unstyled, fully accessible UI components built by Tailwind Labs, the team behind Tailwind CSS, for React and Vue. The short, answer-first definition is this: Headless UI gives you the behavior and accessibility of common interactive patterns, dropdown menus, modals, comboboxes, tabs, toggles, and more, without imposing any visual design at all. You bring the styling, typically with Tailwind CSS utility classes, and Headless UI handles the hard, easy-to-get-wrong parts underneath, like focus management, keyboard navigation, and ARIA semantics.
The word "headless" is the key concept. A traditional component library ships components that come pre-styled with a particular look, which you then have to override if you want something different. A headless library inverts that: it ships the logic and accessibility but no opinions about appearance, so the components render minimal, unstyled markup that you decorate yourself. This is exactly the right model for teams already using Tailwind, who want full control over the visual layer but do not want to reimplement the fiddly accessibility behavior of a custom dropdown or modal from scratch.
Headless UI was created specifically as the interactive-component companion to Tailwind CSS. Tailwind provides utility classes for styling but nothing for behavior; Headless UI fills that gap. Because of that pairing, the two are very frequently found together. Precise, current market-share percentages are difficult to state with confidence, since headless components leave a deliberately minimal footprint and detection methods vary, so treat any single figure cautiously. What is clear qualitatively, and reflected in the Tailwind ecosystem's popularity, is that Headless UI is a widely used choice among Tailwind-based React and Vue projects that need accessible interactive widgets.
It is worth stating what Headless UI is not. It is not a browser extension, not a styled component kit, and not a CSS framework. It is a code-level dependency, the @headlessui/react or @headlessui/vue package, that provides unstyled, accessible components. StackOptic classifies it under UI component libraries, with the important nuance that, being headless, it is one of the harder libraries to detect, precisely because it adds so little to the visible markup.
How Headless UI Works
Headless UI exposes a small, focused set of components that encapsulate interaction logic and accessibility while rendering minimal HTML. You import a component such as Menu, Dialog, Combobox, Listbox, Disclosure, Switch, Tabs, Popover, RadioGroup, or Transition, compose it in your JSX or Vue template, and apply your own classes (usually Tailwind utilities) to its parts. The component manages all the behavior: a Menu handles opening, closing, keyboard navigation, and focus; a Dialog handles focus trapping, scroll locking, and click-outside and escape-key dismissal; a Combobox handles filtering and active-option tracking.
Crucially, the components let you control the rendered structure and styling. Many of them support a render-prop or slot pattern that exposes their internal state (such as whether a menu is open or an option is active/selected), so you can style each state with your own classes. For example, you might render a Menu.Item and apply a Tailwind background utility only when the item is active. The library does not inject a stylesheet or a design system; it injects behavior and the correct accessibility attributes.
Those accessibility attributes are the substance of what Headless UI provides. Components apply the appropriate ARIA roles and properties (for example role="menu", aria-expanded, aria-haspopup, aria-selected, aria-controls) and wire up the relationships between triggers and panels. They manage focus, returning it correctly when a dialog closes, moving it through menu items with the arrow keys, supporting typeahead in listboxes, and so on. This is the part of UI development that is genuinely hard to get right and easy to ship subtly broken, which is why a dedicated, well-tested library is so valuable.
Because Headless UI is unstyled, the surrounding project supplies the look. In the overwhelmingly common case, that styling comes from Tailwind CSS, since both come from the same team and are designed to work together. A developer composes a Headless UI Dialog and decorates it with Tailwind utilities for the overlay, panel, padding, and typography, ending up with a fully accessible modal that looks exactly as the design requires. The Transition component, meanwhile, coordinates enter/leave animations by toggling classes at the right moments, again leaving the actual animation styles to you.
The net effect is a clean division of labor: Headless UI owns behavior and accessibility, your styling layer owns appearance. That separation is powerful for building bespoke interfaces, but it also means the library is intentionally low-profile in the final HTML, which shapes how you detect it.
How to Tell if a Website Uses Headless UI
Detecting Headless UI is harder than detecting a styled component library, and it is important to be honest about that. Because the library is unstyled, it does not add a recognizable headlessui-button-style class to every element the way Ant Design or Chakra do, and the visible classes on the page usually belong to Tailwind, not to Headless UI. Detection therefore relies on a smaller set of more specific signals. StackOptic inspects these from the server side, and you can confirm them by hand, but treat a non-detection as genuinely inconclusive here more than with most libraries.
- Generated
headlessui-IDs. The most reliable tell is the auto-generatedidattributes Headless UI assigns to its components for ARIA wiring. These follow a recognizable pattern such asheadlessui-menu-button-:r1:,headlessui-menu-items-:r2:,headlessui-dialog-:r3:, orheadlessui-listbox-options-.... Seeingidoraria-controls/aria-labelledbyvalues that start withheadlessui-is close to definitive proof of the library. Note that ID formats have varied across versions, but theheadlessui-prefix is the consistent thread. - Data attributes for state. Headless UI components expose interaction state through
data-*attributes you can also style against, for exampledata-headlessui-state(with values likeopen,active,selected,disabled) on rendered elements. Adata-headlessui-stateattribute is a strong, library-specific signal. - ARIA structure around interactive widgets. Even without the prefix, the correct, complete ARIA wiring on a menu or dialog, paired with Tailwind utility classes for styling, is a circumstantial hint, especially on a site you already know uses Tailwind.
- Bundle markers. In the Network tab or bundle, references to
@headlessui/reactor@headlessui/vueconfirm the dependency directly when source maps or unminified chunks are available. - Tailwind pairing. Because Headless UI is the Tailwind team's interactive-component library, it almost always appears alongside Tailwind CSS. Confirming Tailwind first (via its distinctive utility-class patterns) makes a subsequent Headless UI detection much more plausible. See how to tell if a website uses Tailwind CSS for that step.
- React or Vue pairing. Headless UI ships for both React and Vue, so a positive detection should coincide with one of those frameworks. Our guide on how to check if a website uses React, Vue, or Angular covers how to confirm.
Here is how to verify each signal:
| Method | What to do | What Headless UI reveals |
|---|---|---|
| View Source | Open the page and view source | id / aria-controls values beginning headlessui-, if present in server-rendered HTML |
| DevTools Elements | Inspect a dropdown, modal, or tab group | headlessui--prefixed IDs and data-headlessui-state attributes on the parts |
| DevTools (interaction) | Open the menu/dialog and watch attributes | aria-expanded toggling and data-headlessui-state changing to open/active |
| DevTools Network | Filter the bundle for headlessui | @headlessui/react or @headlessui/vue references when chunks are readable |
| Wappalyzer | Run the browser extension on the page | May flag Headless UI, though headless libraries are less reliably detected |
A quick command-line check is curl -s https://example.com | grep -o 'headlessui-[a-z-]*' to surface the prefixed IDs, and grep -o 'data-headlessui-state' to find the state attribute. Be aware of two strong caveats. First, the most distinctive signals (the headlessui- IDs and state attributes) appear on the interactive components, which may only render after a user opens a menu or dialog, so a static fetch can miss them entirely. Second, like other React/Vue libraries, a client-rendered app may ship little initial HTML, so the live page in a browser is often the only reliable place to see these signals. For the broader methodology, see how to find out what technology a website uses and how to check what JavaScript libraries a website uses.
Key Features
- Unstyled, accessible components. A focused set, Combobox, Dialog, Disclosure, Listbox, Menu, Popover, Radio Group, Switch, Tabs, and Transition, that provide behavior and accessibility with zero imposed styling.
- Built-in accessibility. Correct ARIA roles and attributes, focus management, focus trapping, keyboard navigation, typeahead, and dismissal behavior handled automatically.
- State-aware styling. Render-prop and slot APIs plus
data-headlessui-stateattributes let you style each interaction state (open, active, selected, disabled) with your own classes. - React and Vue support. Official packages for both frameworks with consistent behavior and idiomatic APIs.
- Tailwind-first design. Built by the Tailwind team to pair seamlessly with Tailwind CSS, while remaining usable with any styling approach.
- Transition coordination. A
Transitioncomponent that orchestrates enter/leave animation classes at the correct lifecycle moments.
Pros and Cons
Pros
- Total styling freedom: you control every pixel while the library guarantees correct, accessible behavior.
- Excellent, well-tested accessibility for notoriously tricky widgets like menus, dialogs, and comboboxes.
- Tight, first-party integration with Tailwind CSS for teams already in that ecosystem.
- Lightweight and focused, adding behavior rather than a large styled component set or design system.
Cons
- You must do all the styling yourself, so it is slower to a finished look than a pre-styled library and not ideal for teams wanting components that look good out of the box.
- A deliberately small component set, so you will still build or source many UI elements (cards, tables, badges) elsewhere.
- Being headless, it is one of the harder libraries to detect and to recognize in someone else's codebase.
- Best value is realized with Tailwind; without it, you lose some of the intended ergonomic pairing.
Headless UI vs Alternatives
Headless UI competes both with other headless/unstyled libraries and, conceptually, with fully styled component kits. The table positions it.
| Library | Styling | Frameworks | Component breadth | Best for |
|---|---|---|---|---|
| Headless UI | Unstyled (Tailwind-oriented) | React, Vue | Small, focused | Tailwind projects needing accessible interactive widgets |
| Radix UI | Unstyled primitives | React | Broad set of primitives | Custom design systems needing many accessible primitives |
| Chakra UI | Styled (Emotion, style props) | React | Broad | Teams wanting accessible, themeable, pre-styled components |
| Material UI (MUI) | Styled (Emotion, Material) | React | Very broad | Apps wanting Google's Material Design |
| Ant Design | Styled (ant- classes) | React | Very broad, enterprise | Data-dense business apps and dashboards |
The most instructive comparison is Headless UI versus Radix UI, since both are unstyled, accessibility-first libraries. Radix offers a broader catalog of primitives and is React-only, while Headless UI offers a smaller, focused set but supports both React and Vue and is explicitly designed around Tailwind. In the DOM, the two are told apart by their fingerprints: Headless UI leaves headlessui- IDs and data-headlessui-state attributes, whereas Radix leaves data-radix-* and data-state attributes. Against styled libraries like Chakra UI, Material UI, and Ant Design, the trade-off is the headless one: those give you finished, styled components fast, while Headless UI gives you behavior and accessibility and full styling control. For a direct comparison with the other major unstyled option, see Radix UI.
Use Cases
Headless UI is the natural choice for teams already building with Tailwind CSS who need accessible interactive components without abandoning their custom-styling workflow. It lets them add a dropdown, modal, combobox, or tab interface that is fully accessible and keyboard-navigable while styling it entirely with Tailwind utilities, so the result matches their bespoke design system exactly.
It also suits design-system and component-library authors who want to own the visual layer completely but not reinvent accessibility, marketing and product sites in React or Vue that need a few well-behaved interactive widgets, and any project where accessibility is a firm requirement but a pre-packaged look is undesirable. Because it is small and focused, it is often combined with other tools, Tailwind for styling, and sometimes additional component sources for the elements it does not cover.
Consider a few scenarios. A startup whose front end is built entirely with Tailwind might reach for Headless UI the moment it needs an accessible modal or user-menu dropdown, getting correct focus trapping and keyboard support for free while keeping its hand-crafted look. A design-system team building a reusable component library might wrap Headless UI primitives with their own Tailwind-based styling, shipping accessible, on-brand components to the rest of the company. A developer building a polished marketing site might use Headless UI's Transition and Disclosure for animated FAQ accordions styled precisely to the brand.
From a technology-research and lead-generation standpoint, detecting Headless UI is a strong indicator of a Tailwind-centric, modern React or Vue stack built by a team that cares about both custom design and accessibility. Because Headless UI almost always travels with Tailwind, finding one reinforces the other, and together they paint a clear picture of the team's front-end philosophy. For vendors selling to such teams, developer tools, accessibility services, design-system tooling, that context is valuable, even if the headless nature of the library means detection is best done on the live, interacted-with page. Our guide on using tech-stack data to qualify leads explains how to turn these signals into prospects.
Frequently Asked Questions
How can I tell if a website uses Headless UI?
Inspect the interactive components, dropdowns, modals, tab groups, in DevTools and look for auto-generated id and aria-controls/aria-labelledby values beginning with headlessui-, and for data-headlessui-state attributes that change as you open or focus the component. References to @headlessui/react or @headlessui/vue in the bundle confirm it directly. Because Headless UI is unstyled, the visible classes on the page usually belong to Tailwind rather than the library, so the headlessui- prefix and the state attributes are the signals that actually identify it.
Why is Headless UI harder to detect than other component libraries?
Because it is headless: it deliberately adds no styling and no library-branded classes to most elements. A styled library like Ant Design or Chakra UI tags nearly every component with a recognizable class prefix, but Headless UI mostly contributes behavior, ARIA attributes, and a handful of generated IDs. On top of that, its most distinctive signals appear on interactive widgets that may only render once a user opens a menu or dialog, so a static page fetch can miss them. Inspecting the live, interacted-with page is the reliable approach.
Does Headless UI require Tailwind CSS?
No, but it is designed for it. Headless UI provides behavior and accessibility while leaving styling to you, and you can style it with any approach, plain CSS, CSS modules, or another framework. However, it was built by the Tailwind Labs team as the interactive-component companion to Tailwind CSS, and its render-prop/slot APIs and data-headlessui-state attributes pair especially well with Tailwind utilities. In practice the two are very frequently used together, which is why finding one is a strong hint that the other is present.
What is the difference between Headless UI and Radix UI?
Both are unstyled, accessibility-first component libraries, so the core difference is scope and ecosystem. Headless UI offers a small, focused set of components and supports both React and Vue, with a design oriented around Tailwind CSS. Radix UI offers a broader catalog of primitives but is React-only. They also leave different fingerprints: Headless UI shows headlessui- IDs and data-headlessui-state attributes, while Radix shows data-radix-* and data-state attributes. Teams often choose based on framework (Vue support favors Headless UI) and on whether they need Radix's wider primitive set.
Does Headless UI work with both React and Vue?
Yes. Headless UI ships official packages for both React (@headlessui/react) and Vue (@headlessui/vue), with the same accessible components and consistent behavior across both, adapted to each framework's idioms (render props in React, scoped slots in Vue). This dual-framework support is one of its distinguishing features compared with React-only libraries. For detection, a Headless UI site will therefore be a React or Vue application, so confirming one of those frameworks alongside the headlessui- signals gives the most confident result.
Want to identify Headless UI and the rest of a site's stack automatically? Run any URL through StackOptic at https://stackoptic.com.
Alternatives to Headless UI
Compare Headless UI
Analyze a Website
Check if any website uses Headless UI and discover its full technology stack.
Analyze Now