Styling and UI Libraries
|
This section documents React 19.x for the web, using function components and Hooks throughout (class components appear only where React still requires them, such as error boundaries). React Native is out of scope and gets only a pointer. The React 19 additions follow the current official React documentation. This content was generated with the assistance of AI and should be verified against react.dev before being relied on in production, since React APIs continue to evolve between releases. This section’s bibliography lists the reference material consulted while preparing these pages. |
React does not have an opinion on styling — any approach that produces class names or style rules works. This page surveys the common options and the main component libraries.
Styling options
-
Plain CSS / CSS Modules. Import a stylesheet, or a
*.module.cssfile whose class names are locally scoped and hashed:import styles from './Card.module.css'; export function Card() { return <div className={styles.card}>…</div>; }Zero runtime, works everywhere including Server Components. See HTML & CSS Reference and, for a preprocessor, Sass Reference.
-
Tailwind CSS. Utility classes in
className; styling stays in the markup and the build strips unused classes.<button className="rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700">Save</button> -
CSS-in-JS (styled-components, Emotion). Write styles as tagged template literals colocated with the component. Note the runtime cost (styles are generated in the browser) and that a styled component is a Client Component — it needs
'use client'and cannot be used directly in a Server Component. -
vanilla-extract. CSS-in-TypeScript that compiles to static
.cssfiles at build — type safety with no runtime. -
Inline
style. A camelCased object; fine for one-off dynamic values (style={{ width: pct + '%' }}), not for whole design systems (no media queries, no pseudo-classes).
Component libraries
Each ships ready-made, accessible components so you are not rebuilding dialogs, menus and data tables by hand. Most provide a theme (design tokens for color, spacing, typography, dark mode) applied via a provider at the app root, plus responsive-layout primitives. The usual flow is: install the package, wrap the app in the library’s provider (where it has one), then use its components.
-
MUI — a large Material Design implementation with a powerful theming system (
ThemeProvider+createTheme) and companion packages for icons, data grids and date pickers.import { Button } from '@mui/material'; <Button variant="contained" onClick={save}>Save</Button> -
Ant Design — a comprehensive, enterprise-oriented set (rich
Form,Table,DatePicker); theming via aConfigProviderand design tokens.import { Button } from 'antd'; <Button type="primary" onClick={save}>Save</Button> -
Chakra UI — a style-props API with accessible defaults: you pass style and layout as props rather than writing separate CSS.
import { Button } from '@chakra-ui/react'; <Button colorScheme="blue" px={4} onClick={save}>Save</Button> -
PrimeReact — a very large suite (~90 components including
DataTable, charts and pickers) with several ready-made themes switched via a CSS import or thePrimeReactProvider.import { Button } from 'primereact/button'; <Button label="Save" icon="pi pi-check" onClick={save} /> -
gluestack UI — a fully open-source, copy-in library (universal React and React Native) built on utility styling:
npx gluestack-ui add buttondrops the component source into your project, so you own and can edit it. Wrap the app inGluestackUIProvider.import { Button, ButtonText } from '@/components/ui/button'; <Button onPress={save}><ButtonText>Save</ButtonText></Button> -
Radix Primitives — unstyled, accessible behavior primitives (dialog, menu, popover, tabs) that ship the interaction and ARIA wiring and leave all styling to you. shadcn/ui is a popular set of Tailwind-styled components built on Radix that you copy into your project rather than install as a dependency.
import * as Dialog from '@radix-ui/react-dialog'; <Dialog.Root> <Dialog.Trigger>Open</Dialog.Trigger> <Dialog.Portal> <Dialog.Overlay className="overlay" /> <Dialog.Content className="modal"> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Close>Cancel</Dialog.Close> </Dialog.Content> </Dialog.Portal> </Dialog.Root>
Accessibility
A component library gives you accessible primitives, but you still own the wiring: label every control,
manage focus in dialogs and menus, respect prefers-reduced-motion, and test with a keyboard and a screen
reader. useId generates stable ids to connect a label, a field, and its aria-describedby error text:
function Field({ label, error }) {
const id = useId();
return (
<>
<label htmlFor={id}>{label}</label>
<input id={id} aria-invalid={!!error} aria-describedby={error ? `${id}-err` : undefined} />
{error && <p id={`${id}-err`} role="alert">{error}</p>}
</>
);
}
See Web Accessibility for the conformance levels and validation tools.