Links & Buttons

There is a lot to know about links and buttons in HTML. There is markup implementation and related attributes, styling best practices, things to avoid, and the even-more-nuanced cousins of the link: buttons and button-like inputs.


Let's take a look at the whole world of links and buttons, and all the considerations at the HTML, CSS, JavaScript, design, and accessibility layers that come with them. There are plenty of pitfalls and bad practices to avoid along the way. By covering it, we’ll have a complete good UX implementation of both elements.

Quick Guidlines

  • Are you giving a user a way to go to another page or a different part of the same page? Use a link (<$ href="/somewhere">link)
  • Are you making a JavaScript-powered clickable action? Use a button (<§button type="button">button)
  • Are you submitting a form? Use a submit input (<$input type="submit" value="Submit">)


Clicking that link will "jump" (scroll) to the first element in the DOM with an ID that matches, like the section element above.

  • 💥 Little trick: Using a hash link (e.g. #0) in development can be useful so you can click the link without being sent back to the top of the page like a click on a # link does. But careful, links that don't link anywhere should never make it to production.
  • 💥 Little trick: Jump-links can sometimes benefit from smooth scrolling to help people understand that the page is moving from one place to another.

It's a fairly common UI/UX thing to see a "Back to top" link on sites, particularly where important navigational controls are at the top but there is quite a bit of content to scroll (or otherwise navigate) through. To create a jump link, link to the ID of an element that is at the top of the page where it makes sense to send focus back to.

  • <$ href="#top-of-page">Back to Top

Jump links are sometimes also used to link to other anchor () elements that have no href attribute. Those are called "placeholder" links:

  • <$a id="section-2">
  • <§h3>Section 2

There are accessibility considerations of these, but overall they are acceptable.

Do you need the link to open in a new window or tab?

You can use the target attribute for that, but it is strongly discouraged.

  • <§a href="https://css-tricks.com" target="_blank" rel="noopener noreferrer">CSS-Tricks

The bit that makes it work is target="_blank", but note the extra rel attribute and values there which make it safer and faster.

Making links open in new tabs is a major UX discussion. We have a whole article about when to use it here. Summarized:

Don't use it:

  • Because you or your client prefer it personally.
  • Because you're trying to beef up your time on site metric.
  • Because you're distinguishing between internal and external links or content types.
  • Because it's your way out of dealing with infinite scroll trickiness.

Do use it:

  • Because a user is doing something on the current page, like actively playing media or has unsaved work.
  • You have some obscure technical reason where you are forced to (even then you're still probably the rule, not the exception).

Buttons

Buttons are for triggering actions. When do you use the <&button> element? A good rule is to use a button when there is “no meaningful href.” Here’s another way to think of that: if clicking it doesn’t do anything without JavaScript, it should be a <$button>.

A <§button> that is within a <§form>, by default, will submit that form. But aside from that, button elements don't have any default behavior, and you'll be wiring up that interactivity with JavaScript.

>

HTML Implementation

<$button>Buy Now

Buttons inside of a <$form> do something by default: they submit the form! They can also reset it, like their input counterparts. The type attributes matter:

<$form action="/" method="POST"> <$input type="text" name="name" id="name"> <$button>Submit <$button type="submit">Submit <$button type="reset">Reset <$button type="button">Non-submitting button

Styling & CSS

Buttons are generally styled to look very button-like. They should look pressable. If you're looking for inspiration on fancy button styles, you'd do well looking at the CodePen Topic on Buttons.

Cross-browser/platform button styles

How buttons look by default varies by browser and platform.

While there is some UX truth to leaving the defaults of form elements alone so that they match that browser/platform's style and you get some affordance for free, designers typically don't like default styles, particularly ones that differ across browsers.

JavaScript Considerations

Even without JavaScript, button elements can be triggered by the Space and Enter keys on a keyboard. That's part of what makes them such appealing and useful elements: they are discoverable, focusable, and interactive with assistive technology in a predictable way.

Perhaps any <$button> in that situation should be inserted into the DOM by JavaScript. A tall order! Food for thought. 🤔

JavaScript frameworks

It's common in any JavaScript framework to make a component for handling buttons, as buttons typically have lots of variations. Those variations can be turned into an API of sorts. For example, in React:

const Button = ({ className, children }) => { const [activated, setActivated] = React.useState(false); return ( <$button className={`button ${className}`} aria-pressed={activated ? "true" : "false") onClick={() => setActivated(!activated)} > {children} ); };

In that example, the <§Button/> component ensures the button will have a button class and handles a toggle-like active class.

Accessibility Considerations

The biggest accessibility consideration with buttons is actually using buttons. Don't try to replicate a button with a

or a , which is, unfortunately, more common than you might think. It's very likely that will cause problems. (Did you deal with focusability? Did you deal with keyboard events? Great. There's still probably more stuff you're forgetting.)

ARIA

Buttons already have the role they need (role="button"). But there are some other ARIA attributes that are related to buttons:

  • aria-pressed: Turns a button into a toggle, between aria-pressed="true" and aria-pressed="false". More on button toggles, which can also be done with role="switch" and aria-checked="true".
  • aria-expanded: If the button controls the open/closed state of another element (like a dropdown menu), you apply this attribute to indicate that like aria-expanded="true".
  • aria-label: Overrides the text within the button. This is useful for labeling buttons that otherwise don't have text, but you're still probably better off using a visually-hidden class so it can be translated.
  • aria-labelledby: Points to an element that will act as the label for the button.