React Bootstrap Placeholders
React Bootstrap placeholder markup in AdminKit PRO: a loading card with the same layout as the real one, widths, sizes, colors and glow or wave animation.
This component is only available in AdminKit PRO. Learn more.
Placeholders are gray blocks in the shape of text and buttons. Show them while a card or a list waits for its data: the page has its final layout from the start, and nothing jumps when the content arrives.
They are Bootstrap's .placeholder classes in JSX, so there is no component to import. You render a placeholder version of your component while its data is missing, then the real one. Placeholders are part of the PRO version of AdminKit for React.
For charts, maps and plugins, AdminKit uses the Skeleton component instead.
Example
The placeholders demo shows a card next to its loading version, with the same size and layout:
<div className="row">
<div className="col-6">
<div className="card">
<div className="card-body">
<h2 className="card-title">Website redesign</h2>
<p className="card-text">
New landing pages and a lighter checkout, due at the end of the quarter.
</p>
<a href="#" className="btn btn-primary">Open project</a>
</div>
</div>
</div>
<div className="col-6">
<div className="card" aria-hidden="true">
<div className="card-body">
<h2 className="card-title placeholder-glow">
<span className="placeholder col-6" />
</h2>
<p className="card-text placeholder-glow">
<span className="placeholder col-7" />{" "}
<span className="placeholder col-4" />{" "}
<span className="placeholder col-4" />{" "}
<span className="placeholder col-6" />
</p>
<a
href="#"
tabIndex={-1}
className="btn btn-primary disabled placeholder col-6"
aria-disabled="true"
/>
</div>
</div>
</div>
</div>The {" "} between the spans keeps the space that separates them in HTML, so they wrap like words. Empty elements close themselves in JSX: <span className="placeholder col-6" />.
Classes
| Class | Effect |
|---|---|
placeholder | A block in the current text color, at reduced opacity |
col-<n>, w-25 to w-100 | The width; or a style={{ width: "25%" }} object |
placeholder-lg, placeholder-sm, placeholder-xs | The height; by default it follows the font size of the parent |
bg-<color> | Another color than the text color |
placeholder-glow, placeholder-wave | On the parent: a pulsing or a sweeping animation |
On a .btn, placeholder keeps the button's height. Add disabled and tabIndex={-1}, so it cannot be clicked or focused.
While data loads
Write the placeholder version as its own small component, next to the real one. When you change the layout of one, the other is right there to change too:
import { useEffect, useState } from "react";
type Project = { name: string; summary: string };
function ProjectCardPlaceholder() {
return (
<div className="card" aria-hidden="true">
<div className="card-body">
<h2 className="card-title placeholder-glow">
<span className="placeholder col-6" />
</h2>
<p className="card-text placeholder-glow">
<span className="placeholder col-7" /> <span className="placeholder col-4" />
</p>
</div>
</div>
);
}
export function ProjectCard({ id }: { id: string }) {
const [project, setProject] = useState<Project | null>(null);
useEffect(() => {
fetch(`/api/projects/${id}`)
.then((response) => response.json())
.then(setProject);
}, [id]);
return (
<div aria-busy={project === null}>
{project === null ? (
<ProjectCardPlaceholder />
) : (
<div className="card">
<div className="card-body">
<h2 className="card-title">{project.name}</h2>
<p className="card-text">{project.summary}</p>
</div>
</div>
)}
</div>
);
}For a list or a table, render a fixed number of placeholder rows with Array.from({ length: 3 }, (_, index) => ...) and the index as the key, since the rows have no data yet.
Sizes, colors and animation
Set the height with a size class and the color with a bg- class. The animation class goes on the parent:
<>
<p className="placeholder-glow mb-2"><span className="placeholder col-12 placeholder-lg" /></p>
<p className="placeholder-glow mb-2"><span className="placeholder col-12" /></p>
<p className="placeholder-glow mb-2"><span className="placeholder col-12 placeholder-sm bg-primary" /></p>
<p className="placeholder-wave mb-0"><span className="placeholder col-12 placeholder-xs bg-success" /></p>
</>Placeholders or Skeleton
- Use placeholders for content you write in markup: cards, lists, table rows, profile headers. They copy the layout of the real content.
- Use Skeleton (
@/components/ui/skeleton) for content that a library draws in the browser, such as a chart or a map. The plugin wrappers render it themselves until they are ready.
Accessibility
- Hide the placeholder version from screen readers with
aria-hidden="true": its blocks have no text to read. - Mark the region that loads with
aria-busywhile the data is missing, as in the example above. - Placeholder buttons get
tabIndex={-1}andaria-disabled="true", so keyboard users do not land on them.
Related
- Next.js Bootstrap placeholders: the same markup in AdminKit for Next.js
- Bootstrap 5 placeholders: the placeholders of the HTML version
- Placeholders demo: a card next to its loading version, in every theme color
Last updated on
Offcanvas
A React offcanvas component on Bootstrap's markup: a side panel opened from state, four placements, backdrop and scroll options, a responsive sidebar mode.
PopoversPro
A React Bootstrap popover with a title and body: opens on click next to its element, closes on Escape or a click outside, positioned by Floating UI.