Alerts
An Alert displays important messaging to the user that may not require the user to respond, such as a system status or confirmation. Some Alerts may require users to respond, such as an input error in a form.
Do not use alerts as containers for newsworthy items or page content that you want attention drawn to (example: Upcoming Seminar!). Alerts are for information that the user should know about regarding their use of the website or page. Consider using a Panel instead for page content.
Use the appropriate announcement behavior for assistive technology. Some code examples omit the attribute pairing aria-live
and role
which controls behavior of alerts that are dynamically updated. If you are only including your alert message in html, straight from the server, leave them out. Read the Accessibility section to understand which attributes are correct for your situation.
Examples
Informational
<div class="bux-alert bux-alert--info">
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id="label-type-info-205224924">Information.</div>
<div class="bux-alert__message">
<h2 class="bux-alert__message-title" id="-message-205224924">
This is an info message.
</h2>
<div class="bux-alert__message-text">
This is additional text about this message.
</div>
</div>
</div>
{#
Buckeye UX - version 1.0.15
Copyright (C) 2024 The Ohio State University
#}
{% set live_type = '' %}
{% if live %}
{% if alert_role == 'status' %}
{% set live_type = 'role="status" aria-live="polite"' %}
{% elseif alert_role == 'alert' %}
{% set live_type = 'role="alert" aria-live="assertive"' %}
{% else %}
{% set live_type = 'aria-live="polite"' %}
{% endif %}
{% endif %}
{% set random_seed = random() %}
{% set alert_id = "label-type-" ~ alert_type ~ "-" ~ random_seed %}
{% set alert_label = alert_role ~ "-message-" ~ random_seed %}
{% if live %}
<div role="region" aria-labelledby="{{ alert_id }} {{ alert_label }}">
{% endif %}
<div class="bux-alert bux-alert--{{ alert_type }}" {{ live_type }}>
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id={{ alert_id }}>{{ alert_type_string }}</div>
<div class="bux-alert__message">
<h{{ alert_heading_level | default(2) }} class="bux-alert__message-title" id="{{ alert_label }}">{{ alert_title }}</h{{ alert_heading_level | default(2) }}>
{% if alert_text %}
<div class="bux-alert__message-text">{{ alert_text }}</div>
{% endif %}
{% if dismissible %}
<button class="bux-alert__dismiss"><span class="visually-hidden">Dismiss this alert</span></button>
{% endif %}
</div>
</div>
{% if live %}
</div>
{% endif %}
{% for type, messages in message_list %}
<div class="status-box" role="contentinfo" aria-label="{{ status_headings[type] }}" {{ attributes|without('role', 'aria-label') }}>
{# Message type. #}
{% if type == 'error' %}
<div class="bux-alert bux-alert--error" role="alert">
{% elseif type == 'status' %}
<div class="bux-alert bux-alert--info" role="status">
{% elseif type == 'warning' %}
<div class="bux-alert bux-alert--warning" role="status">
{% else %}
<div class="bux-alert">
{% endif %}
{# Icon. #}
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden">{{ alert_type_string }}</div>
{# Message contents. #}
<div class="bux-alert__message">
{% if status_headings[type] %}
<h2 class="bux-alert__message-title">{{ type|capitalize }}</h2>
{% endif %}
{% if messages|length > 1 %}
<ul class="bux-alert__message-text">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% else %}
<div class="bux-alert__message-text">{{ messages|first }}</div>
{% endif %}
</div> {# End bux-alert__message. #}
</div> {# End bux-alert. #}
</div> {# End status-box. #}
{% endfor %}
Success
<div class="bux-alert bux-alert--success">
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id="label-type-success-2035247637">Success.</div>
<div class="bux-alert__message">
<h2 class="bux-alert__message-title" id="-message-2035247637">
This is a success message.
</h2>
<div class="bux-alert__message-text">
This is additional text about this message.
</div>
</div>
</div>
{#
Buckeye UX - version 1.0.15
Copyright (C) 2024 The Ohio State University
#}
{% set live_type = '' %}
{% if live %}
{% if alert_role == 'status' %}
{% set live_type = 'role="status" aria-live="polite"' %}
{% elseif alert_role == 'alert' %}
{% set live_type = 'role="alert" aria-live="assertive"' %}
{% else %}
{% set live_type = 'aria-live="polite"' %}
{% endif %}
{% endif %}
{% set random_seed = random() %}
{% set alert_id = "label-type-" ~ alert_type ~ "-" ~ random_seed %}
{% set alert_label = alert_role ~ "-message-" ~ random_seed %}
{% if live %}
<div role="region" aria-labelledby="{{ alert_id }} {{ alert_label }}">
{% endif %}
<div class="bux-alert bux-alert--{{ alert_type }}" {{ live_type }}>
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id={{ alert_id }}>{{ alert_type_string }}</div>
<div class="bux-alert__message">
<h{{ alert_heading_level | default(2) }} class="bux-alert__message-title" id="{{ alert_label }}">{{ alert_title }}</h{{ alert_heading_level | default(2) }}>
{% if alert_text %}
<div class="bux-alert__message-text">{{ alert_text }}</div>
{% endif %}
{% if dismissible %}
<button class="bux-alert__dismiss"><span class="visually-hidden">Dismiss this alert</span></button>
{% endif %}
</div>
</div>
{% if live %}
</div>
{% endif %}
Warning
<div
role="region"
aria-labelledby="label-type-warning-1139892845 status-message-1139892845"
>
<div class="bux-alert bux-alert--warning" role="status" aria-live="polite">
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id="label-type-warning-1139892845">
Warning.
</div>
<div class="bux-alert__message">
<h2 class="bux-alert__message-title" id="status-message-1139892845">
This is a warning message.
</h2>
<div class="bux-alert__message-text">
This is additional text about this message.
</div>
</div>
</div>
</div>
{#
Buckeye UX - version 1.0.15
Copyright (C) 2024 The Ohio State University
#}
{% set live_type = '' %}
{% if live %}
{% if alert_role == 'status' %}
{% set live_type = 'role="status" aria-live="polite"' %}
{% elseif alert_role == 'alert' %}
{% set live_type = 'role="alert" aria-live="assertive"' %}
{% else %}
{% set live_type = 'aria-live="polite"' %}
{% endif %}
{% endif %}
{% set random_seed = random() %}
{% set alert_id = "label-type-" ~ alert_type ~ "-" ~ random_seed %}
{% set alert_label = alert_role ~ "-message-" ~ random_seed %}
{% if live %}
<div role="region" aria-labelledby="{{ alert_id }} {{ alert_label }}">
{% endif %}
<div class="bux-alert bux-alert--{{ alert_type }}" {{ live_type }}>
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id={{ alert_id }}>{{ alert_type_string }}</div>
<div class="bux-alert__message">
<h{{ alert_heading_level | default(2) }} class="bux-alert__message-title" id="{{ alert_label }}">{{ alert_title }}</h{{ alert_heading_level | default(2) }}>
{% if alert_text %}
<div class="bux-alert__message-text">{{ alert_text }}</div>
{% endif %}
{% if dismissible %}
<button class="bux-alert__dismiss"><span class="visually-hidden">Dismiss this alert</span></button>
{% endif %}
</div>
</div>
{% if live %}
</div>
{% endif %}
Error
<div
role="region"
aria-labelledby="label-type-error-1093624663 alert-message-1093624663"
>
<div class="bux-alert bux-alert--error" role="alert" aria-live="assertive">
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id="label-type-error-1093624663">Error.</div>
<div class="bux-alert__message">
<h2 class="bux-alert__message-title" id="alert-message-1093624663">
This is an error message.
</h2>
<div class="bux-alert__message-text">
This is additional text about this message.
</div>
</div>
</div>
</div>
{#
Buckeye UX - version 1.0.15
Copyright (C) 2024 The Ohio State University
#}
{% set live_type = '' %}
{% if live %}
{% if alert_role == 'status' %}
{% set live_type = 'role="status" aria-live="polite"' %}
{% elseif alert_role == 'alert' %}
{% set live_type = 'role="alert" aria-live="assertive"' %}
{% else %}
{% set live_type = 'aria-live="polite"' %}
{% endif %}
{% endif %}
{% set random_seed = random() %}
{% set alert_id = "label-type-" ~ alert_type ~ "-" ~ random_seed %}
{% set alert_label = alert_role ~ "-message-" ~ random_seed %}
{% if live %}
<div role="region" aria-labelledby="{{ alert_id }} {{ alert_label }}">
{% endif %}
<div class="bux-alert bux-alert--{{ alert_type }}" {{ live_type }}>
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id={{ alert_id }}>{{ alert_type_string }}</div>
<div class="bux-alert__message">
<h{{ alert_heading_level | default(2) }} class="bux-alert__message-title" id="{{ alert_label }}">{{ alert_title }}</h{{ alert_heading_level | default(2) }}>
{% if alert_text %}
<div class="bux-alert__message-text">{{ alert_text }}</div>
{% endif %}
{% if dismissible %}
<button class="bux-alert__dismiss"><span class="visually-hidden">Dismiss this alert</span></button>
{% endif %}
</div>
</div>
{% if live %}
</div>
{% endif %}
Alert with dismiss button JSThis feature of the component requires JavaScript.
Page-level alerts can be used with an optional dismiss button, however it’s important to avoid allowing users to dismiss alerts that are used to display error messages.
<div
role="region"
aria-labelledby="label-type-warning-1286364075 alert-message-1286364075"
>
<div class="bux-alert bux-alert--warning" role="alert" aria-live="assertive">
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id="label-type-warning-1286364075">
Warning.
</div>
<div class="bux-alert__message">
<h2 class="bux-alert__message-title" id="alert-message-1286364075">
This is a warning message.
</h2>
<div class="bux-alert__message-text">
This is additional text about this message.
</div>
<button class="bux-alert__dismiss">
<span class="visually-hidden">Dismiss this alert</span>
</button>
</div>
</div>
</div>
{#
Buckeye UX - version 1.0.15
Copyright (C) 2024 The Ohio State University
#}
{% set live_type = '' %}
{% if live %}
{% if alert_role == 'status' %}
{% set live_type = 'role="status" aria-live="polite"' %}
{% elseif alert_role == 'alert' %}
{% set live_type = 'role="alert" aria-live="assertive"' %}
{% else %}
{% set live_type = 'aria-live="polite"' %}
{% endif %}
{% endif %}
{% set random_seed = random() %}
{% set alert_id = "label-type-" ~ alert_type ~ "-" ~ random_seed %}
{% set alert_label = alert_role ~ "-message-" ~ random_seed %}
{% if live %}
<div role="region" aria-labelledby="{{ alert_id }} {{ alert_label }}">
{% endif %}
<div class="bux-alert bux-alert--{{ alert_type }}" {{ live_type }}>
<div class="bux-alert__icon" aria-hidden="true"></div>
<div class="visually-hidden" id={{ alert_id }}>{{ alert_type_string }}</div>
<div class="bux-alert__message">
<h{{ alert_heading_level | default(2) }} class="bux-alert__message-title" id="{{ alert_label }}">{{ alert_title }}</h{{ alert_heading_level | default(2) }}>
{% if alert_text %}
<div class="bux-alert__message-text">{{ alert_text }}</div>
{% endif %}
{% if dismissible %}
<button class="bux-alert__dismiss"><span class="visually-hidden">Dismiss this alert</span></button>
{% endif %}
</div>
</div>
{% if live %}
</div>
{% endif %}
Usage
Dos
- Use to notify users about system status including error, warnings, and updates
- Use to notify users they’ve successfully completed a task
- Use along with inline validation alerts to summarize multiple errors on longer forms
- Write helpful alert messages. For errors, include a brief description of the problem and how to fix it
- Keep the title brief, but clear; use the description if more context is needed
- Where appropriate, alert title should be a link to the position on the page where the invalid element can be found
- Alert message should offer next steps where appropriate
Don’ts
- Don't use if action taken by the user will result in losing/destroying their work, use a modal dialog that allows the user to confirm the destructive action
- Don’t use error messages that automatically disappear. If a user doesn’t have time to read the error message they may not know how to correct the problem once it has been automatically removed.
Implementation notes
- Avoid using error messages that automatically disappear. If a user doesn’t have time to read the error message they may not know how to correct the problem once it has been automatically removed.
- Write helpful alert messages. For errors, Include a brief description of the problem and how to fix it.
- Alert title should be clear and concise. “Success!” rather than “Application was submitted successfully!”
- Alert message should be descriptive and should clearly articulate the problem
the user has encountered or the information you are trying to convey to the
user
- “The user ID and password you entered do not match” is more clear than “Unauthorized”
- Where appropriate, alert title should be a link to the position on the page where the invalid element can be found
- Alert message should offer next steps where appropriate
Good example
- Clear title; explains that maintenance was scheduled and expected
- Informs the user of the length of the outage
- Lets the user know when the system is expected to be available
Bad example
- Doesn’t indicate that maintenance was scheduled and expected
- Doesn’t inform the user how long the system will be unavailable
- Doesn’t let the user know when the system is expected to be available again
Accessibility
- If the Alert will be dynamic, the container used as the live region must exist in the page before scripts set the content within it. The most reliable way is putting the empty
aria-live="polite" role="status"
element in the html that is served on page load. - To maximize compatibility, use a redundant
aria-live="polite"
when usingrole="status"
. - To maximize compatibility, use a redundant
aria-live="assertive"
when usingrole="alert"
. aria-live="assertive" role="alert"
is rarely appropriate. Only use it for messages that truly require immediate attention.aria-live="assertive" role="alert"
means that the message will interrupt any text currently being read aloud by a screen reader, mid-word if necessary. This can be disruptive to users.- If the message is non-critical, use
role="status"
instead. This will still be read aloud, but the screen reader will finish reading the current element. - Icon and background colors have been tested to conform with accessibility requirements. Do not choose new colors.
- Icon styles are intentionally associated with the type of alert. Do not choose new icons.
- Update behavior of a live region can be customized. See use of
aria-relevant
andaria-atomic
if you need to send consecutive updates to a live region between page loads. Ensure that you test in multiple screen readers to check that these attributes do what you expect. - Make sure the proper heading level is chosen for the alert title to ensure it sits in the page hiearchy correctly.
Notes on the use of aria-live
and role
Static alerts, that are present and complete with their message text when the page loads, should not use either of these attributes. This is the scenario where a form is submitted to the server and a full page is returned with a notification of alerts or errors.
The attributes aria-live
and role
are used to specify behavior of a container that will be updated with new content after page load. When used as shown in the examples, these attributes have the same effect and are used together to maximize compatibility across assistive technology.
Only pages that will detect and present alert notifications in between page loads should use these attributes. aria-live
and role
control how a screen reader will interrupt a user to announce the dynamic message injected into the alert. The aria-live="polite" role="status"
attribute pairing will announce the content injected into it after a screen reader reaches a natural pause point. This is preferred almost all the time. The aria-live="assertive" role="alert"
attribute paring will interrupt whatever the screen reader is currently reading. This can be jarring to the user and often harms comprehension.