> For the complete documentation index, see [llms.txt](https://analog.groupthought.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://analog.groupthought.com/reference/alpine/video.md).

# x-video (Analog)

Lazy playback for a video inside the component: the video renders only when it is needed, and window events drive playback from outside.

Lazy playback for a `<video>` inside the component: the video renders only when it is needed, and window events drive playback from outside.

| Directive / magic                                                                          | What it does                                                                |
| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| `x-video`                                                                                  | The root. Finds the `<video>` element inside itself once rendered           |
| `x-video.autoplay`                                                                         | Renders the video on first intersect and plays it while in view             |
| `$video.state`                                                                             | `'initial'`, `'playing'`, `'paused'`, or `null` before the video renders    |
| `$video.shouldRenderVideo`                                                                 | True when the `<video>` should be in the DOM. Use it with `<template x-if>` |
| `$video.hidePosterImage`                                                                   | True once playback started, so the poster image can be hidden               |
| `$video.showPlayButton`                                                                    | True while a click-to-play video has not been requested                     |
| `$video.handleIntersect()` / `handleEnter()` / `handleLeave()`                             | Viewport triggers for `x-intersect`                                         |
| `$video.playVideo()` / `pauseVideo()` / `muteVideo()` / `unmuteVideo()` / `unloadPlayer()` | Playback control                                                            |
| `$video.handlePlayButtonClick()`                                                           | Requests render and playback of a click-to-play video                       |
| `$video.id`                                                                                | The `<video>` element's id                                                  |

The root doesn't observe the viewport. Bind `x-intersect` to the `$video` handlers, as `core-video` does. Any rendered video pauses when it leaves the view, and an autoplay video also resumes when it returns. The component dispatches `theme:video:init`, `theme:video:playing`, `theme:video:paused`, `theme:video:muted`, and `theme:video:unmuted` with the video id as detail, and listens on `window` for `theme:video:play`, `theme:video:pause`, `theme:video:mute`, and `theme:video:unmute` whose detail is a video id or an array of ids.

## Examples

### A lazy autoplay video

Use `x-intersect` for the viewport triggers and `<template x-if>` to defer the `<video>` element:

```html
<div x-video.autoplay>
  <img src="{{ video.preview_image | image_url }}" alt="">
  <div
    x-intersect.once="$video.handleIntersect()"
    x-intersect:enter="$video.handleEnter()"
    x-intersect:leave="$video.handleLeave()"
  >
    <template x-if="$video.shouldRenderVideo">
      {{ video | video_tag: playsinline: true, muted: true, loop: true }}
    </template>
  </div>
</div>
```

The poster image renders on the server before the video loads. `core-video` contains the theme's version of this markup.

### Click to play

Use `$video.showPlayButton` and `$video.handlePlayButtonClick()` when the merchant turns autoplay off:

```html
<button x-show="$video.showPlayButton" @click="$video.handlePlayButtonClick()">
  Play
</button>
```

The click renders the `<video>` and starts playback; the poster stays visible until the first frame plays (`$video.hidePosterImage`).

### Driving a video from outside

Use the window events to control a video from another component:

```html
<button @click="$dispatch('theme:video:pause', videoId)">Pause the banner</button>
```

The detail can also be an array of ids to address several videos at once.

## Customizing

Render videos through `core-video`. It includes the intersection triggers, poster, play button, controls, and autoplay parameter.
