Skip to content

Link Button

A link button is an <a> that looks like a button. Put af-btn on the anchor. Default text links stay underlined; a.af-btn opts out of that and picks up padding, radius, and intent colors.

Use this when the control navigates (OAuth start, “Get started”, download). Use <button class="af-btn"> when it does something on the page (submit, toggle, open a dialog).

  • Link button — the href is the destination. Middle-click, copy URL, and open-in-new-tab keep working.
  • Text link — inline or quiet navigation that should read as text. See Link.
  • Button — no URL, or the URL is a side effect of an action. See Button.

Do not wrap a <button> in an <a>. Do not fake navigation with window.location on a <button>.

<a href="#" class="af-btn">Get started</a>
<a href="#">Forgot password?</a>
<a href="#" class="af-btn">Get started</a>

Same af-is-* modifiers as Button. Primary is the default. Secondary and outline are a good fit for OAuth and sibling CTAs.

<a href="#" class="af-btn">Get started</a>
<a href="#" class="af-btn af-is-secondary">Continue with Google</a>
<a href="#" class="af-btn af-is-outline">Learn more</a>
<a href="#" class="af-btn af-is-danger">Delete account</a>

Full intent list: Button variants.

<a href="#" class="af-btn af-is-sm">Small</a>
<a href="#" class="af-btn">Default</a>
<a href="#" class="af-btn af-is-lg">Large</a>

Stretch with af-w-full. Do not use af-block — it replaces the button’s inline-flex layout.

<a href="#" class="af-btn af-is-secondary af-w-full">Continue with Google</a>

Keep a real href. Add rel="noopener noreferrer" when using target="_blank".

<a href="https://example.com" class="af-btn" target="_blank" rel="noopener noreferrer">Open docs</a>
<a href="/app.zip" class="af-btn af-is-outline" download>Download</a>

Anchors do not support native disabled. Prefer ARIA plus the visual fallback class. See Button states.

Use aria-disabled="true" and af-is-disabled (pointer-events: none). Prefer that over removing href.

<a href="#" class="af-btn af-is-disabled" aria-disabled="true">Unavailable</a>

Prefer aria-busy="true". af-is-loading is the CSS fallback.

<a href="#" class="af-btn" aria-busy="true">Redirecting…</a>
<a href="#" class="af-btn af-is-loading">Redirecting…</a>

For nav that uses button-styled links, mark the current item with aria-current="page". af-is-active is visual-only.

<a href="#" class="af-btn" aria-current="page">Overview</a>
<a href="#" class="af-btn af-is-outline">Settings</a>
ClassRole
a.af-btnCanonical: button look on an anchor
.af-link-buttonAlias that only strips underline. Pair with af-btn for the full button look
  • Keep a real href so it is a link in the accessibility tree, not a fake button
  • Keyboard: Enter follows the link (Space is for <button>)
  • Visible focus ring is enabled by default
  • Disabled: aria-disabled="true" + af-is-disabled, not the disabled attribute
  • Icon-only link buttons need aria-label
  • Use link buttons only for navigation, not in-page actions
  • Match variants and sizes from Button — do not invent a second set of classes
  • Stretch with af-w-full, not af-block / af-is-block
  • Text that sits in a sentence or footer should stay a text link