---
title: "More: skeleton"
description: A shimmering placeholder over an element while it loads, revealed in place when loading ends.
---

`Modifier.kapowSkeleton` covers an element with a placeholder while `loading` is true, then fades the placeholder away to reveal the content. The content is measured and placed the whole time, so nothing moves when the data arrives. Lay out the real composables with dummy data and they become the shape of the skeleton.

## Usage

The sample covers an avatar and a name while a profile loads.

```kotlin
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.unit.dp
import com.jantursky.kapow.kapowSkeleton

@Composable
fun ProfileRow(avatar: Painter, name: String, loading: Boolean) {
    Row {
        Image(
            painter = avatar,
            contentDescription = null,
            modifier = Modifier.size(48.dp).kapowSkeleton(loading, shape = CircleShape),
        )
        BasicText(name, Modifier.kapowSkeleton(loading, loadingDescription = "Loading profile"))
    }
}
```

## Parameters

| Parameter | Default | Description |
| --- | --- | --- |
| `loading` | none | Whether the placeholder covers the content. |
| `shape` | `RoundedCornerShape(8.dp)` | The shape of the placeholder. Give it the shape of the content, such as a circle for an avatar. |
| `color` | `Color(0xFFD9DCE3)` | The fill of the placeholder. With an alpha below 1 the content shows through. |
| `shimmer` | `true` | Whether a band of light keeps sweeping across the placeholder. |
| `shimmerColor` | `Color.White.copy(alpha = 0.5f)` | The band. Its alpha is how bright the band gets at its middle. |
| `angle` | `20f` | Direction the band travels, in degrees clockwise from pointing right. |
| `duration` | `1500.milliseconds` | How long one sweep takes. |
| `revealDuration` | `300.milliseconds` | How long the placeholder takes to fade away. |
| `revealEasing` | `FastOutSlowInEasing` | The curve of that fade. |
| `loadingDescription` | `null` | What a screen reader hears while `loading` is true. The element becomes one node with this state description and the dummy content under it is hidden. `null` leaves the semantics alone. |

## Reduced motion

The placeholder is still, with no shimmer, and the reveal is a plain cross-fade.

## Notes

- An element that is first composed with `loading` set to false shows its content at once, with no placeholder and no reveal.
- The shimmer stops by itself once the placeholder is gone, so a loaded list costs nothing.
- Nothing recomposes while the placeholder shimmers or fades.
- The placeholder is drawn, not announced. Give `loadingDescription` if a screen reader should hear that the element is loading. While loading, its dummy content is hidden from assistive technology, and when loading ends the content's own semantics are back. The description changes nothing that is drawn, measured or placed. Do not set it on content that never finishes loading, because that hides the content from screen readers.
- For a shimmer over your own placeholder blocks, use [`ConditionalEffect.shimmer`](/effects/conditional-shimmer).

## Live example

<iframe class="live-example" src="https://kapow-demo.vercel.app/#more-skeleton" title="Live example: more-skeleton" loading="lazy" allow="autoplay"></iframe>
