Components for AaSH (ARIA augmented Semantic HTML)
    Preparing search index...

    Using Icons with unstyled components

    A common approach to displaying icons is to assign a class to an element that determines which icon to display. This makes it difficult to change the icon later using CSS.

    The approach proposed here is to treat an icon as an alternative visual representation of text. We start with a textual description of an action such as <button><span>Select language</span></button>. For a more compact presentation, the text can be visually replaced with an icon. This can be achieved with CSS like this:

    button {
        // Make text invisible, but preserve it for screen readers
        * {
            position: absolute;
            width: 1px;
            height: 1px;
            padding: 0;
            margin: -1px;
            overflow: hidden;
            clip-path: inset(50%);
            white-space: nowrap;
            border: 0;
        }
    
        &::before {
            content: "";
            display: inline-block;
            width: 1em;
            height: 1em;
            vertical-align: middle;
    
            background-color: currentColor;
            mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...");
            mask-repeat: no-repeat;
            mask-position: center;
            mask-size: contain;
        }
    }
    

    Of course, using button as selector is too broad. It must be replaced with a more specific selector that targets only the button used for choosing the language.

    Also note that any text must be wrapped in a child element to make it invisible. There is no way to make DOM text (child) nodes invisible without making the element itself invisible. Using content: "" comes to mind, but using it on an element (not a pseudo-element) has no effect.

    Unfortunately, neither HTML elements with their attributes nor ARIA attributes (such as role) provide a reliable way to identify an element's specific purpose. Users typically infer an element's purpose from its text or, when no visible text is available, from an accessible name provided through an attribute such as aria-label. However, both may be localized, making them unsuitable for identifying elements in CSS selectors.

    The approach proposed here is to use a data-purpose attribute to specify an element's purpose. Possible values include:

    Value Description
    add-card Add a card to e.g. a dashboard.
    choose-language Choose a language.
    open-help Open a help dialog.
    open-settings Open a settings dialog.
    remove-item Remove an item. The common representation as an icon is "x". Removing should be interpreted in the widest sense. "Closing a dialog" is also considered "removing".
    show-expanded Display an expanded view.

    These values are based on practical experience with the JGrapes Web Console framework and are by no means exhaustive.

    Since data-purpose can also be useful for styling the UI independently of icon selection, it should not, by itself, imply that an element must be represented by an icon. Instead, icon styling should be activated explicitly through the as-icon class. The resulting CSS might look like this:

    .as-icon {
        // Make text invisible, but preserve it for screen readers
        * {
            position: absolute;
            width: 1px;
            height: 1px;
            padding: 0;
            margin: -1px;
            overflow: hidden;
            clip-path: inset(50%);
            white-space: nowrap;
            border: 0;
        }
        
        &::before {
            content: "";
            display: inline-block;
            width: 1em;
            height: 1em;
            vertical-align: middle;
    
            background-color: currentColor;
    
            mask-repeat: no-repeat;
            mask-position: center;
            mask-size: contain;
        }
    
        &[data-purpose="choose-language"]::before {
            mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...");
        }
    }