Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Buttons and roles

Every <button> in Pico is already styled: the primary color, rounded corners, padding, a visible focus ring. Variants come from a few classes, and special behavior from accessibility attributes: role tells the browser and screen readers what an element is, and aria-* tells them what state it is in.

Button variants

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
 
<button>Subscribe</button>
<button class="secondary">Later</button>
<button class="contrast">Resume</button>
<button class="outline">All projects</button>
<button class="outline secondary">Cancel</button>
<button disabled>Unavailable</button>

The preview shows a blue, a grey and a dark button, two outlined buttons and a faded disabled one. Classes combine: outline secondary gives a grey outline.

ClassWhen to use
no classThe main action on the screen
secondaryA secondary action
contrastThe action that must stand out most
outlineA quieter version of any variant

When a button leads to another page, it is a link, not a <button>. The role="button" attribute gives the link a button look while it stays a link:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
 
<a href="#" role="button">Read the blog</a>
<a href="#" role="button" class="outline">Portfolio</a>

Two links look like buttons. The same variant classes work here too.

Button group and loading

The role="group" attribute on a wrapper joins the buttons into one strip. The aria-busy="true" attribute shows a spinner — that is how a button says an action is in progress:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
 
<div role="group">
  <button>All</button>
  <button class="secondary">CSS</button>
  <button class="secondary">HTML</button>
</div>
<button id="save">Save draft</button>
 
<script>
  const save = document.querySelector('#save');
  save.addEventListener('click', () => {
    save.setAttribute('aria-busy', 'true');
    save.textContent = 'Saving…';
    setTimeout(() => {
      save.removeAttribute('aria-busy');
      save.textContent = 'Saved';
      console.log('Draft saved');
    }, 1500);
  });
</script>

At the top there are three filter buttons in one strip. Click "Save draft": for a second and a half a spinner turns in the button, then the label changes and a message appears under the example.

Tooltip

The data-tooltip attribute shows a tooltip on hover, and data-placement="bottom" moves it below:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
 
<p style="margin-top: 3rem">
  <button data-tooltip="PDF file, 120 KB">Download resume</button>
</p>

Hover over the button and a dark label with the text appears above it. The top margin gives the tooltip room in the preview.

Common mistake

Making a button out of a <div> with a click handler and role="button". It looks like a button but cannot be used from the keyboard: you cannot Tab to it and press Enter. Use <button> for actions, <a href> for navigation, and put role="button" only on links.

Thanks for reading!

Donate to the site — we work hard for you.