A digital clock for Home Assistant whose digits are solved to fill the whole card — all four edges, at any card size or shape.
Most "big text" cards pick a font size and hope. This one measures. Text has a
fixed aspect ratio, so scaling alone can never make 09:14 touch all four
edges of an arbitrary rectangle. Instead the card drives the wdth axis of a
variable font until the time's proportions match the card's, and only then
falls back to distortion.
- HACS → Frontend → ⋮ → Custom repositories
- Add
https://github.com/fwhitten/digital-clock-cardwith the category Lovelace - Install Digital Clock Card, then reload your browser
- Download
digital-clock-card.jsfrom the latest release - Copy it to
config/www/ - Add the resource under Settings → Dashboards → ⋮ → Resources:
/local/digital-clock-card.js, type JavaScript Module
Then add the card from the picker. It needs no entity, and everything is configurable from the visual editor.
Every option is available in the visual editor. The YAML names are listed for anyone who prefers to type.
| Option | Default | Description |
|---|---|---|
hour_format |
"24" |
"24" for 09:14, "12" for 9:14 AM. |
leading_zero |
true |
12-hour only. Off shows 9:14. The clock resizes as the hour gains a digit. |
show_meridiem |
true |
12-hour only. Adds a full-height stacked AM/PM column. |
font_weight |
400 |
100–900, continuous. See weight and card shape. |
background |
true |
Off makes the card fully transparent, with the digits edge to edge and no padding at all. |
padding |
8 |
Percentage of the card's shorter side left clear. Only applies with a background. |
stretch_to_fill |
true |
What to do when the card is a more extreme shape than the width axis can reach. See filling. |
aspect_ratio |
3 |
Only used in the masonry view, where cards size to their content instead of to a grid. |
time_animation |
"fade" |
none, fade or swipe. Only the digits that changed animate. |
swipe_direction |
"up" |
up or down. Swipe only. |
colon_blink |
"none" |
none, flash or fade. Blinks once a second, locked to the real clock. |
color |
theme | A Home Assistant colour name (primary, red, orange, …). Follows the theme into dark mode. |
color_light / color_dark |
— | Exact CSS colours that override color, chosen by the active theme's mode. |
background_color |
theme | As color, for the card background. |
background_color_light / background_color_dark |
— | As above, exact values. |
tap_action / hold_action / double_tap_action |
none |
Standard Home Assistant actions. |
The smallest possible card:
type: custom:digital-clock-cardA frameless clock that fills its grid cell completely:
type: custom:digital-clock-card
background: false
font_weight: 250
colon_blink: fade
time_animation: swipeA bold 12-hour clock in the theme's accent colour:
type: custom:digital-clock-card
hour_format: "12"
leading_zero: false
font_weight: 800
color: accent
tap_action:
action: navigate
navigation_path: /lovelace/clockThe card is given a rectangle and has to make the ink of 09:14 touch every
edge of it.
- Solve the width axis. Archivo's
wdthaxis runs from 62 to 125, which changes a digit's advance by about two thirds. The card bisects that axis for the width at which the time's aspect ratio equals the card's, so the digits reach both pairs of edges while keeping their proper shapes. - Size to the ink, not the line. A font's line box includes ascender and descender space that digits never occupy; sizing to it leaves a stubborn gap above and below. The card works from the ink box of the digits, measured from the font itself at build time, so the tops of the digits sit exactly on the top edge.
- Distort only as a last resort. If the card is a more extreme shape than
the width axis can reach,
stretch_to_filldecides what happens: stretch the digits to cover the remainder (the default, so the card is always full), or leave them undistorted and centred, with a gap.
All of this is arithmetic over a metric table extracted from the font when the card is built, so resizing costs no layout measurement and the first frame is already correct. The only thing measured in the browser is where it places the baseline, which is calibrated once.
Because the digits are tabular — every digit has exactly the same advance at
every point on both axes — the layout is solved once and never moves as the
time changes. A 1 does not make the clock jump.
Heavier digits cannot be squeezed as narrow, so the weight you choose sets the range of card shapes that can be filled without any distortion:
| Font weight | Narrowest card | Widest card |
|---|---|---|
| 100 | 2.44 : 1 | 4.03 : 1 |
| 200 | 2.46 : 1 | 4.10 : 1 |
| 300 | 2.49 : 1 | 4.19 : 1 |
| 400 | 2.52 : 1 | 4.30 : 1 |
| 500 | 2.55 : 1 | 4.41 : 1 |
| 600 | 2.59 : 1 | 4.54 : 1 |
| 700 | 2.62 : 1 | 4.65 : 1 |
| 800 | 2.67 : 1 | 4.82 : 1 |
| 900 | 2.75 : 1 | 5.05 : 1 |
(Ratios are for a four-digit 24-hour clock; a stacked AM/PM column widens them slightly.)
A wide, short card is what Archivo's width axis is built for. Because that axis only spans 62–125, the band is narrow and the weight barely widens it: nothing narrower than about 2.4:1 can be filled without stretching, at any weight. Square and portrait cards get stretched noticeably, so give the card a wide, short slot where you can. The editor shows the reachable range beneath the weight slider as you drag it.
The card implements getGridOptions(), so in the sections view it can be
dragged to any size and reflows instantly; it defaults to full width and two
rows, and will go as small as three columns by one row.
In the older masonry view, cards size to their content and there is no
height to fill, so the card falls back to the configured aspect_ratio.
- Theme. Colours come from the active Home Assistant theme, so light and dark follow whatever the user has set — including "auto", which tracks the system. Explicit colours can be given separately for each mode.
- Efficiency. The clock schedules a single timer aligned to the next minute rather than polling, and stops entirely while its tab is hidden, catching up when it comes back. The blinking colon runs as a compositor animation, phase- locked to the wall clock, so no per-second JavaScript is involved.
- Reduced motion. Digit transitions and the blinking colon are disabled
automatically when the browser reports
prefers-reduced-motion. - Accessibility. The card exposes the time as a
timerrole with a readable label, and becomes a focusable button when an action is configured. - Offline. The font is subset to the fourteen glyphs a clock needs and embedded in the bundle (under 9KB), so nothing is fetched from a third party and the card works on installs with no internet access.
- Tabular figures. Archivo's digits are proportional by default, which would make the clock re-solve and jump every minute. The build remaps the digit codepoints onto the font's tabular figures, so every digit has an identical advance at every point on both axes and the layout never moves.
npm install
npm run build # -> dist/digital-clock-card.js
npm run watchThere is a harness at dev/index.html that renders the card at a spread of
sizes and configurations against stand-ins for the frontend's elements, and
audits how exactly the digits meet each edge:
npx http-server -p 8177 . Then open http://localhost:8177/dev/ and call audit() from the console.
docs/preview.svg in the README is generated too, with the glyphs converted to
paths so it needs no embedded font:
.venv/bin/python tools/build-preview.pyIt re-implements the layout solver against exact font instances rather than the interpolated table, so the two act as a check on each other - they currently agree on font size to 0.003% and on the width axis to 0.10%.
src/font-data.ts is generated. It holds the subset woff2 and the metric grid
the solver interpolates. To regenerate it — after changing which glyphs are
included, or the sampling grid:
python3 -m venv .venv && .venv/bin/pip install -r tools/requirements.txt
.venv/bin/python tools/build-font.pyThe card is MIT licensed — see LICENSE.
It embeds a subset of Archivo by Omnibus-Type, which is licensed separately under the SIL Open Font License 1.1 — see OFL.txt and NOTICE.