Calculator
Modern websites may have calculator functionality which allows users to perform mathematical calculations. These calculators SHOULD be accessible for all users as well.
NOTE:
- New to accessibility or uncertain of requirements, it will be helpful to review all sections below.
- Already familiar with requirements, skip to the “Working Example” section for sample HTML, CSS and JavaScript (when needed), along with a working demo.
- Keyboard support MUST be present for all interactive elements in the calculator.
- Accessible name MUST be defined for all interactive elements in the calculator. For more information, refer to the Images and Buttons with Identical Names components.
-
For color contrast requirements pertaining to textual and non-textual content, refer to the
Color Contrast component.
For example –- For textual interactive elements and textual results displayed, the color contrast MUST be at least 4.5:1 against the background color if it is standard text in default state (in case of interactive elements, it is applicable in focused and hover states as well).
- The contrast requirement of 3:1 ratio MUST be met with the adjacent colors for the custom focus indicator for the interactive elements.
-
Provide an accessible name to the input field used to display the calculated answer using a
title
oraria-label
attribute. -
On activating any of the interactive elements used to enter the values to be calculated, ensure that
dynamic updates are announced for screen reader users.
-
Provide
aria-live="polite"
attribute orrole="status"
to the container such as<div>
element used to display the results. This will ensure the dynamic update to the screen reader users is announced. For more information on how to handle the announcements, refer to the Dynamic Update component.
-
Provide
- A clear focus indicator SHOULD be provided for all interactive components in the calculator.
- Provide keyboard shortcuts for users so that they can easily access the calculator. For example, a keyboard shortcut to switch focus between the keypad and the answer area can be provided for ease of access. For more information on ensuring the keyboard shortcuts are implemented in an accessible manner, refer to the Character Key Shortcuts component.
- Ensure that all elements of the calculator ARE visible in Windows High Contrast mode.
- Ensure that text CAN be resized at 200% zoom and reflow at 400% zoom modes. For more information on meeting this requirement, refer to the Reflow component.
- An Esc key mechanism SHOULD be implemented to clear the values. Also, feedback SHOULD be announced when the values are cleared. For example, feedback stating, the values cleared from the screen.
- The value entered SHOULD get calculated in the answer area using an Enter key. For example, if any value is entered in the field that is to be calculated (5+5), on pressing Enter key, the results should be displayed.
- The screen and the control areas CAN be defined within a region along with an accessible name for the region. For more information, refer to Landmarks component.
-
All the interactive elements SHOULD be navigable using Tab and Shift+Tab keys.
Also, they SHOULD be navigable using arrow keys (e.g., left, right)
For example,<div class="calc"> <div class="calc__header"> <h1 class="calc__heading">Calculator</h1> </div> <!-- Calculator display --> <div class="calc__display"> <p id="display"> <span class="sr-only" aria-live="polite" id="sr-info"></span> <span id="display-screen" aria-hidden="true">0</span> </p> </div> // Calculator buttons <div class="calc__keypad-wrapper"> <div class="calc__keypad" id="keypad" role="grid" aria-label="Calculator Keypad"> <div role="row" class="calc__keypad__row"> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-num js-calc-btn" id="7" type="button" tabindex="0">7</button> </span> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-num js-calc-btn" id="8" type="button" tabindex="-1">8</button> </span> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-num js-calc-btn" id="9" type="button" tabindex="-1">9</button> </span> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-func js-calc-btn" id="delete" type="button" aria-label="Backspace" tabindex="-1">delete </button> </span> </div> <div role="row" class="calc__keypad__row"> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-num js-calc-btn" id="4" type="button" tabindex="-1">4</button> </span> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-num js-calc-btn" id="5" type="button" tabindex="-1">5</button> </span> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-num js-calc-btn" id="6" type="button" tabindex="-1">6</button> </span> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-num js-calc-btn" id="+" type="button" aria-label="Add by" tabindex="-1">+</button> </span> </div> (…) <div role="row" class="calc__keypad__row"> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-func js-calc-btn" id="Reset" type="button" aria-label="Reset" tabindex="-1">reset</button> </span> <span role="gridcell" class="calc__keypad__gridcell"> <button class="calc__btn btn-equals js-calc-btn" id="Equals" type="button" aria-label="Equals" tabindex="-1">=</button> </span> </div> </div> <div class="grid__NUX hidden" id="grid-nux" role="region" aria-label="Calculator Keypad Instructions" tabindex="0"> <p> Move keyboard focus inside the keypad with arrow keys. Press <code>Space</code> to activate key. </p> <p> Press Home to jump to the top left key (7). Press End to jump to the last key (=). </p> <p> You can also use number keys and numeric keyboard. Press Enter to calculate. </p> <button id="close-nux-btn">Close Tutorial</button> </div> </div> </div>
A well-defined calculator majorly benefit the below users.
- People with cognitive disabilities
- People with visual disabilities
- People using speech input
- People using keyboard only
- People with limited dexterity
<body class="dark-theme" id="body">
<main>
<div class="calc__wrapper">
<div class="calc">
<div class="calc__header">
<h1 class="calc__heading">Calculator</h1>
</div>
<div class="calc__display">
<p id="display">
<span class="sr-only" role="alert" aria-live="assertive"
aria-atomic="true" aria-relevant="additions text"
id="sr-info"></span>
<span id="display-screen" aria-hidden="true">0</span>
</p>
</div>
<div class="calc__keypad-wrapper">
<div class="calc__keypad" id="keypad" role="grid"
aria-label="Calculator Keypad"></div>
<div class="grid__NUX hidden" id="grid-nux" role="region"
aria-label="Calculator Keypad Instructions"
tabindex="0">
<p>
Move keyboard focus inside the keypad with arrow keys.
Press <code>Space</code> to activate key.
</p>
<p>
Press Home to jump to the top left key (7). Press End
to jump to the last key (=).
</p>
<p>
You can also use number keys and numeric keyboard.
Press Enter to calculate.
</p>
<button id="close-nux-btn">Close Tutorial</button>
</div>
</div>
</div>
</div>
</main>
</body>
.dark-theme {
--bg-color: hsl(222, 26%, 31%);
--keypad-bg: hsl(223, 31%, 20%);
--display-bg: hsl(224, 36%, 15%);
--display-text: hsl(0, 100%, 100%);
--equals-key-bg: hsl(225, 21%, 49%);
--equals-key-shadow: hsl(224, 28%, 35%);
--equals-key-text: hsl(0, 100%, 100%);
--equals-key-hover: hsl(224, 51%, 76%);
--function-key-bg: hsl(6, 63%, 50%);
--function-key-hover: hsla(6, 93%, 67%, 1);
--function-key-shadow: hsl(6, 70%, 34%);
--function-key-text: hsl(0, 100%, 100%);
--number-key-bg: hsl(30, 25%, 89%);
--number-key-hover: hsl(31, 100%, 100%);
--number-key-shadow: hsl(28, 16%, 65%);
--number-key-text: hsl(221, 14%, 31%);
--focus-color: hsl(223, 31%, 20%);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: inherit;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: var(--bg-color);
font-family: 'Spartan', sans-serif;
transition: background-color 200ms ease-in-out;
}
main {
width: 100%;
}
.calc__wrapper {
margin: 0 auto;
padding: 2rem 1.5rem;
max-width: 37rem;
}
.calc__header {
display: flex;
justify-content: space-between;
align-items: flex-end;
height: 2.75rem;
margin-bottom: 1.5rem;
}
.calc__heading {
font-size: 2rem;
line-height: 2rem;
color: var(--display-text);
}
.calc__display {
margin-bottom: 1.5rem;
padding: 1.5rem 1.625rem;
background-color: #fff;
border-radius: 0.625rem;
height: 5.375rem;
font-size: 2rem;
font-weight: 700;
text-align: right;
color: hsl(224, 36%, 15%);
transition: background-color 200ms ease-in-out, color 200ms ease-in-out;
}
.calc__display span.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
.calc__keypad-wrapper { position: relative; }
.calc__keypad {
display: grid;
grid-template-rows: repeat(5, 1fr);
gap: 0.75rem;
justify-items: stretch;
padding: 1.5rem;
background-color: #fff;
border-radius: 0.625rem;
transition: background-color 200ms ease-in-out;
}
.calc__keypad__row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.75rem;
width: 100%;
}
.calc__keypad__gridcell {
display: block;
width: 100%;
}
.calc__keypad__row:last-of-type .calc__keypad__gridcell {
grid-column: span 2;
}
.calc__btn {
padding: 0.625rem 0 0.875rem;
width: 100%;
border: 0;
border-radius: 0.625rem;
font-size: 1.75rem;
font-weight: 700;
line-height: 2.25rem;
cursor: pointer;
transition: background-color 0.2s ease-in-out, transform 0.2s ease-in-out;
}
.calc__btn:focus {
outline: 3px solid var(--equals-key-bg);
outline-offset: 2px;
}
.calc__btn:active,
.calc__btn.active {
transform: scale(0.9);
}
.btn-num {
background-color: var(--number-key-bg);
color: var(--number-key-text);
box-shadow: inset 0 -0.25rem 0 var(--number-key-shadow);
}
.btn-num:hover,
.calc__btn.active {
background-color: var(--number-key-hover);
}
.btn-func {
background-color: var(--function-key-bg);
color: var(--function-key-text);
box-shadow: inset 0 -0.25rem 0 var(--function-key-shadow);
color: var(--function-key-text);
font-size: 1rem;
text-transform: capitalize;
}
.btn-func:hover,
.btn-func.active {
background-color: var(--function-key-hover);
}
.btn-equals {
background-color: var(--equals-key-bg);
color: var(--equals-key-text);
box-shadow: inset 0 -0.25rem 0 var(--equals-key-shadow);
font-size: 1.5rem;
}
.btn-equals:hover,
.btn-equals.active {
background-color: var(--equals-key-hover);
}
.btn-equals:focus {
outline: 3px solid var(--function-key-bg);
outline-offset: 2px;
}
.grid__NUX {
display: flex;
flex-direction: column;
position: absolute;
top: 5rem;
left: 1.5rem;
width: calc(100% - 3rem);
border-radius: 5px;
padding: 1rem;
background: var(--bg-color);
color: var(--display-text);
}
.grid__NUX:focus {
outline: 3px solid var(--equals-key-bg);
outline-offset: 2px;
}
.grid__NUX p {
margin-bottom: 0.75rem;
line-height: 1.5rem;
}
.grid__NUX button {
background: transparent;
padding: 0.5rem;
border: 0;
text-decoration: underline;
color: var(--display-text);
cursor: pointer;
align-self: flex-end;
}
.grid__NUX button:focus {
outline: 3px solid var(--equals-key-bg);
outline-offset: 2px;
}
.grid__NUX.hidden { display: none; }
@media screen and (min-width: 500px) {
.calc__display {
padding: 1.8rem 2.25rem;
height: 7rem;
font-size: 3rem;
}
.calc__keypad {
gap: 1rem;
padding: 1.5rem 1.8rem;
}
.calc__btn { font-size: 2rem; }
.btn-func { font-size: 1.25rem; }
.btn-equals { font-size: 1.75rem; }
.grid__NUX {
width: 70%;
top: 6rem;
left: 2rem;
}
}
Calculator
0
Move keyboard focus inside the keypad with arrow keys. Press Space
to activate key.
Press Home to jump to the top left key (7). Press End to jump to the last key (=).
You can also use number keys and numeric keyboard. Press Enter to calculate.