You can add an icon to a button as an inline image enclosed in a span with the class mzp-c-button-icon-start if the icon appears before the text label or mzp-c-button-icon-end if it appears after the label.

You can optionally use a standard unicode character or symbol, but be aware not all platforms will support all characters. Icon fonts are also an option, with all the usual caveats about using webfonts. You can use an emoji but they also may not be supported equally across platforms and even on supporting platforms they’ll be rendered in completely different styles by different systems. For consistency and reliability, use an image.

Tips

  • Prefer simple, single-color icons. Complex images likely won’t render well at such a small size. Multicolored icons or logos may not adapt to different backgrounds as the button state changes.

  • Prefer embedded SVG over an external img (whether SVG or other format). An inline SVG icon can more easily change color for the different button states and style variants. Be aware that very old browsers don’t support SVG.

  • Consider the text direction of the page language. Arrows in particular indicate a specific orientation that may be confusing in text that flows the opposite direction. The “Next” and “Previous” buttons shown here are a good example of how this can go wrong. In a right-to-left language, the “Next” arrow moves to the left of the text label, but still points to the right. A properly bi-directional design should reverse those icons as well.

Tips for inline SVG

  • Optimize SVG files for embedding inline in the HTML document. Strip out unnecessary comments or metadata added by editing tools. Use SVGO either locally on online.

  • Merge shapes and paths where possible to reduce the number of elements and points.

  • Avoid unnecessary grouping of elements.

  • Define colors with currentColor. This will inherit the icon’s color from the button text, including color changes in hover and focus states. An icon with its own defined colors will need to accommodate background color changes, either with a color that is visible on all backgrounds, or facilitating a color change some other way besides currentColor (e.g. with additional CSS).

No-Nos

  • Don’t add multiple icons to a button. Technically Protocol doesn’t prevent it, it’s just a bad idea.
<p>
    <button class="mzp-c-button" type="button">Button with Icon
        <span class="mzp-c-button-icon-end">
            <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 24 24" width="24" height="24" fill="currentColor">
                <path d="m21.3 4.5-8-4c-.8-.4-1.8-.4-2.7 0l-8 4C1.6 5.1 1 6.1 1 7.2v9.5c0 1.1.6 2.2 1.7 2.7l8 4c.4.2.9.3 1.3.3s.9-.1 1.3-.3l8-4c1-.5 1.7-1.5 1.7-2.7V7.2c0-1.1-.6-2.1-1.7-2.7zm-9.7-2.2c.1-.1.3-.1.4-.1.2 0 .3 0 .4.1L19.8 6 12 9.9 4.2 6l7.4-3.7zm-8 15.4c-.4-.2-.6-.6-.6-.9V7.6l8 4v9.8l-7.4-3.7zm16.8 0L13 21.4v-9.8l8-4v9.2c0 .3-.2.7-.6.9z" />
            </svg>
        </span>
    </button>
</p>

<p>
    <button class="mzp-c-button" type="button">
        <span class="mzp-c-button-icon-start">
            <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 24 24" width="24" height="24" fill="currentColor">
                <path d="m21.3 4.5-8-4c-.8-.4-1.8-.4-2.7 0l-8 4C1.6 5.1 1 6.1 1 7.2v9.5c0 1.1.6 2.2 1.7 2.7l8 4c.4.2.9.3 1.3.3s.9-.1 1.3-.3l8-4c1-.5 1.7-1.5 1.7-2.7V7.2c0-1.1-.6-2.1-1.7-2.7zm-9.7-2.2c.1-.1.3-.1.4-.1.2 0 .3 0 .4.1L19.8 6 12 9.9 4.2 6l7.4-3.7zm-8 15.4c-.4-.2-.6-.6-.6-.9V7.6l8 4v9.8l-7.4-3.7zm16.8 0L13 21.4v-9.8l8-4v9.2c0 .3-.2.7-.6.9z" />
            </svg>
        </span>
        Button with Icon</button>
</p>

<p>
    <a class="mzp-c-button mzp-t-xl mzp-t-product" href="https://www.mozilla.org/firefox/new/">Download Firefox
        <span class="mzp-c-button-icon-end">
            <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
                <path d="M8 13c.2 0 .4-.1.5-.2l4.4-4.4-1.1-1.1-3.1 3.1V1H7.2v9.4L4.1 7.3l-1 1.1 4.4 4.4c.1.1.3.2.5.2z" />
                <path d="M13.5 12v2c0 .3-.2.5-.5.5H3c-.3 0-.5-.2-.5-.5v-2H1v2c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2v-2h-1.5z" />
            </svg>
        </span>
    </a>
</p>

<p>
    <button class="mzp-c-button mzp-t-product mzp-t-secondary" type="button">
        <span class="mzp-c-button-icon-start">
            <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
                <path d="M12 15H4c-1.1 0-2-.9-2-2V2c0-1.1.9-2 2-2h8c1.1 0 2 .9 2 2v11c0 1.1-.9 2-2 2zM4 1.5c-.3 0-.5.2-.5.5v11c0 .3.2.5.5.5h8c.3 0 .5-.2.5-.5V2c0-.3-.2-.5-.5-.5H4z" />
                <path d="M5.5 3.5h5V5h-5z" />
                <path d="M5.5 6.5h5V8h-5z" />
                <path d="M5.5 9.5h3V11h-3z" />
            </svg>
        </span>
        Try Reader Mode</button>
</p>

<p>
    <a class="mzp-c-button mzp-t-sm mzp-t-secondary" href="#">
        <span class="mzp-c-button-icon-start">
            <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
                <path d="m1.2 7.7 5.5-5.5 1.1 1.1-4.2 4.2H15V9H3.6l4.2 4.2-1.1 1.1-5.5-5.5c-.1-.2-.2-.4-.2-.6s.1-.3.2-.5z" />
            </svg>
        </span>
        Previous</a>

    <a class="mzp-c-button mzp-t-sm mzp-t-secondary" href="#">Next
        <span class="mzp-c-button-icon-end">
            <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
                <path d="M14.8 7.7 9.3 2.2 8.2 3.3l4.2 4.2H1V9h11.4l-4.2 4.2 1.1 1.1 5.5-5.5c.1-.2.2-.4.2-.6s-.1-.3-.2-.5z" />
            </svg>
        </span>
    </a>
</p>

<p>
    <button class="mzp-c-button" type="button">Character
        <span class="mzp-c-button-icon-end">
            ❤︎
        </span>
    </button>
</p>

<p>
    <button class="mzp-c-button" type="button">Emoji
        <span class="mzp-c-button-icon-end">
            ❤️
        </span>
    </button>
</p>