React Bootstrap: Install, Components and Theming Guide
React Bootstrap is a library that rebuilds Bootstrap’s components as React components: <Button>, <Modal>, <Navbar>, <Form>, and the rest. It uses Bootstrap’s own CSS for the look, but replaces Bootstrap’s JavaScript with React code, so modals, dropdowns, and collapses are controlled with props and state instead of data-bs-* attributes. This guide covers installing it in a Vite or Next.js app, the components you will use most, routing, custom themes, dark mode, how it compares with plain Bootstrap and reactstrap, and the problems people hit most often.
The current stable release is React Bootstrap 2.10.10, which targets Bootstrap 5. Version 3 is in beta (3.0.0-beta.6) and requires React 18.3 or newer.
Install React Bootstrap
React Bootstrap doesn’t include any CSS, so install Bootstrap alongside it:
npm install react-bootstrap bootstrap
Then import Bootstrap’s stylesheet once, at the entry point of your app.
Vite or Create React App (src/main.jsx or src/index.js):
import 'bootstrap/dist/css/bootstrap.min.css'
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
Next.js App Router (app/layout.js):
import 'bootstrap/dist/css/bootstrap.min.css'
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Don’t also load bootstrap.bundle.min.js. React Bootstrap does that work itself, and running both makes components open and close twice.
Your first component
import Button from 'react-bootstrap/Button'
export default function App() {
return <Button variant="primary" onClick={() => alert('Saved')}>Save</Button>
}
variant takes the same names as Bootstrap’s classes: primary, secondary, success, danger, outline-primary, link, and so on. size="sm" and size="lg" match btn-sm and btn-lg.
You can import components one by one (import Button from 'react-bootstrap/Button') or together (import { Button, Modal } from 'react-bootstrap'). Both produce small bundles with modern bundlers; the one-by-one form also works best in Next.js server components.
Layout: Container, Row, and Col
import Container from 'react-bootstrap/Container'
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'
<Container>
<Row className="g-4">
<Col md={8}>Main content</Col>
<Col md={4}>Sidebar</Col>
</Row>
</Container>
md={8} becomes col-md-8. The props map directly onto the Bootstrap grid, and <Container fluid> gives a full-width container. For everything else, such as spacing and flex utilities, use className with normal Bootstrap classes; React Bootstrap doesn’t replace them.
A responsive navbar
import Container from 'react-bootstrap/Container'
import Nav from 'react-bootstrap/Nav'
import Navbar from 'react-bootstrap/Navbar'
import NavDropdown from 'react-bootstrap/NavDropdown'
export default function SiteNav() {
return (
<Navbar expand="lg" bg="dark" data-bs-theme="dark" collapseOnSelect>
<Container>
<Navbar.Brand href="/">Acme</Navbar.Brand>
<Navbar.Toggle aria-controls="main-nav" />
<Navbar.Collapse id="main-nav">
<Nav className="ms-auto">
<Nav.Link href="/features">Features</Nav.Link>
<Nav.Link href="/pricing">Pricing</Nav.Link>
<NavDropdown title="Resources" id="resources-menu">
<NavDropdown.Item href="/docs">Docs</NavDropdown.Item>
<NavDropdown.Item href="/blog">Blog</NavDropdown.Item>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
)
}
expand="lg" collapses the menu below the large breakpoint, and collapseOnSelect closes the mobile menu when a link is clicked. data-bs-theme="dark" gives white text on the dark background. The markup it produces is explained in the Bootstrap navbar guide.
A modal controlled by state
import { useState } from 'react'
import Button from 'react-bootstrap/Button'
import Modal from 'react-bootstrap/Modal'
export default function DeleteButton() {
const [show, setShow] = useState(false)
return (
<>
<Button variant="danger" onClick={() => setShow(true)}>Delete project</Button>
<Modal show={show} onHide={() => setShow(false)} centered>
<Modal.Header closeButton>
<Modal.Title>Delete this project?</Modal.Title>
</Modal.Header>
<Modal.Body>This can't be undone.</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={() => setShow(false)}>Cancel</Button>
<Button variant="danger" onClick={() => setShow(false)}>Delete</Button>
</Modal.Footer>
</Modal>
</>
)
}
show decides whether the modal is open, and onHide runs when someone clicks the backdrop, presses Escape, or clicks the close button. Other props match Bootstrap’s classes: size="lg", fullscreen="md-down", scrollable, and backdrop="static". The Bootstrap modal guide explains each option.
Forms
import { useState } from 'react'
import Button from 'react-bootstrap/Button'
import Form from 'react-bootstrap/Form'
export default function SignupForm() {
const [validated, setValidated] = useState(false)
function handleSubmit(event) {
const form = event.currentTarget
event.preventDefault()
if (form.checkValidity()) {
// send the data
}
setValidated(true)
}
return (
<Form noValidate validated={validated} onSubmit={handleSubmit}>
<Form.Group className="mb-3" controlId="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" required />
<Form.Control.Feedback type="invalid">Enter a valid email.</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-3" controlId="plan">
<Form.Label>Plan</Form.Label>
<Form.Select>
<option value="free">Free</option>
<option value="pro">Pro</option>
</Form.Select>
</Form.Group>
<Form.Check className="mb-3" type="switch" id="updates" label="Email me product updates" />
<Button type="submit">Create account</Button>
</Form>
)
}
controlId on Form.Group sets the id of the input and the for of the label, so they are linked without writing either. validated adds Bootstrap’s was-validated class. The underlying classes are covered in the Bootstrap forms guide, the select guide, and the checkbox and switch guide.
Tooltips and toasts
import { useState } from 'react'
import Button from 'react-bootstrap/Button'
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
import Toast from 'react-bootstrap/Toast'
import ToastContainer from 'react-bootstrap/ToastContainer'
import Tooltip from 'react-bootstrap/Tooltip'
export default function Toolbar() {
const [saved, setSaved] = useState(false)
return (
<>
<OverlayTrigger placement="top" overlay={<Tooltip id="save-tip">Save changes</Tooltip>}>
<Button aria-label="Save" onClick={() => setSaved(true)}>Save</Button>
</OverlayTrigger>
<ToastContainer position="bottom-end" className="p-3">
<Toast show={saved} onClose={() => setSaved(false)} delay={4000} autohide bg="success">
<Toast.Body className="text-white">Changes saved.</Toast.Body>
</Toast>
</ToastContainer>
</>
)
}
Unlike plain Bootstrap, tooltips need no initialization code: OverlayTrigger handles it. ToastContainer positions toasts with values such as top-end, bottom-center, and middle-center.
Links with React Router or Next.js
Components that render links accept an as prop, so your router’s link component can do the navigation:
import { Link } from 'react-router-dom' // or: import Link from 'next/link'
import Nav from 'react-bootstrap/Nav'
<Nav.Link as={Link} to="/pricing">Pricing</Nav.Link> {/* React Router */}
<Nav.Link as={Link} href="/pricing">Pricing</Nav.Link> {/* Next.js */}
This keeps Bootstrap’s styling while avoiding full page reloads.
Using React Bootstrap with Next.js
React Bootstrap’s components are marked as client components, so you can use them inside server components. Two things to know:
- Anything with state needs your own client component. A modal opened with
useStatemust live in a file that starts with'use client', like the examples above. - Dot syntax can fail in server components. In a server component,
Navbar.Brandmay throw an error about client modules. Import the part directly instead:import NavbarBrand from 'react-bootstrap/NavbarBrand', or put the whole navbar in a client component.
Custom themes
The CSS import loads stock Bootstrap. To change the colors, fonts, and spacing, compile your own Bootstrap with Sass instead:
npm install sass
// src/styles/custom.scss
$primary: #2f55ff;
$border-radius: .75rem;
$font-family-sans-serif: "Inter", system-ui, sans-serif;
@import "bootstrap/scss/bootstrap";
Replace the CSS import with import './styles/custom.scss'. Every React Bootstrap component picks up the new theme, because they all use Bootstrap’s classes. How the variables work is explained in Bootstrap Sass variables explained and how to customize Bootstrap 5 colors. If you’d rather design the theme visually, build it in the bootstrap.build editor and export the Sass or compiled CSS into your project.
Dark mode
React Bootstrap follows Bootstrap’s color modes. Set data-bs-theme="dark" on <html> for the whole app, or on a single component:
useEffect(() => {
document.documentElement.setAttribute('data-bs-theme', isDark ? 'dark' : 'light')
}, [isDark])
The Bootstrap dark mode guide covers following the system setting and remembering the choice.
React Bootstrap, reactstrap, or plain Bootstrap?
| React Bootstrap | reactstrap | Bootstrap classes in JSX | |
|---|---|---|---|
| Latest version | 2.10.10 (3.0 in beta) | 9.2.3 | Bootstrap 5.3.9 |
| Interactive components | Rewritten in React | Rewritten in React | Bootstrap’s own JavaScript |
| Accessibility handled | Yes, by the library | Yes, by the library | Yes, by Bootstrap’s JavaScript |
| Best for | Most React apps | Existing reactstrap projects | Simple pages, static sites |
React Bootstrap is the most widely used of the three, with about 1.6 million weekly npm downloads in November 2026 against about 540,000 for reactstrap, and it is still getting new releases. reactstrap works, but its last release was in 2024. Writing plain className="btn btn-primary" is fine for static markup, but for modals, dropdowns, and tooltips you would have to call Bootstrap’s JavaScript from useEffect and clean it up yourself, which React Bootstrap does for you. For a wider comparison with a utility-first framework, see Bootstrap vs Tailwind. For Vue projects, the equivalent library is BootstrapVueNext.
Common problems
Components have no styles. The Bootstrap CSS isn’t imported. Add import 'bootstrap/dist/css/bootstrap.min.css' at your app’s entry point.
Dropdowns or modals open and close immediately. Bootstrap’s JavaScript is loaded too, from a script tag or an import 'bootstrap'. Remove it.
The mobile menu doesn’t open. Navbar.Toggle and Navbar.Collapse must be inside the same Navbar, and the toggle’s aria-controls should match the collapse’s id.
Copied examples use bsStyle or componentClass. Those props are from the Bootstrap 3 version of React Bootstrap. Use variant and as.
A Next.js error mentions client modules. You used a compound name such as Navbar.Brand or a hook in a server component. Import the sub-component directly, or add 'use client' to the file.
FAQ
What is React Bootstrap?
React Bootstrap is a library of React components, such as Button, Modal, Navbar, and Form, that render Bootstrap’s markup and classes. It replaces Bootstrap’s JavaScript with React code, so interactive components are controlled with props and state. It needs Bootstrap’s CSS to be installed and imported.
How do I install React Bootstrap?
Run npm install react-bootstrap bootstrap, then add import 'bootstrap/dist/css/bootstrap.min.css' once at your app’s entry point, such as src/main.jsx or app/layout.js. Import components with import Button from 'react-bootstrap/Button'.
Which version of Bootstrap does React Bootstrap use?
React Bootstrap 2.x, the current stable line (2.10.10), targets Bootstrap 5, and works with the latest Bootstrap 5.3 CSS. Older lines exist for Bootstrap 4 (1.6.x) and Bootstrap 3 (0.33.x).
Should I use React Bootstrap or reactstrap?
For new projects, React Bootstrap: it is more widely used and still releasing updates, while reactstrap’s last release was in 2024. Both render Bootstrap’s classes, so the look is the same.
Does React Bootstrap work with Next.js?
Yes. Import Bootstrap’s CSS in app/layout.js, and put components that use state, such as modals, in files marked 'use client'. In server components, import sub-components directly, for example react-bootstrap/NavbarBrand, instead of using Navbar.Brand.
Try it in the builder
Make these changes visually with a live preview, then export clean Bootstrap Sass or CSS.
Open the Builder