---
title: Time
frameworkTitle:
  html: media-time
description: Time display components for showing current time, duration, and remaining time in a video player
---

import ComponentReference from "@/components/docs/api-reference/ComponentReference.astro";
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
import StyleCase from "@/components/docs/StyleCase.astro";
import Demo from "@/components/docs/demos/Demo.astro";

{/* React demos */}
import CurrentTimeDemoReact from "@/components/docs/demos/time/react/css/CurrentTime";
import currentTimeReactTsx from "@/components/docs/demos/time/react/css/CurrentTime.tsx?raw";
import currentTimeReactCss from "@/components/docs/demos/time/react/css/CurrentTime.css?raw";

import CurrentDurationDemoReact from "@/components/docs/demos/time/react/css/CurrentDuration";
import currentDurationReactTsx from "@/components/docs/demos/time/react/css/CurrentDuration.tsx?raw";
import currentDurationReactCss from "@/components/docs/demos/time/react/css/CurrentDuration.css?raw";

import RemainingDemoReact from "@/components/docs/demos/time/react/css/Remaining";
import remainingReactTsx from "@/components/docs/demos/time/react/css/Remaining.tsx?raw";
import remainingReactCss from "@/components/docs/demos/time/react/css/Remaining.css?raw";

import CustomSeparatorDemoReact from "@/components/docs/demos/time/react/css/CustomSeparator";
import customSeparatorReactTsx from "@/components/docs/demos/time/react/css/CustomSeparator.tsx?raw";
import customSeparatorReactCss from "@/components/docs/demos/time/react/css/CustomSeparator.css?raw";

import CustomNegativeSignDemoReact from "@/components/docs/demos/time/react/css/CustomNegativeSign";
import customNegativeSignReactTsx from "@/components/docs/demos/time/react/css/CustomNegativeSign.tsx?raw";
import customNegativeSignReactCss from "@/components/docs/demos/time/react/css/CustomNegativeSign.css?raw";

{/* HTML demos */}
import CurrentTimeDemoHtml from "@/components/docs/demos/time/html/css/CurrentTime.astro";
import currentTimeHtml from "@/components/docs/demos/time/html/css/CurrentTime.html?raw";
import currentTimeHtmlCss from "@/components/docs/demos/time/html/css/CurrentTime.css?raw";
import currentTimeHtmlTs from "@/components/docs/demos/time/html/css/CurrentTime.ts?raw";
import CurrentDurationDemoHtml from "@/components/docs/demos/time/html/css/CurrentDuration.astro";
import currentDurationHtml from "@/components/docs/demos/time/html/css/CurrentDuration.html?raw";
import currentDurationHtmlCss from "@/components/docs/demos/time/html/css/CurrentDuration.css?raw";
import currentDurationHtmlTs from "@/components/docs/demos/time/html/css/CurrentDuration.ts?raw";
import RemainingDemoHtml from "@/components/docs/demos/time/html/css/Remaining.astro";
import remainingHtml from "@/components/docs/demos/time/html/css/Remaining.html?raw";
import remainingHtmlCss from "@/components/docs/demos/time/html/css/Remaining.css?raw";
import remainingHtmlTs from "@/components/docs/demos/time/html/css/Remaining.ts?raw";
import CustomSeparatorDemoHtml from "@/components/docs/demos/time/html/css/CustomSeparator.astro";
import customSeparatorHtml from "@/components/docs/demos/time/html/css/CustomSeparator.html?raw";
import customSeparatorHtmlCss from "@/components/docs/demos/time/html/css/CustomSeparator.css?raw";
import customSeparatorHtmlTs from "@/components/docs/demos/time/html/css/CustomSeparator.ts?raw";
import CustomNegativeSignDemoHtml from "@/components/docs/demos/time/html/css/CustomNegativeSign.astro";
import customNegativeSignHtml from "@/components/docs/demos/time/html/css/CustomNegativeSign.html?raw";
import customNegativeSignHtmlCss from "@/components/docs/demos/time/html/css/CustomNegativeSign.css?raw";
import customNegativeSignHtmlTs from "@/components/docs/demos/time/html/css/CustomNegativeSign.ts?raw";

## Anatomy

<FrameworkCase frameworks={["react"]}>
```tsx
<Time.Group>
  <Time.Value type="current" />
  <Time.Separator />
  <Time.Value type="duration" />
</Time.Group>
```
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
```html
<media-time-group>
  <media-time type="current"></media-time>
  <media-time-separator></media-time-separator>
  <media-time type="duration"></media-time>
</media-time-group>
```
</FrameworkCase>

## Behavior

Three display types — `current`, `duration`, and `remaining` — in digital format with smart padding:

- **Hours** are never padded (`1:05:30`, not `01:05:30`)
- **Minutes** are padded when hours are shown (`1:05:30`, but `5:30`)
- **Seconds** are always padded (`1:05`, not `1:5`)

Hour display is triggered when either the current value or the duration exceeds 1 hour, ensuring consistency within a Group. Remaining time displays a negative sign (customizable via the `negativeSign` prop).

Use `toggle` to let current displays switch between elapsed and remaining time, or remaining and duration displays switch between those two values. The initial display comes from `type`.

<FrameworkCase frameworks={["react"]}>

```tsx
<Time.Value toggle />
<Time.Value toggle type="remaining" />
<Time.Value toggle type="duration" />
```
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>

```html
<media-time toggle></media-time>
<media-time toggle type="remaining"></media-time>
<media-time toggle type="duration"></media-time>
```
</FrameworkCase>

## Styling

The negative sign is rendered inside `<span aria-hidden="true">` and can be hidden with CSS:

```css
[data-type="remaining"] > span[aria-hidden] {
  display: none;
}
```

## Accessibility

<FrameworkCase frameworks={["html"]}>
Each `<media-time>` has:
- `aria-label` for the static role label ("Current time", "Duration", "Remaining")
- `aria-valuetext` for the dynamic human-readable time ("1 minute, 30 seconds")
</FrameworkCase>

<FrameworkCase frameworks={["react"]}>
Each `<Time.Value>` has:
- `aria-label` for the static role label ("Current time", "Duration", "Remaining")
- `aria-valuetext` for the dynamic human-readable time ("1 minute, 30 seconds")
</FrameworkCase>

No `aria-live` region is used — time updates too frequently and might overwhelm screen readers. The separator is `aria-hidden="true"` since screen readers already hear each time value separately. The negative sign is also `aria-hidden` because `aria-valuetext` already conveys "remaining". In React, `<time datetime>` provides machine-readable time for parsers.

Toggleable time displays receive `role="button"` and keyboard support for Enter and Space.

## Examples

### Current Time

<FrameworkCase frameworks={["react"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "App.tsx", code: currentTimeReactTsx, lang: "tsx" },
      { title: "App.css", code: currentTimeReactCss, lang: "css" },
    ]}>
      <CurrentTimeDemoReact client:idle />
    </Demo>
  </StyleCase>
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "index.html", code: currentTimeHtml, lang: "html" },
      { title: "index.css", code: currentTimeHtmlCss, lang: "css" },
      { title: "index.ts", code: currentTimeHtmlTs, lang: "ts" },
    ]}>
      <CurrentTimeDemoHtml />
    </Demo>
  </StyleCase>
</FrameworkCase>

### Current / Duration

<FrameworkCase frameworks={["react"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "App.tsx", code: currentDurationReactTsx, lang: "tsx" },
      { title: "App.css", code: currentDurationReactCss, lang: "css" },
    ]}>
      <CurrentDurationDemoReact client:idle />
    </Demo>
  </StyleCase>
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "index.html", code: currentDurationHtml, lang: "html" },
      { title: "index.css", code: currentDurationHtmlCss, lang: "css" },
      { title: "index.ts", code: currentDurationHtmlTs, lang: "ts" },
    ]}>
      <CurrentDurationDemoHtml />
    </Demo>
  </StyleCase>
</FrameworkCase>

### Remaining

<FrameworkCase frameworks={["react"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "App.tsx", code: remainingReactTsx, lang: "tsx" },
      { title: "App.css", code: remainingReactCss, lang: "css" },
    ]}>
      <RemainingDemoReact client:idle />
    </Demo>
  </StyleCase>
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "index.html", code: remainingHtml, lang: "html" },
      { title: "index.css", code: remainingHtmlCss, lang: "css" },
      { title: "index.ts", code: remainingHtmlTs, lang: "ts" },
    ]}>
      <RemainingDemoHtml />
    </Demo>
  </StyleCase>
</FrameworkCase>

### Custom Separator

<FrameworkCase frameworks={["react"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "App.tsx", code: customSeparatorReactTsx, lang: "tsx" },
      { title: "App.css", code: customSeparatorReactCss, lang: "css" },
    ]}>
      <CustomSeparatorDemoReact client:idle />
    </Demo>
  </StyleCase>
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "index.html", code: customSeparatorHtml, lang: "html" },
      { title: "index.css", code: customSeparatorHtmlCss, lang: "css" },
      { title: "index.ts", code: customSeparatorHtmlTs, lang: "ts" },
    ]}>
      <CustomSeparatorDemoHtml />
    </Demo>
  </StyleCase>
</FrameworkCase>

### Custom Negative Sign

<FrameworkCase frameworks={["react"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "App.tsx", code: customNegativeSignReactTsx, lang: "tsx" },
      { title: "App.css", code: customNegativeSignReactCss, lang: "css" },
    ]}>
      <CustomNegativeSignDemoReact client:idle />
    </Demo>
  </StyleCase>
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
  <StyleCase styles={["css"]}>
    <Demo files={[
      { title: "index.html", code: customNegativeSignHtml, lang: "html" },
      { title: "index.css", code: customNegativeSignHtmlCss, lang: "css" },
      { title: "index.ts", code: customNegativeSignHtmlTs, lang: "ts" },
    ]}>
      <CustomNegativeSignDemoHtml />
    </Demo>
  </StyleCase>
</FrameworkCase>

<ComponentReference component="Time" />
