> ## Documentation Index
> Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Bubble Styling

> Style the Angular message bubbles with CSS custom properties and BEM selectors, including the multi-attachment bubbles for images, videos, audio, and files.

## Overview

Angular message bubbles are styled with plain CSS. Every bubble exposes BEM-style class
names (`.cometchat-<name>-bubble__<element>`) that you can target from your global
stylesheet, and the colors, typography, and radii they use come from the theme variables
described in [Theming](/docs/ui-kit/angular/customization/theming).

There are no style inputs to pass — you override the selectors below.

<Note>
  Media messages always render with the multi-attachment bubbles. Which bubble handles a
  given message is decided by
  [`CometChatMessageBubble`](/docs/ui-kit/angular/components/cometchat-message-bubble#media-message-rendering)
  and is not configurable.
</Note>

## Where Each Bubble's Styles Live

Four of the five multi-attachment bubbles **delegate** their rendering to the
single-attachment bubble underneath, so you style them through that component's classes.
`CometChatAudiosBubble` is the exception — it draws its own player rows and has its own
stylesheet.

| Message type                   | Bubble                                  | Style it with                 |
| ------------------------------ | --------------------------------------- | ----------------------------- |
| `image`                        | [Image Bubble](#image-bubble)           | `.cometchat-image-bubble__*`  |
| `video`                        | [Video Bubble](#video-bubble)           | `.cometchat-video-bubble__*`  |
| `file`                         | [File Bubble](#file-bubble)             | `.cometchat-file-bubble__*`   |
| `audio` tagged as a voice note | [Voice Note Bubble](#voice-note-bubble) | `.cometchat-audio-bubble__*`  |
| `audio` (attached file)        | [Audio Bubble](#audio-bubble)           | `.cometchat-audios-bubble__*` |

## Shared Batch Width

Every batched media bubble resolves to one shared width so a batch reads as a single
visual block. Set `--cometchat-multi-attachment-width` to change it — it defaults to
`400px`.

```css theme={null}
:root {
  --cometchat-multi-attachment-width: 480px;
}
```

## Incoming vs Outgoing

The modifier used for direction is **not** consistent across bubbles — match the row for
the exact class you are styling. The two audio classes differ, so watch those two rows:

| Section          | Class                                                | Direction modifiers                     |
| ---------------- | ---------------------------------------------------- | --------------------------------------- |
| Image, Video     | `.cometchat-image-bubble`, `.cometchat-video-bubble` | `--incoming` / `--outgoing`             |
| File, Voice Note | `.cometchat-file-bubble`, `.cometchat-audio-bubble`  | `--sender` / `--receiver`               |
| Audio            | `.cometchat-audios-bubble`                           | `--sender` only (absent means incoming) |

```css theme={null}
.cometchat-image-bubble--outgoing { border-radius: 12px 12px 4px 12px; }
.cometchat-file-bubble--sender    { background: var(--cometchat-primary-color); }
```

## Message Bubbles

### Image Bubble

`CometChatImagesBubble` renders a message's image attachments as one grouped bubble, with
the layout chosen automatically from the attachment count (single, grid, 2×2). When there
are more images than visible cells, the last cell shows a **`+N`** overflow overlay;
clicking any cell opens the fullscreen gallery, and an optional caption renders below the
grid. It delegates rendering to `cometchat-image-bubble` and adds the shared batch width.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b/WbN-rq2ubtYeHzyc/images/angular_images_bubble.png?fit=max&auto=format&n=WbN-rq2ubtYeHzyc&q=85&s=dc1bdbde36c51e47cd37f5b35c504930" alt="Incoming and outgoing image bubbles, each showing four image attachments in a 2×2 grid with a +3 overflow tile on the last image" width="1280" height="664" data-path="images/angular_images_bubble.png" />
</Frame>

**Styling**

```css expandable theme={null}
/* The grid container and its layout states */
.cometchat-image-bubble__container { }
.cometchat-image-bubble__grid { }
.cometchat-image-bubble__grid--2x2 { }
.cometchat-image-bubble__grid--overflow { }

/* Bubble-level layout modifiers */
.cometchat-image-bubble--single { }
.cometchat-image-bubble--grid { }
.cometchat-image-bubble--grid-2x2 { }
.cometchat-image-bubble--overflow { }

/* Caption rendered under the grid */
.cometchat-image-bubble__caption { }
```

### Video Bubble

`CometChatVideosBubble` renders a message's video attachments as a thumbnail grid — each
cell showing a poster with a centered play overlay and a duration badge, plus a **`+N`**
overflow overlay when there are more videos than visible cells. Clicking a cell opens
fullscreen playback. It delegates rendering to `cometchat-video-bubble` and adds the
shared batch width.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b/WbN-rq2ubtYeHzyc/images/angular_videos_bubble.png?fit=max&auto=format&n=WbN-rq2ubtYeHzyc&q=85&s=4c3b2fae4f88ad7e301e4cf1116185bf" alt="Incoming and outgoing video bubbles, each showing four video thumbnails with play overlays in a 2×2 grid and a +3 overflow tile on the last thumbnail" width="1280" height="720" data-path="images/angular_videos_bubble.png" />
</Frame>

**Styling**

```css expandable theme={null}
.cometchat-video-bubble__container { }
.cometchat-video-bubble__grid { }

/* Play affordance and duration chip */
.cometchat-video-bubble__play-overlay { }
.cometchat-video-bubble__duration-badge { }
.cometchat-video-bubble__duration-text { }

.cometchat-video-bubble--single { }
.cometchat-video-bubble--grid-2x2 { }
.cometchat-video-bubble__caption { }
```

### Audio Bubble

`CometChatAudiosBubble` renders a message's attached audio files as a stack of inline
player rows, each with a file name, seekable scrubber, duration, and download control. The
list collapses after three rows behind a **Show N more** toggle. Unlike the other media
bubbles it is **custom-rendered** — it does not delegate, and draws its own player rows.
The caption is rendered with a nested `cometchat-text-bubble`.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b/WbN-rq2ubtYeHzyc/images/angular_audios_bubble.png?fit=max&auto=format&n=WbN-rq2ubtYeHzyc&q=85&s=71244a9429112eab4697ff1c36800def" alt="Incoming and outgoing audio bubbles, each showing three audio player rows with file name, scrubber, duration, and download control, plus a Show 2 more toggle" width="1280" height="760" data-path="images/angular_audios_bubble.png" />
</Frame>

**Styling**

```css expandable theme={null}
.cometchat-audios-bubble { }
.cometchat-audios-bubble--sender { }
.cometchat-audios-bubble__container { }
.cometchat-audios-bubble__container--multi { }
.cometchat-audios-bubble__header { }
.cometchat-audios-bubble__body { }

/* One player row */
.cometchat-audios-bubble__item { }
.cometchat-audios-bubble__item--unsupported { }
.cometchat-audios-bubble__name { }
.cometchat-audios-bubble__name--file { }
.cometchat-audios-bubble__duration { }

/* Transport, download, and icons */
.cometchat-audios-bubble__play { }
.cometchat-audios-bubble__play-icon { }
.cometchat-audios-bubble__slider { }
.cometchat-audios-bubble__download { }
.cometchat-audios-bubble__download-icon { }
.cometchat-audios-bubble__file-icon { }
.cometchat-audios-bubble__type-icon { }

/* Collapse toggle shown once the list exceeds three rows */
.cometchat-audios-bubble__toggle { }
.cometchat-audios-bubble__toggle-icon { }

.cometchat-audios-bubble__caption { }
```

### File Bubble

`CometChatFilesBubble` renders a message's generic file attachments as a connected stack
of file cards, each showing the file name, size, type, and a download control. Longer
lists collapse behind a **Show N more** toggle. It delegates rendering to
`cometchat-file-bubble` and adds the shared batch width.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b/WbN-rq2ubtYeHzyc/images/angular_files_bubble.png?fit=max&auto=format&n=WbN-rq2ubtYeHzyc&q=85&s=56ebaa48d61c8a6ce4b85fdf8684a7df" alt="Incoming and outgoing file bubbles, each showing PDF, Word, and PowerPoint rows with file size and download control, plus a Show 2 more toggle" width="1280" height="620" data-path="images/angular_files_bubble.png" />
</Frame>

**Styling**

```css expandable theme={null}
.cometchat-file-bubble__container { }
.cometchat-file-bubble__container--multi { }

/* Download affordance, including its disabled state */
.cometchat-file-bubble__download { }
.cometchat-file-bubble__download-icon { }
.cometchat-file-bubble__download--disabled { }
.cometchat-file-bubble__download-icon--disabled { }

/* Expand / collapse controls for long lists */
.cometchat-file-bubble__collapse-control { }
.cometchat-file-bubble__expand-indicator { }

.cometchat-file-bubble__caption { }
```

### Voice Note Bubble

`CometChatVoiceNoteBubble` renders audio messages recorded with the composer's voice
recorder, giving them the waveform playback UI (play/pause, seekable progress, elapsed and
total time). It exists as a distinct component so routing can pick it over the Audio
Bubble, based on the message metadata — an `audio` message is treated as a voice note only
when it carries the tag. It delegates rendering to `cometchat-audio-bubble`.

<Note>
  Voice notes render with the same waveform player UI as the single-attachment
  [`cometchat-audio-bubble`](/docs/ui-kit/angular/components/cometchat-audio-bubble) component they
  delegate to, so no separate screenshot is shown here.
</Note>

**Styling**

```css expandable theme={null}
.cometchat-audio-bubble__body { }
.cometchat-audio-bubble__audio-list { }
.cometchat-audio-bubble__audio-item { }

/* Per-row states */
.cometchat-audio-bubble__audio-item--loading { }
.cometchat-audio-bubble__audio-item--error { }

/* Transport controls */
.cometchat-audio-bubble__play-button { }
.cometchat-audio-bubble__progress-fg { }
.cometchat-audio-bubble__cancel-button { }

.cometchat-audio-bubble__caption { }
```

## Related

* [Theming](/docs/ui-kit/angular/customization/theming)
* [Message Bubble](/docs/ui-kit/angular/components/cometchat-message-bubble) — routes each message type to the bubbles above
* [Message List](/docs/ui-kit/angular/components/cometchat-message-list) — renders the bubbles and groups a batch
* [Message Composer](/docs/ui-kit/angular/components/cometchat-message-composer#multiple-attachments) — stages and sends multiple attachments
