Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Doug Neiner
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Doug Neiner@dougneiner )

Accessibility And Styled Anchor Links vs. Styled Buttons In Angular 7.2.15

By Ben Nadel on

After reading Accessibility For Everyone by Laura Kalbag, I've become more aware of the accessibility short-comings in my application interfaces. Of particular note is the fact that Anchor Links aren't keyboard accessible; at least, not by default. Yesterday, I demonstrated how to make anchor links keyboard accessible in Angular; but, the exercise in augmentation begs the question: is the anchor link even the right choice of Element? According to Marcy Sutton, probably not. Anchor links are for "resource links" whereas Buttons are for triggering discrete actions. And, as it turns out, Buttons happen to be much more accessible by default. As such, I wanted to take a quick look at styling Buttons in an Angular 7.2.15 application.

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

Marcy Sutton has a good explanation of the Button in her blog post; but, to sum up some of the key points, the Button element provides a number of benefits over the Anchor link element (in certain situations):

  • Buttons are naturally keyboard accessible without any additional effort, HTML markup, or Angular directives.

  • Buttons can be triggered with both the Enter key and the Spacebar key.

  • Buttons are more semantically correct when they are used to trigger a discrete action, like deleting an item, opening a pop-up content area, or changing the state of a toggle (which makes a difference in how Screen Readers announce them).

All of this makes me think that a good portion of the Anchor links in my current Angular applications should actually but Button elements. As such, I wanted to put together a quick demo to showcase the fact that a tags and button tags are both highly modifiable from a CSS stand-point.

To demonstrate, I have a simple App component that lists two sets of interactive elements: one set uses the a tag; the other set uses the button tag:

<p>
	<a href="#">Native Href link</a> (experiment control)
</p>

<p>
	Styled <code>&lt;A&gt;</code> elements:
</p>

<div class="actions">
	<a (click)="logClick( 'Download item one' )">
		<svg aria-hidden="true">
			<use xlink:href="#sprite-button-icon" />
		</svg>
		Download One
	</a>
	<a (click)="logClick( 'Download item two' )">
		<svg aria-hidden="true">
			<use xlink:href="#sprite-button-icon" />
		</svg>
		Download Two
	</a>
	<a (click)="logClick( 'Download item three' )">
		<svg aria-hidden="true">
			<use xlink:href="#sprite-button-icon" />
		</svg>
		Download Three
	</a>
</div>

<p>
	Styled <code>&lt;BUTTON&gt;</code> elements:
</p>

<div class="actions">
	<button (click)="logClick( 'Download item one' )">
		<svg aria-hidden="true">
			<use xlink:href="#sprite-button-icon" />
		</svg>
		Download One
	</button>
	<button (click)="logClick( 'Download item two' )">
		<svg aria-hidden="true">
			<use xlink:href="#sprite-button-icon" />
		</svg>
		Download Two
	</button>
	<button (click)="logClick( 'Download item three' )">
		<svg aria-hidden="true">
			<use xlink:href="#sprite-button-icon" />
		</svg>
		Download Three
	</button>
</div>

<!--
	NOTE: Usually, the SVG spite is placed high in the document. However, for this demo,
	I am placing it low down just to get it out of the way. It still seems to function
	as you would hope.
-->
<svg style="display: none ;">
	<symbol id="sprite-button-icon" viewBox="0 0 24 16" aria-labelledby="sprite-button-icon-label">
		<title id="sprite-button-icon-label">
			Download Icon
		</title>
		<path d="M19.4,6 C18.7,2.6 15.7,0 12,0 C9.1,0 6.6,1.6 5.4,4 C2.3,4.4 0,6.9 0,10 C0,13.3 2.7,16 6,16 L19,16 C21.8,16 24,13.8 24,11 C24,8.4 21.9,6.2 19.4,6 L19.4,6 Z M17,9 L12,14 L7,9 L10,9 L10,5 L14,5 L14,9 L17,9 L17,9 Z" />
	</symbol>
</svg>

As you can see, the a and button elements are essentially identical. They all have a (click) event-handler (function not show in this demo). And, they all include an SVG icon. And, when we render them, they look exactly the same. The main difference is that the button elements are much more accessible:

Demonstration that Button elements can be styled and are highly accessible in Angular 7.2.15.

The button element does require a tiny bit more CSS, particularly around Font style; but, as you can see in the following LESS CSS, both the a tag and the button tag are equally flexible:

:host {
	display: block ;
	font-size: 18px ;
}

.actions {
	display: flex ;
	font-family: monospace ;
	margin: 20px 0px 30px 0px ;

	a,
	button {
		align-items: center ;
		background-color: #f0f0f0 ;
		border: 1px solid #e0e0e0 ;
		border-radius: 5px 5px 5px 5px ;
		color: #ff3366 ;
		cursor: pointer ;
		display: flex ;
		font-family: inherit ; // Needed for Button.
		font-size: inherit ; // Needed for Button.
		margin-right: 10px ;
		padding: 10px 15px 10px 12px ;

		// Only CHROME seems to show a nice beefy outline by default; as such, in order
		// to get the focus styling more consistent, I am going to override the outline
		// and then use a box-shadow. This works the same in the major desktop browsers.
		&:focus,
		&:active {
			outline: none ;
			box-shadow: 0px 0px 2px 4px #ff3366 ;
		}
	}

	svg {
		fill: #ff3366 ;
		height: 16px ;
		margin-right: 13px ;
		width: 24px ;
	}
}

As you can see, it really takes no additional effort to style a button element. This may not have been true years ago; but, it is certainly true today in all modern browsers.

Now, to be clear, I am very much an accessibility novice. At this point, I'm just trying to become more aware of my own knowledge gaps; and, I'm starting to baby-step towards a more holistic understanding of my users. So, I won't get into any deeper explanation of semantic HTML or element selection. But, I will certainly be trying to use the button element in more places within my Angular applications, especially when the goal of the UI (user interface) interaction is to trigger a non-routable, discrete action. I believe this will naturally create a more accessible and intuitive experience.

ASIDE: Part of creating a "more intuitive" experience is not removingthe native focus and active indicators. For years, I've been told by designers (and by my own biased aesthetic) to remove the "outline" that shows up around an active element. Going forward, however, I will be trying to champion such accessible interface features, not trying to suppressing them.



Reader Comments

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.