State and <main>

Providing feedback to the user action: a tour of the different UI component states.

An important part of a UI designer job when designing interfaces it's providing feedback to the users about the status of the components, to have a clear understanding about when they're over an element, when a link was already visited, when something is loading or when the information they just filled in the input is correct.

Meme of Vince McMahon reaction about providing feedback to teammates, boss and users. Fig. 1 - Providing feedback to your users.

So, what is a state? The Accessible Rich Internet Applications (WAI-ARIA) 1.2 describes it as: "A state is a dynamic property expressing characteristics of an object that may change in response to user action or automated processes."

I'll try to cover some of the most common states a designer should think about...

User action pseudo-classes

Examples of a button styles when enabled, hovered, focused and active Examples of a button styles when enabled, hovered, focused and active Examples of a button styles when enabled, hovered, focused and active Examples of a button styles when enabled, hovered, focused and active Fig. 2 - Enabled, hover, focus and active button states.

The CSS user action pseudo-classes apply when the user interacts with some element:

  • :hoverThe element is being pointed by the cursor. Only works on desktop.
  • :focus The user clicks or taps on an element or selects it with the keyboard's Tab key.
  • :activeThe user press down the element.
  • :visited Represents links that have been already visited.

It's important to style all these states differently. Usually, the most subtle style changes can be applied to the :hover state, since it's easier for the user to know when they hovered over something, the :focus state change instead, needs to have more visibility since the user don't know beforehand where the next element in the tab sequence is located.

Design tip: It's possible to hide the focus styles when the user clicks or taps an element and show it only when the interaction is being made via keyboard with the :focus-within pseudo-class.

In addition, in an <input> or <textarea> components the placeholder text is displayed before the user enters a value and should be visually different. The CSS ::placeholder pseudo-class can be used to style the element state.

Disabled and read-only

Three input-text components, enabled, disabled and readonly Three input-text components, enabled, disabled and readonly Three input-text components, enabled, disabled and readonly Three input-text components, enabled, disabled and readonly Fig. 3 - Enabled versus disabled and read-only states.

These states communicate to the user that there are restrictions in the interaction with the UI element:

  • Disabled: This component is not available for interaction, it can't receive focus.
  • Readonly: The user cannot modify the value of the control, but is still focusable.

Only some of the UI components can have a readonly state, <input> and <textarea> (although maybe others should), where some relevant information to the user needs to be shown, but cannot be modified. Communicate visually when the element has some restrictions, but still allows interaction, and also when doesn't allow it.

Accessibility tip: The WCAG 2.1 Success Criterion 1.4.3: Contrast (Minimum) says that "Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement." In other words: A disabled element doesn't have a contrast requirement.

Contextual states

An input text showing an error and another input showing a success message An input text showing an error and another input showing a success message An input text showing an error and another input showing a success message An input text showing an error and another input showing a success message Fig. 4 - Error and success states.

These states show the user what's occurring in the user context. In this article, I will cover its application mainly in form inputs.

  • Error: Show the user that what they just entered is invalid.
  • Success: Show the user that what they just entered is valid.

Be careful not to design these states in such a way that they hide others (e.g. use the border-color to represent both error and :focus states, and when the element is focused on, the reference that the field had an error is lost)

Usability tip: For most of the cases, show only the error state in a component when the focus is moved to another element. Having said that, there are some cases when can be interesting to show it when the user is still interacting with the component (e.g. Exceeding the character limit in an input or textarea). Above all, it is important to avoid those cases that can cause the error to be displayed as soon as the user interacts with the field, without having entered a value yet. I'm watching you 👀

Although I listed here only error and success states, warning, info or any other contextual state needed to provide feedback to the users should be designed in a way that is understandable and scalable across components or applications.

Dragged elements and drop areas

From left to right. An enabled image, an image being dragged, and an area being highlighted when the image is dragged on top From left to right. An enabled image, an image being dragged, and an area being highlighted when the image is dragged on top From top to bottom. An enabled image, an image being dragged, and an area being highlighted when the image is dragged on top From top to bottom. An enabled image, an image being dragged, and an area being highlighted when the image is dragged on top Fig. 5 - Enabled, drag and dragover states.

These states provide feedback of an ongoing drag operation, from when an element is being dragged to when a zone is available to drop that element.

  • Dragged: This element is being pressed and dragged.
  • Dragover: Indicate that the element is a valid drop target.

According to the MDN documentation, the dragged state usually is "A translucent representation of the draggable elements" and it's a common pattern used to represent this element state. Another distinction that can be used is a drop shadow to represent the change in the z-axis position of the element when placed with other visually equal siblings.

Accessibility tip: Although aria-dropeffect and aria-grabbed are deprecated since ARIA 1.1, they remain in the spec and can be used since there are accessibility concerns related to the HTML Drag and Drop API.

  • MDN Web Docs - HTML Drag and Drop API
  • WAI-ARIA 1.2 - aria-dropeffect property
  • WAI-ARIA 1.2 - aria-grabbed state
  • Checked and unchecked / Selected and unselected

    An option list with the top option unselected, displaying an empty checkbox and the bottom one selected, displaying a checked checkbox. An option list with the top option unselected, displaying an empty checkbox and the bottom one selected, displaying a checked checkbox. An option list with the top option unselected, displaying an empty checkbox and the bottom one selected, displaying a checked checkbox. An option list with the top option unselected, displaying an empty checkbox and the bottom one selected, displaying a checked checkbox. Fig. 6 - Selected and unselected states in an option list.

    These states are engaged by checking/selecting or unchecking/deselecting an element, and they apply to checkboxes, radio buttons, and select options (among others).

  • Checked / Selected: The element has been checked or selected (by default or by the user) or all his children have been.
  • Unchecked / Unselected: The element has not been checked / selected.
  • Indeterminate: The indeterminate state indicates that the checkbox contains a sublist of selections and not all of them have been checked or unchecked.
  • Other elements where selected / unselected states can apply are: sidenav links, tabs, toggles

    Design tip: Different states can be applied to an element at the same time (e.g. a checkbox can be selected | unselected | indeterminate, hovered | focused | active and have an error). Try to define all the possibilities beforehand when designing the component interaction.

  • MDN Web Docs - CSS pseudo-class: :indeterminate
  • MDN Web Docs - CSS pseudo-class: :checked
  • Current

    A breadcrumbs component with links to the parent page and the previous, and a different styled text for the current page A breadcrumbs component with links to the parent page and the previous, and a different styled text for the current page A breadcrumbs component with a link to the parent page and a different styled text for the current page A breadcrumbs component with a link to the parent page and a different styled text for the current page Fig. 7 - Current state in a breadcrumbs component.

    Do not confuse this state with the CSS :current pseudo-class. The current state applies in a group of related elements, such as several links in a breadcrumb, steps in a multi-step flow, or the current date in a date-picker or time-picker.

    • Current: indicate that this is the current element within its group.

    The line between current and selected can be sometimes blurred, in multiple cases those states will overlap and only one visual definition needs to be made (e.g. a navigation link in a tree: the user interacted selecting it at the same time is showing the current page).

    Accessibility tip: Use the aria-current state to indicate the current item in a set of related elements.

  • WAI-ARIA 1.2 - aria-current state
  • Loading

    Two inputs type file with an element below, the item in the left is showing a loading indicator, the right one a completed sign Two inputs type file with an element below, the item in the left is showing a loading indicator, the right one a completed sign Two inputs type file with an element below, the top item is showing a loading indicator, the bottom one a completed sign Two inputs type file with an element below, the top item is showing a loading indicator, the bottom one a completed sign Fig. 8 - Loading state in a file item.

    Multiple components can have loading states: buttons, modal dialogs, autocomplete or select dialogs, file items, etc...

    • Loading: Indicate that the element is loading (I know...too obvious)

    Design tip: Design a loading indicator component with different sizes so you can reuse it across multiple scenarios: the entire screen, a portion of it, or inside a component.

    Conclusions

    • Cover every state needed to provide information about the component status.
    • When a component has multiple states at the same time (e.g. focused and error) make sure that both are visible and understandable.
    • Selected elements should be clearly visible, avoid using subtle changes in the background color or font-weight.
    • Disabled states don't need to be readable, don't use them if the information is necessary for understanding the context, use readonly instead.

    “Only second chance I know, is the chance to make the same mistake twice.”

    Bob Barrenger (Alec Baldwin) - State and main

    Me writing the second article of the year ☝️. Imposter syndrome intensifies.

    Sending my ❤️ to @emilianos for the amazing Mac cursor set!

    Next article