UNPKG

9.48 kBMarkdownView Raw
1<div align="center">
2 <a href="https://github.com/dvtng/react-loading-skeleton">
3 <img src="assets/logo.svg" alt="Logo" width="80" height="80" />
4 </a>
5 <h1 align="center">React Loading Skeleton</h1>
6 <p align="center">
7 Make beautiful, animated loading skeletons that automatically adapt to your app.
8 </p>
9 <h3>
10 <!--<a href="https://dvtng.github.io/react-loading-skeleton">View Live Demo</a> &nbsp;&nbsp;&bull;&nbsp;&nbsp;-->
11 <a href="https://codesandbox.io/s/react-loading-skeleton-3xwil?file=/src/App.tsx">Open on CodeSandbox</a>
12 </h3>
13 <img src="https://media.giphy.com/media/l0Iyk4bAAjac3AU2k/giphy.gif" alt="Gif of the skeleton in action">
14</div>
15
16Learn about the [changes in version
173](https://github.com/dvtng/react-loading-skeleton/releases/tag/v3.0.0), or view
18the [v2
19documentation](https://github.com/dvtng/react-loading-skeleton/tree/v2#readme).
20
21## Basic Usage
22
23Install via one of:
24
25```bash
26yarn add react-loading-skeleton
27npm install react-loading-skeleton
28```
29
30```tsx
31import Skeleton from 'react-loading-skeleton'
32import 'react-loading-skeleton/dist/skeleton.css'
33
34<Skeleton /> // Simple, single-line loading skeleton
35<Skeleton count={5} /> // Five-line loading skeleton
36```
37
38## Principles
39
40### Adapts to the styles you have defined
41
42The `Skeleton` component should be used directly in your components in place of
43content that is loading. While other libraries require you to meticulously craft
44a skeleton screen that matches the font size, line height, and margins of your
45content, the `Skeleton` component is automatically sized to the correct
46dimensions.
47
48For example:
49
50```tsx
51function BlogPost(props) {
52 return (
53 <div>
54 <h1>{props.title || <Skeleton />}</h1>
55 {props.body || <Skeleton count={10} />}
56 </div>
57 );
58}
59```
60
61...will produce correctly-sized skeletons for the heading and body without any
62further configuration.
63
64This ensures the loading state remains up-to-date with any changes
65to your layout or typography.
66
67### Don't make dedicated skeleton screens
68
69Instead, make components with _built-in_ skeleton states.
70
71This approach is beneficial because:
72
731. It keeps styles in sync.
742. Components should represent all possible states — loading included.
753. It allows for more flexible loading patterns. In the blog post example above,
76 it's possible to have the title load before the body, while having both
77 pieces of content show loading skeletons at the right time.
78
79## Theming
80
81Customize individual skeletons with props, or render a `SkeletonTheme` to style
82all skeletons below it in the React hierarchy:
83
84```tsx
85import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
86
87return (
88 <SkeletonTheme baseColor="#202020" highlightColor="#444">
89 <p>
90 <Skeleton count={3} />
91 </p>
92 </SkeletonTheme>
93);
94```
95
96## Props Reference
97
98### `Skeleton` only
99
100<table>
101 <thead>
102 <tr>
103 <th>Prop</th>
104 <th>Description</th>
105 <th>Default</th>
106 </tr>
107 </thead>
108 <tbody>
109 <tr>
110 <td><code>count?: number</code></td>
111 <td>
112 The number of lines of skeletons to render. If
113 <code>count</code> is a decimal number like 3.5,
114 three full skeletons and one half-width skeleton will be
115 rendered.
116 </td>
117 <td><code>1</code></td>
118 </tr>
119 <tr>
120 <td><code>wrapper?: React.FunctionComponent <br> &lt;PropsWithChildren&lt;unknown&gt;&gt;</code></td>
121 <td>
122 A custom wrapper component that goes around the individual skeleton
123 elements.
124 </td>
125 <td></td>
126 </tr>
127 <tr>
128 <td><code>circle?: boolean</code></td>
129 <td>
130 Makes the skeleton circular by setting <code>border-radius</code> to
131 <code>50%</code>.
132 </td>
133 <td><code>false</code></td>
134 </tr>
135 <tr>
136 <td><code>className?: string</code></td>
137 <td>
138 A custom class name for the individual skeleton elements which is used
139 alongside the default class, <code>react-loading-skeleton</code>.
140 </td>
141 <td></td>
142 </tr>
143 <tr>
144 <td><code>containerClassName?: string</code></td>
145 <td>
146 A custom class name for the <code>&lt;span&gt;</code> that wraps the
147 individual skeleton elements.
148 </td>
149 <td></td>
150 </tr>
151 <tr>
152 <td><code>containerTestId?: string</code></td>
153 <td>
154 A string that is added to the container element as a
155 <code>data-testid</code> attribute. Use it with
156 <code>screen.getByTestId('...')</code> from React Testing Library.
157 </td>
158 <td></td>
159 </tr>
160 <tr>
161 <td><code>style?: React.CSSProperties</code></td>
162 <td>
163 This is an escape hatch for advanced use cases and is not the preferred
164 way to style the skeleton. Props (e.g. <code>width</code>,
165 <code>borderRadius</code>) take priority over this style object.
166 </td>
167 <td></td>
168 </tr>
169 </tbody>
170</table>
171
172### `Skeleton` and `SkeletonTheme`
173
174<table>
175 <thead>
176 <tr>
177 <th>Prop</th>
178 <th>Description</th>
179 <th>Default</th>
180 </tr>
181 </thead>
182 <tbody>
183 <tr>
184 <td><code>baseColor?: string</code></td>
185 <td>The background color of the skeleton.</td>
186 <td><code>#ebebeb</code></td>
187 </tr>
188 <tr>
189 <td><code>highlightColor?: string</code></td>
190 <td>The highlight color in the skeleton animation.</td>
191 <td><code>#f5f5f5</code></td>
192 </tr>
193 <tr>
194 <td><code>width?: string | number</code></td>
195 <td>The width of the skeleton.</td>
196 <td><code>100%</code></td>
197 </tr>
198 <tr>
199 <td><code>height?: string | number</code></td>
200 <td>The height of each skeleton line.</td>
201 <td>The font size</td>
202 </tr>
203 <tr>
204 <td><code>borderRadius?: string | number</code></td>
205 <td>The border radius of the skeleton.</td>
206 <td><code>0.25rem</code></td>
207 </tr>
208 <tr>
209 <td><code>inline?: boolean</code></td>
210 <td>
211 By default, a <code>&lt;br /&gt;</code> is inserted after each skeleton so
212 that each skeleton gets its own line. When <code>inline</code> is true, no
213 line breaks are inserted.
214 </td>
215 <td><code>false</code></td>
216 </tr>
217 <tr>
218 <td><code>duration?: number</code></td>
219 <td>The length of the animation in seconds.</td>
220 <td><code>1.5</code></td>
221 </tr>
222 <tr>
223 <td><code>direction?: 'ltr' | 'rtl'</code></td>
224 <td>
225 The direction of the animation, either left-to-right or right-to-left.
226 </td>
227 <td><code>'ltr'</code></td>
228 </tr>
229 <tr>
230 <td><code>enableAnimation?: boolean</code></td>
231 <td>
232 Whether the animation should play. The skeleton will be a solid color when
233 this is <code>false</code>. You could use this prop to stop the animation
234 if an error occurs.
235 </td>
236 <td><code>true</code></td>
237 </tr>
238 </tbody>
239</table>
240
241## Examples
242
243### Custom Wrapper
244
245There are two ways to wrap a skeleton in a container:
246
247```tsx
248function Box({ children }: PropsWithChildren<unknown>) {
249 return (
250 <div
251 style={{
252 border: '1px solid #ccc',
253 display: 'block',
254 lineHeight: 2,
255 padding: '1rem',
256 marginBottom: '0.5rem',
257 width: 100,
258 }}
259 >
260 {children}
261 </div>
262 );
263}
264
265// Method 1: Use the wrapper prop
266const wrapped1 = <Skeleton wrapper={Box} count={5} />;
267
268// Method 2: Do it "the normal way"
269const wrapped2 = (
270 <Box>
271 <Skeleton />
272 </Box>
273);
274```
275
276## Troubleshooting
277
278### The skeleton width is 0 when the parent has `display: flex`!
279
280In the example below, the width of the skeleton will be 0:
281
282```tsx
283<div style={{ display: 'flex' }}>
284 <Skeleton />
285</div>
286```
287
288This happens because the skeleton has no intrinsic width. You can fix it by
289applying `flex: 1` to the skeleton container via the `containerClassName` prop.
290
291For example, if you are using Tailwind, your code would look like this:
292
293```tsx
294<div style={{ display: 'flex' }}>
295 <Skeleton containerClassName="flex-1" />
296</div>
297```
298
299### The height of my container is off by a few pixels!
300
301In the example below, the height of the `<div>` will be slightly larger than 30
302even though the `react-loading-skeleton` element is exactly 30px.
303
304```tsx
305<div>
306 <Skeleton height={30} />
307</div>
308```
309
310This is a consequence of how `line-height` works in CSS. If you need the `<div>`
311to be exactly 30px tall, set its `line-height` to 1. [See
312here](https://github.com/dvtng/react-loading-skeleton/issues/23#issuecomment-939231878)
313for more details.
314
315## Contributing
316
317Contributions are welcome! See `CONTRIBUTING.md` to get started.
318
319## Acknowledgements
320
321Our logo is based off an image from [Font
322Awesome](https://fontawesome.com/license/free). Thanks!