# Avatars

The Flutter SDK provides avatar components for displaying users and channels throughout your chat UI. This page covers the available avatar widgets, their configuration options, and how to customize their appearance using the theme system.

### Overview

Avatar components use a `StreamAvatarSize` enum for sizing. To handle taps, wrap the avatar in a `GestureDetector` or `InkWell`.

### StreamUserAvatar

Displays a user's avatar with optional online indicator.

```dart
GestureDetector(
  onTap: () => showProfile(user),
  child: StreamUserAvatar(
    user: user,
    size: StreamAvatarSize.lg,       // 40px diameter
    showOnlineIndicator: true,
  ),
)
```

![](@chat-sdk/flutter/v10-latest/_assets/user_avatar_default.png)

### StreamChannelAvatar

Displays an avatar for a channel. 1:1 channels show the other user's avatar; group channels show a 2×2 avatar grid.

```dart
GestureDetector(
  onTap: () => openChannel(channel),
  child: StreamChannelAvatar(
    channel: channel,
    size: StreamAvatarGroupSize.lg,   // 40px
  ),
)
```

|                            1:1 channel                            |                           Group channel                            |
| :---------------------------------------------------------------: | :----------------------------------------------------------------: |
| ![](@chat-sdk/flutter/v10-latest/_assets/user_avatar_default.png) | ![](@chat-sdk/flutter/v10-latest/_assets/avatar_group_default.png) |

### StreamUserAvatarGroup

`StreamUserAvatarGroup` displays a grid of user avatars. It accepts `users` (`Iterable<User>`).

```dart
GestureDetector(
  onTap: () => showGroupInfo(),
  child: StreamUserAvatarGroup(
    users: otherMembers.map((m) => m.user!),
    size: StreamAvatarGroupSize.lg,
  ),
)
```

![](@chat-sdk/flutter/v10-latest/_assets/avatar_group_default.png)

### StreamUserAvatarStack

Displays overlapping user avatars (e.g., thread participants).

```dart
StreamUserAvatarStack(
  users: threadParticipants,
  size: StreamAvatarStackSize.xs,   // 20px
  max: 3,
  overlap: 0.33,
)
```

![](@chat-sdk/flutter/v10-latest/_assets/avatar_stack_default.png)

| Parameter | Type                     | Default  | Description                       |
| --------- | ------------------------ | -------- | --------------------------------- |
| `users`   | `Iterable<User>`         | required | Users to display                  |
| `size`    | `StreamAvatarStackSize?` | `.sm`    | Avatar size                       |
| `max`     | `int`                    | `5`      | Max avatars before overflow badge |
| `overlap` | `double`                 | `0.33`   | Overlap fraction (0.0–1.0)        |

### Size Reference

#### StreamAvatarSize

| Enum   | Diameter |
| ------ | -------- |
| `.xs`  | 20px     |
| `.sm`  | 24px     |
| `.md`  | 32px     |
| `.lg`  | 40px     |
| `.xl`  | 48px     |
| `.xxl` | 80px     |

#### StreamAvatarGroupSize

| Enum   | Diameter |
| ------ | -------- |
| `.lg`  | 40px     |
| `.xl`  | 48px     |
| `.xxl` | 80px     |

#### StreamAvatarStackSize

| Enum  | Diameter |
| ----- | -------- |
| `.xs` | 20px     |
| `.sm` | 24px     |

### Customizing with StreamComponentFactory

`StreamComponentFactory` provides three avatar slots that let you replace the default rendering at different levels of the component hierarchy. All changes apply to every avatar in the wrapped subtree.

#### `avatar` — replace every avatar circle

The `avatar` slot is the lowest-level hook. Because `StreamUserAvatar`, `StreamChannelAvatar`, and `StreamUserAvatarGroup` all delegate to `StreamAvatar` internally, a single `avatar` builder replaces every avatar circle across the whole chat UI.

`StreamAvatarProps` exposes `imageUrl`, `placeholder`, `backgroundColor`, `foregroundColor`, `showBorder`, and `size`.

```dart
StreamComponentFactory(
  builders: StreamComponentBuilders(
    avatar: (context, props) {
      // Square avatar with rounded corners instead of a circle.
      return ClipRRect(
        borderRadius: BorderRadius.circular(8),
        child: props.imageUrl != null
            ? Image.network(props.imageUrl!, fit: BoxFit.cover)
            : Container(
                color: props.backgroundColor,
                child: Builder(builder: props.placeholder),
              ),
      );
    },
  ),
  child: child,
)
```

#### `avatarGroup` — replace the group grid layout

The `avatarGroup` slot controls how multiple avatars are arranged in a grid, used by `StreamChannelAvatar` for group channels and `StreamUserAvatarGroup`.

`StreamAvatarGroupProps` exposes `children` (the pre-built avatar widgets) and `size`.

```dart
StreamComponentFactory(
  builders: StreamComponentBuilders(
    avatarGroup: (context, props) {
      // Horizontal row instead of the default 2×2 grid.
      final themeSize = switch (props.size ?? StreamAvatarGroupSize.lg) {
        StreamAvatarGroupSize.lg => StreamAvatarSize.sm,
        StreamAvatarGroupSize.xl => StreamAvatarSize.md,
        StreamAvatarGroupSize.xxl => StreamAvatarSize.xl,
      };
      return StreamAvatarTheme(
        data: StreamAvatarThemeData(size: themeSize),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: props.children
              .take(3)
              .map((avatar) => Padding(
                    padding: const EdgeInsets.only(right: 2),
                    child: avatar,
                  ))
              .toList(),
        ),
      );
    },
  ),
  child: child,
)
```

![](@chat-sdk/flutter/v10-latest/_assets/avatar_group_custom.png)

#### `avatarStack` — replace the overlapping stack layout

The `avatarStack` slot controls the overlapping avatar row used by `StreamUserAvatarStack` (e.g. thread participants).

`StreamAvatarStackProps` exposes `children`, `size`, `overlap`, and `max`.

```dart
StreamComponentFactory(
  builders: StreamComponentBuilders(
    avatarStack: (context, props) {
      // Custom layout: 1 medium avatar on top (overlapping the row
      // below by 10%), rest in a small overlapping row (40% overlap).
      final visible = props.children.take(props.max).toList();
      if (visible.isEmpty) return const SizedBox.shrink();

      final topDiameter = StreamAvatarSize.md.value;
      final bottomDiameter = StreamAvatarSize.sm.value;
      final step = bottomDiameter * 0.6;
      final rest = visible.skip(1).toList();
      final bottomRowWidth =
          rest.isEmpty ? 0.0 : bottomDiameter + (rest.length - 1) * step;
      final totalWidth = bottomRowWidth.clamp(topDiameter, double.infinity);
      final topLeft = (totalWidth - topDiameter) / 2;
      final bottomLeft = (totalWidth - bottomRowWidth) / 2;
      final topOverlap = topDiameter * 0.1;
      final totalHeight = topDiameter + bottomDiameter - topOverlap;

      return SizedBox(
        width: totalWidth,
        height: totalHeight,
        child: Stack(
          children: [
            // Top avatar — rendered first so the bottom row paints over
            // it at the overlap, keeping the bottom avatars fully visible.
            Positioned(
              top: 0,
              left: topLeft,
              child: StreamAvatarTheme(
                data: const StreamAvatarThemeData(size: StreamAvatarSize.md),
                child: visible.first,
              ),
            ),
            // Bottom row — rendered last so it appears above the top avatar
            // at the overlap point.
            Positioned(
              top: topDiameter - topOverlap,
              left: bottomLeft,
              child: StreamAvatarTheme(
                data: const StreamAvatarThemeData(size: StreamAvatarSize.sm),
                child: SizedBox(
                  width: bottomRowWidth,
                  height: bottomDiameter,
                  child: Stack(
                    children: [
                      for (var i = 0; i < rest.length; i++)
                        Positioned(left: i * step, child: rest[i]),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      );
    },
  ),
  child: child,
)
```

![](@chat-sdk/flutter/v10-latest/_assets/avatar_stack_custom.png)


---

This page was last updated at 2026-06-09T15:44:03.762Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/flutter/stream-chat-flutter/avatars/](https://getstream.io/chat/docs/sdk/flutter/stream-chat-flutter/avatars/).