- No data uploaded
- Instant results
Bootstrap 5 Login Modal for React
A production-ready minimal login modal: a centered sign-in dialog with email and password fields, “remember me”, a forgot-password link and a social sign-in button. Pick your brand color, toggle dark mode and corner radius — the live preview and the React code update instantly in your browser.
Live component editor
import 'bootstrap/dist/css/bootstrap.min.css';
import './theme.css';
import { useState } from 'react';
export default function LoginModal() {
const [open, setOpen] = useState(true);
return (
<div>
<button type="button" className="btn btn-brand fw-semibold rounded-2" onClick={() => setOpen(true)}>Sign in</button>
<div hidden={!open}>
<div className="position-fixed top-0 start-0 w-100 h-100 z-3 d-flex align-items-center justify-content-center p-3 overlay" role="dialog" aria-modal="true" aria-labelledby="login-title">
<div className="position-relative w-100 mw-md p-5 bg-body border shadow-sm rounded-3">
<button type="button" className="position-absolute top-0 end-0 m-2 btn btn-sm btn-link link-secondary text-decoration-none" aria-label="Close" onClick={() => setOpen(false)}>×</button>
<h2 id="login-title" className="fs-4 fw-bold mb-1 text-body-emphasis">Welcome back</h2>
<p className="small mb-4 text-body-secondary">Sign in to continue to your dashboard.</p>
<form className="d-flex flex-column gap-3">
<div>
<label htmlFor="login-email" className="form-label small fw-medium">Email</label>
<input id="login-email" type="email" autoComplete="email" placeholder="you@company.com" className="form-control rounded-2" required />
</div>
<div>
<div className="d-flex align-items-center justify-content-between">
<label htmlFor="login-password" className="form-label small fw-medium">Password</label>
<a href="#" className="small text-brand fw-medium text-decoration-none">Forgot?</a>
</div>
<input id="login-password" type="password" autoComplete="current-password" placeholder="••••••••" className="form-control rounded-2" required />
</div>
<label className="d-flex align-items-center gap-2 small text-body">
<input type="checkbox" className="form-check-input mt-0" /> Remember me for 30 days
</label>
<button type="submit" className="btn btn-brand fw-semibold rounded-2 w-100">Sign in</button>
</form>
<div className="d-flex align-items-center gap-2 my-4">
<span className="flex-fill border-top"></span>
<span className="small text-uppercase text-body-secondary">or</span>
<span className="flex-fill border-top"></span>
</div>
<button type="button" className="btn btn-outline-secondary fw-semibold rounded-2 w-100">Continue with Google</button>
<p className="mt-4 text-center small text-body-secondary">No account? <a href="#" className="text-brand fw-medium text-decoration-none">Create one</a></p>
</div>
</div>
</div>
</div>
);
}
/* theme.css — brand color #4f46e5 for Bootstrap 5.3 */
:root { --brand: #4f46e5; --brand-hover: #433cc3; --brand-rgb: 79, 70, 229; --brand-contrast: #ffffff; }
.btn-brand {
--bs-btn-color: var(--brand-contrast); --bs-btn-bg: var(--brand); --bs-btn-border-color: var(--brand);
--bs-btn-hover-color: var(--brand-contrast); --bs-btn-hover-bg: var(--brand-hover); --bs-btn-hover-border-color: var(--brand-hover);
--bs-btn-active-color: var(--brand-contrast); --bs-btn-active-bg: var(--brand-hover); --bs-btn-active-border-color: var(--brand-hover);
--bs-btn-focus-shadow-rgb: var(--brand-rgb);
}
.text-brand { color: var(--brand) !important; }
.border-brand { border: 2px solid var(--brand) !important; }
.bg-brand-subtle { background-color: rgba(var(--brand-rgb), .12) !important; }
.form-control:focus, .form-check-input:focus { border-color: var(--brand); box-shadow: 0 0 0 .25rem rgba(var(--brand-rgb), .25); }
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }
.overlay { background: rgba(15, 23, 42, .5); backdrop-filter: blur(4px); z-index: 1050; }
.choice[aria-pressed="true"] { border-color: var(--brand) !important; color: var(--brand) !important; box-shadow: 0 0 0 .2rem rgba(var(--brand-rgb), .2); }
.mw-sm { max-width: 24rem; } .mw-md { max-width: 28rem; } .mw-lg { max-width: 32rem; } .mw-xl { max-width: 36rem; }
.mw-2xl { max-width: 42rem; } .mw-4xl { max-width: 56rem; } .mw-6xl { max-width: 72rem; }
More Bootstrap components for React
All components →- Signup Form A registration card with name, email and password fields, a password hint, a terms-of-service checkbox and a primary call to action
- Navbar A responsive top navigation bar with a logo, primary links, a sign-in/CTA pair on desktop and a collapsible hamburger menu on mobile
- Cookie Consent Banner A GDPR-style cookie banner with equally prominent “Accept all” and “Reject all”, granular analytics/marketing toggles (off by default), stored consent and Google Consent Mode v2 signals
- Contact Form A contact card with name, email, a topic selector, a message textarea and a submit button
- Footer A multi-column site footer with a brand description, three link groups, a newsletter sign-up field and a copyright row
- Pricing Table A three-tier pricing section with a monthly/yearly billing toggle, a highlighted “most popular” plan and feature checklists
- Hero Section A landing-page hero with an announcement badge, a large headline, supporting copy, primary and secondary calls to action and a row of social-proof stats
- Feature Grid A marketing section with a centered heading and a responsive grid of six feature cards, each with an icon badge, title and description
Install Bootstrap 5 for React
Create a React project with Vite and install Bootstrap:
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm install bootstrapSave the generated theme.css next to the component; the component file already imports bootstrap/dist/css/bootstrap.min.css and ./theme.css. No Bootstrap JavaScript is required — interactivity uses useState.
Use the login modal in React
// App.jsx
import LoginModal from './LoginModal';
export default function App() {
return <LoginModal />;
}Accessibility & customization
The dialog uses role="dialog", aria-modal="true" and aria-labelledby pointing at its title. Every field has a visible <label>, the close button has an aria-label, and inputs use the correct autocomplete tokens so password managers work.
Every color, radius and dark-mode choice is baked into plain Bootstrap classes plus a tiny CSS-variable theme file, so the copied code has no runtime dependency on this site.
Compatibility
| Item | Details |
|---|---|
| CSS framework | Bootstrap 5.3+ (CSS only) |
| Library | React 18+ (function component) |
| Interactive state | open |
| Dark mode | Yes — toggle in the editor |
| Style | Minimal |