Navigation

v0.0.4
Feedback

Alert

A message in the flow of the page, with an optional status.

On this page

An alert is a message in the flow of the page, about the page it sits in. It is a flat face with a half-pixel contour. A status tints the face faintly and colors the icon; the words stay in ink, so the hue never carries the meaning alone.

Alert

<div class="alert" role="status">  <svg class="icon alert-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">    <circle cx="12" cy="12" r="9" />    <path d="M12 11v5M12 8v.01" />  </svg>  <div class="alert-body">    <p class="alert-title">A new version is available</p>    <p class="alert-description">Reload to use the latest build of the dashboard.</p>  </div>  <button type="button" class="btn btn-sm">Reload</button></div>

#Status

Choose the status by what the reader has to do, and say it in the words as well.

  • alert-info adds context that changes nothing yet.
  • alert-success confirms something that just completed.
  • alert-warning asks for attention before something goes wrong.
  • alert-danger reports a failure or a blocked action.

Status

<div class="alert alert-info" role="status">  <svg class="icon alert-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">    <circle cx="12" cy="12" r="9" />    <path d="M12 11v5M12 8v.01" />  </svg>  <div class="alert-body">    <p class="alert-description">Scheduled maintenance on Sunday from 02:00 to 03:00 UTC.</p>  </div></div><div class="alert alert-success" role="status">  <svg class="icon alert-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">    <circle cx="12" cy="12" r="9" />    <path d="m8.5 12.5 2.5 2.5 4.5-5.5" />  </svg>  <div class="alert-body">    <p class="alert-description">Your domain is verified and serving traffic.</p>  </div></div><div class="alert alert-warning" role="status">  <svg class="icon alert-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">    <path d="M12 4 3 19h18L12 4ZM12 10v4M12 17v.01" />  </svg>  <div class="alert-body">    <p class="alert-title">Your card expires this month</p>    <p class="alert-description">Update the payment method to keep deployments running.</p>  </div>  <button type="button" class="btn btn-sm">Update</button></div><div class="alert alert-danger" role="alert">  <svg class="icon alert-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">    <circle cx="12" cy="12" r="9" />    <path d="M12 8v5M12 16v.01" />  </svg>  <div class="alert-body">    <p class="alert-title">The build failed</p>    <p class="alert-description">The install step exited with code 1. Read the logs for the missing dependency.</p>  </div></div>

#Layout

An alert uses --alert-radius, defaulting to var(--radius-control-lg). When it is held directly in a tray, set that property on the alert to var(--radius-surface) to follow the holder's corner and inset.

Put icon alert-icon on the icon: it centers on the first line of text, however many lines follow. alert-body takes the remaining width. A button or a link after the body sits at the end of the row and wraps under the text when the alert is narrow.

In a narrow column

<div class="alert alert-warning max-w(280) mx-auto" role="status">  <svg class="icon alert-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">    <path d="M12 4 3 19h18L12 4ZM12 10v4M12 17v.01" />  </svg>  <div class="alert-body">    <p class="alert-title">Usage is at 90%</p>    <p class="alert-description">Requests are limited when the plan runs out.</p>  </div>  <button type="button" class="btn btn-sm">Upgrade</button></div>

#Accessibility

  • An alert that appears after the page has loaded needs a live region: role="status" waits for a pause, and role="alert" interrupts. Keep role="alert" for failures that need action now.
  • An alert that is part of the page from the start needs no role.
  • Mark the icon aria-hidden="true"; the text carries the message.

#Classes

ClassDescription
alertA neutral message: a flat face with a half-pixel contour. A button or a link after the body sits at the end of the row and wraps under the text when the alert is narrow
alert-infoContext that changes nothing yet: a faint tint and icon in the info hue. With alert
alert-successSomething that just completed: a faint tint and icon in the success hue. With alert
alert-warningAttention before something goes wrong: a faint tint and icon in the warning hue. With alert
alert-dangerA failure or a blocked action: a faint tint and icon in the danger hue. With alert
alert-iconBeside icon on the icon: centers it on the first line of text, however many lines follow
alert-bodyHolds the words and takes the remaining width
alert-titleThe few strong words that carry the message
alert-descriptionThe sentence under the title, or the whole message of an alert without a title

#Custom properties

PropertyDefaultDescription
--alert-radiusvar(--radius-control-lg)Circular radius before the corner scale; use var(--radius-surface) when held directly in a tray. On alert

#Source

@master/ui/components/alert.css
/* * Alert: a message in the flow of the page, about the page it sits in. * A flat face with a half-pixel contour; a status tints the face faintly and colors the icon, and the words * stay in ink, so the hue never carries the meaning alone. When there is no room, the action wraps under the text. */@layer components {  .alert {    --alert-radius: var(--radius-control-lg);    --alert-tone: var(--color-text-muted);    --icon-size: 1rem;    --icon-color: var(--alert-tone);    display: flex;    flex-wrap: wrap;    align-items: flex-start;    gap: .625rem .75rem;    padding: .75rem .875rem;    border-radius: calc(var(--alert-radius) * var(--corner-scale));    corner-shape: var(--corner-shape);    background: var(--color-surface-chip);    color: var(--color-text-body);    box-shadow: inset 0 0 0 .5px var(--color-line-contour);    font-size: .84375rem;    line-height: 1.5;    &:is(.alert-info, .alert-success, .alert-warning, .alert-danger) {      background: color-mix(in oklab, var(--alert-tone) 6%, var(--color-surface-raised));      box-shadow: inset 0 0 0 .5px color-mix(in oklab, var(--alert-tone) 34%, transparent);    }    &.alert-info { --alert-tone: var(--color-info); }    &.alert-success { --alert-tone: var(--color-success); }    &.alert-warning { --alert-tone: var(--color-warning); }    &.alert-danger { --alert-tone: var(--color-danger); }    @media (forced-colors: active) {      outline: 1px solid CanvasText;      outline-offset: -1px;    }  }  /* The icon centers on the first line of text, however many lines follow. */  .alert-icon {    margin-block: calc((1lh - var(--icon-size)) / 2);  }  /* The words take the remaining width and never shrink below a readable measure before the action wraps. */  .alert-body {    display: grid;    flex: 1 1 12rem;    gap: .125rem;    min-width: 0;  }  .alert-title {    margin: 0;    color: var(--color-text-strong);    font-weight: var(--font-weight-control);    text-wrap: balance;    overflow-wrap: anywhere;  }  .alert-description {    margin: 0;    text-wrap: pretty;    overflow-wrap: anywhere;  }}