Implementing Carbon Design System Skeletons in React: A Practical Guide
Learn how to add Carbon Design System Skeleton components to your React app, set up loading states, customize appearance with CSS variables, validate rendering, and handle common pitfalls.
16 Jul 2025, 19:58 UTC

Desired Outcome
Render a lightweight, animated placeholder that matches the shape of your content while data is being fetched, preserving layout stability and improving perceived performance.
Prerequisites
- Node.js 18+ and npm or yarn.
- React 18+ application (create‑react‑app, Next.js, or similar).
- Carbon Design System v11 or newer:
npm i @carbon/react @carbon/icons-react(peer dependencies are bundled). - Basic understanding of CSS custom properties (variables).
Step‑by‑Step Usage
- Install Carbon
# From your project root npm install @carbon/react @carbon/icons-react # or yarn add @carbon/react @carbon/icons-react - Import Skeleton components
import { Skeleton, SkeletonText } from '@carbon/react'; - Create a loading wrapper
function UserProfile({ userId }) { const [loading, setLoading] = React.useState(true); const [user, setUser] = React.useState(null); React.useEffect(() => { fetchUser(userId).then(data => { setUser(data); setLoading(false); }); }, [userId]); return ( <div> {loading ? ( <div style={{ width: '200px', height: '100px' }}> <SkeletonText width="80%"/> <Skeleton width="100%" height="20px"/> </div> ) : ( <UserCard user={user} /> )} </div> ); }Use
SkeletonTextfor text lines andSkeletonfor generic blocks. The inlinestyledefines the placeholder’s dimensions, preventing collapse. - Customize with CSS variables
/* In your global CSS or a module */ :root { --skeleton-bg: #e0e0e0; /* Base color */ --skeleton-wave: #c6c6c6; /* Gradient overlay */ --skeleton-animation-duration: 1.2s; }These variables automatically apply to all
<Skeleton>instances. If you need component‑specific overrides, target the class name.bx--skeletonor useclassNameprops.
Validation Checks
- Open dev tools and inspect the rendered
<div class="bx--skeleton">. Verify thebackgroundandanimationstyles match your CSS variables. - Toggle the
loadingflag in the component state. Whenloadingis true, the skeleton should occupy the same space as the final content. - Confirm that disabling
loadingremoves the skeleton and displays the real content without residual artifacts or layout shift. - Check the network panel to ensure the skeleton appears immediately while the fetch request is pending.
Fallback & Recovery
- Collapsed Skeleton: If the placeholder collapses, ensure
widthandheightare set either inline or via CSS. Carbon’s skeleton defaults to1emif omitted. - Missing CSS Variables: Older browsers may ignore CSS custom properties. Provide fallback values directly in the component, e.g.,
<Skeleton style={{ '--skeleton-bg': '#e0e0e0' }} />. - Version Mismatch: Carbon v11+ uses the new
SkeletonAPI. If you’re on v10 or older, import from@carbon/react/lib/Skeletonbut note that the API differs slightly. - Bundle Size: Skeleton is a pure CSS component; no extra JavaScript is added. If you’re concerned about CSS bloat, import only the
@carbon/react/lib/Skeletonmodule and its styles.
Practical Example: Skeleton in a Paginated Table
Below is a minimal example that shows how to use skeletons while a paginated table loads each page.
function PaginatedTable({ page }) {
const [loading, setLoading] = React.useState(true);
const [data, setData] = React.useState([]);
React.useEffect(() => {
setLoading(true);
fetchPage(page).then(rows => {
setData(rows);
setLoading(false);
});
}, [page]);
return (
<table className="bx--data-table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{loading
? Array.from({ length: 5 })
.map((_, i) => (
<tr key={i}>
<td><Skeleton width="30%"/></td>
<td><SkeletonText width="80%"/></td>
</tr>
))
: data.map(row => (
<tr key={row.id}>
<td>{row.id}</td>
<td>{row.name}</td>
</tr>
))}
</tbody>
</table>
);
}
This example reserves five rows of skeleton placeholders, matching the table’s layout and preventing content shift when the next page loads.
Limitations & Notes
- Carbon Skeleton relies on the
@carbon/reactpeer dependencies. Ensure React and React‑DOM versions are compatible (React 18+). - Custom shapes beyond text, button, and avatar require manual CSS or the
Skeletoncomponent withwidth/heightprops. - Animations may be disabled in users’ browsers for accessibility. Carbon respects the
prefers-reduced-motionmedia query; you can override with--skeleton-waveif needed. - While the skeleton itself is lightweight, over‑using it on large pages can give the illusion of slowness. Use sparingly and target truly asynchronous sections.
Conclusion
By following this guide, you can seamlessly integrate Carbon Design System’s Skeleton component into any React application, delivering smooth loading experiences while keeping bundle size minimal and layout stable.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.