Menu


Link


Text that goes somewhere, in three sizes or the size of the text around it, with an optional icon; underlined, unless it stands on its own. As a button it stays in the color of the words around it and opens something where it stands.

Customize the preview


Choices
Show
Flags
View

Options


Link options
ChoiceValuesDefaultWhat it does
sizesmbk-link--size-<value>lgmdsminheritlg
Figma calls these Large, Medium and Small, each a body preset; inherit takes the size of the text around it, as in a heading or a card title.
standalonesmbk-link--standaloneOn or offOff
A link standing on its own, outside running text: underlined on hover and press only.
pressablesmbk-link--pressableOn or offOff
Words that are pressed rather than followed, such as a name that opens its card: a button in the color of the text around it, its line always there.

Partssmbk-link__iconsmbk-link__label

Examples


Usage

A link, underlined at rest.

Sizes

Three text sizes; the icon follows the text.

With icons

An icon at either end.

Standalone

A link standing on its own, in a list or a card: underlined on hover and press only.

Inherited size

Takes the size of the text around it, here a heading and a card title; the icon takes it too.

Disabled

Keeps its text, loses its address.

Guidelines


Purpose

Text that takes a person somewhere. It is set in the body face at body sizes so that it sits inside running text or stands alone as an inline action, and it carries the link color family (rest, hover, pressed, disabled) and an underline. Inside running text the underline is always there; a link standing on its own shows it on hover and press only. Inside a sentence it is part of the sentence: it wraps across lines like the words around it.

With as="button" the same words open something where they stand instead of going anywhere: a name that opens its card, or words that open a part of the page. They keep the color and size of the text around them, and the link's underline says they can be pressed.

When to use

  • Navigation inside text: "read the guide", "see all".
  • A standalone inline action that reads as text, not as a control.
  • With as="button": a piece of text that opens something about what it names, such as a name in a table cell or in a line of words that opens its card. It is the popover's opener when the words should stay words.
  • With as="button": words in a sentence that open a part of the page and have no address of their own.

When not to use

  • For an action that changes state on the page, such as saving or deleting. Use a button, ghost tone if it should read lightly, even where it could be pressed words: pressed words open something, and a control that changes things should look like one.
  • With as="button", for anything with an address. A real link opens in a new tab and copies its address, so give it href and leave as out.
  • As a button visually. The button wrapper can render a link with button classes when that is truly needed.

Usage rules

Do

  • Keep the underline on links inside paragraphs; set standalone only on a link that stands on its own, in a list, a footer or a card.
  • Keep a link's words in the label part when writing the markup by hand. A link with an icon draws its underline on the label, so words outside it would leave the line running under the icon.
  • Match the link size to the surrounding text's preset. Inside a heading or a title, which no body size matches, set the size to inherit: the link takes the text's face and keeps its underline.
  • Use as="button" for a name that opens its card, in place of a button with its look taken off.

Don't

  • Attach a click handler to a link to make it act like a button. Use as="button", which has the role and the keys.
  • Put a link inside a button or a label.
  • Put a space between the label and an icon when writing the markup by hand. The line may break at that space and leave the icon alone on the next line.
  • Put a link that belongs to a sentence in a flex or grid row with the text around it. A flex or grid parent turns the link into a block, which wraps on its own instead of with the words; keep it directly in the sentence's text.
Read the terms of service before you publish your first project.
Do

Keep the underline on links inside a paragraph, so they stand out from the words around them without relying on color.

Read the terms of service before you publish your first project.
Don't

A standalone link inside a sentence is marked by color alone and disappears for readers who cannot tell the colors apart.

Anatomy

  • The block, a real anchor. With as="button", inline words with a button's role and keys, because a real button is one box that cannot break across lines with the words around it.
  • The label part, the text. In a link with an icon, the label draws the underline, so the line stops where the words stop.
  • The icon part, before or after the label. Optional. Figma hides the leading icon by default and shows a trailing one. It sits in the line like one more letter of the word beside it, so the two are never split across lines.

Behavior

Hover darkens the text; pressed uses the pressed color. The underline sits a small gap below the words. It is quiet at rest, stronger on hover and strongest while pressed, and it is see-through at rest and on hover, so it looks the same on any surface. A standalone link draws its underline on hover and press. A disabled link keeps its text and loses its address. Without an address it is no longer a link, so a screen reader reads it as plain text; it does not say that a link is unavailable.

A link flows with the text it sits in. A long link inside a paragraph breaks across lines wherever the words around it would, and its underline follows it onto each line. An icon travels with its word: a trailing icon never starts a line on its own and a leading icon never ends one. The underline runs under the words only, never under the icon or the gap beside it, in every state. Standing alone in a flex or grid layout, a link is one line tall and wraps inside its own width if it has to.

On a touch screen a link standing on its own takes an invisible press area round its words, out to the comfortable touch target, and its look does not change. A link inside a sentence does not, so a press on the words around it never follows the link.

With as="button" the words take the color of the text around them, and its size unless size says otherwise. Under the pointer they keep that color and the line grows stronger; pressed, the words turn to the subtle text color and the line is at its strongest. Nothing but the line tells them from the words beside them, so the line stays, in a sentence or on their own, and standalone only gives them the press area on a touch screen. There is no disabled form: when there is nothing to open, write plain text.

As the popover's trigger the words stay in their line and break with it. A paragraph cannot hold the panel, so inside a p element put the popover after the paragraph and name the words with openerId.

Accessibility


What it does for you

  • It is a real anchor with an address, so Enter follows it. A link without an address is not a link; the disabled state removes the address on purpose, which leaves plain text behind.
  • With as="button" it is a button to a screen reader and a Tab stop, and Enter and Space press it, once however long they are held. Its words name it. As a popover's opener it says that it opens a dialog and whether that dialog is open.
  • Focus draws the system ring, rounded, around the whole link; a link that wraps gets a ring around each of its lines.
  • Nothing is cut short or pushed outside its container, so a link inside text still reads whole at twice the text size and at the narrowest reflow width (WCAG 1.4.4 Resize Text and 1.4.10 Reflow). Inline links wrap naturally, as the words around them do.
  • A link inside running text is underlined at rest, so it can be told from the words around it without color (WCAG 1.4.1 Use of Color).
  • Icons are decorative.
  • On a touch screen a link standing on its own takes an invisible press area round its words, out to the comfortable touch target. A link inside a sentence does not, so a press on the words around it never follows the link.

What you must do

  • Make the link text say where it goes, since the icons do not.
  • Drop the underline at rest, with the standalone flag, only on a link that stands on its own, where its place already says it is a link.
  • Use a button carrying the link's classes, not an anchor, for an action that sits among words and changes the page rather than going anywhere, such as a filter bar's Clear all. It is announced as a button and pressed with Space or Enter.
  • Set standalone on pressed words that stand on their own, such as a name in a table cell, so they take the press area on a touch screen. Leave it off inside a sentence.
  • Write the role and the keys yourself when writing pressed words by hand: role="button", tabindex="0", and Enter and Space pressing it.

How to test

  • Tab to the link: the focus ring shows around the whole link, and around each line of one that wraps, in both themes and in a forced-color mode.
  • Press Enter: the link is followed.
  • With as="button", press Enter and Space: each presses it once, the page does not scroll, and a screen reader calls it a button.
  • With a screen reader, it is read as a link by its text. A link with no address is read as plain text.
  • With text at 200% and the page 320 pixels wide, a link inside a paragraph breaks across lines with the words around it and nothing is cut off.
  • In a forced-color mode, a disabled link is drawn in the system's gray text color.
  • On a touch screen, a press just outside a standalone link's words follows it; a press on the words around a link in a sentence does not.

Keyboard

Link keys
KeyWhat it does
Tab
Moves focus to the link.
Enter
Follows the link.
EnterorSpace
Presses words with as="button", and a button carrying the link's classes.

Source


The files the link is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
link.css
/* smbk-link — Link. Figma "Link" 4129:21956.
 * An inline box, not a flex box: a link inside a sentence wraps across lines
 * like the words around it. The icon is inline too, so its glyph joins the
 * word beside it as one more letter would: a line never breaks between them,
 * and the icon travels with its word. */

.smbk-link {
  display: inline;
  color: var(--smbk-color-text-link);
  font-family: var(--smbk-typography-body-lg-font-family);
  font-size: var(--smbk-typography-body-lg-font-size);
  font-weight: var(--smbk-typography-body-lg-font-weight);
  line-height: var(--smbk-typography-body-lg-line-height);
  letter-spacing: var(--smbk-typography-body-lg-letter-spacing);
  text-decoration-line: underline;
  text-decoration-color: var(--smbk-color-text-link-underline);
  text-decoration-thickness: var(--smbk-border-width-link-underline);
  text-underline-offset: var(--smbk-space-link-underline);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

/* A button can carry the link's classes for an action that sits among words and acts on the page rather than going
   anywhere, such as a filter bar's Clear all: the button's own box goes, and the link's look stays. */
button.smbk-link {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  text-align: inherit;
  appearance: none;
}

@media (hover: hover) {
  .smbk-link:hover,
  .smbk-link--standalone:hover {
    color: var(--smbk-color-text-link-hover);
    text-decoration-line: underline;
    text-decoration-color: var(--smbk-color-text-link-underline-hover);
  }
}

.smbk-link:active,
.smbk-link--standalone:active {
  color: var(--smbk-color-text-link-pressed);
  text-decoration-line: underline;
  text-decoration-color: var(--smbk-color-text-link-underline-pressed);
}

.smbk-link:focus-visible {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: var(--smbk-focus-ring-offset);
  border-radius: var(--smbk-radius-full);
}

.smbk-link[aria-disabled="true"] {
  color: var(--smbk-color-text-link-disabled);
  pointer-events: none;
}

/* A link standing on its own, outside running text, shows its underline on hover and press only.
   Inside a sentence the underline stays, so a link never reads as plain words. */
.smbk-link--standalone {
  text-decoration-line: none;
}

/* Words that are pressed rather than followed, such as a name that opens its card. They are the words of the text
   around them, in its color, so the line is what says they can be pressed: it stays, standing on its own too, and
   the words keep their color under the pointer. A press shows in the words as well as the line. */
.smbk-link--pressable {
  color: inherit;
  text-decoration-line: underline;
}

@media (hover: hover) {
  .smbk-link--pressable:hover {
    color: inherit;
  }
}

.smbk-link--pressable:active {
  color: var(--smbk-color-text-subtle);
}

/* The underline runs under the words, never under an icon or the gap beside it. A line set on the link reaches
   everything inline inside it and nothing inside can take it off: only a box of its own would shed it, and that would
   let the line break before the icon. So a link with an icon leaves the underline to its label, and the icon stays
   inline. The label takes its line's color and thickness from the link, whichever state the link is in. */
.smbk-link__label {
  text-decoration-color: inherit;
  text-decoration-thickness: inherit;
}

.smbk-link:has(> .smbk-link__icon):has(> .smbk-link__label) {
  text-decoration-line: none;
}

.smbk-link:has(> .smbk-link__icon):is(:not(.smbk-link--standalone), .smbk-link--pressable) > .smbk-link__label {
  text-decoration-line: underline;
}

@media (hover: hover) {
  .smbk-link:has(> .smbk-link__icon):hover > .smbk-link__label {
    text-decoration-line: underline;
  }
}

.smbk-link:has(> .smbk-link__icon):active > .smbk-link__label {
  text-decoration-line: underline;
}

/* Not a box of its own, which would let the line break before it. Sitting on
   the text baseline centers Phosphor's glyph on the capitals. The icon follows
   the text: 20 beside the large link, 16 beside the medium, 12 beside the small. */
.smbk-link__icon {
  display: inline;
  font-size: var(--smbk-size-icon-md);
}

.smbk-link__icon:first-child {
  margin-inline-end: var(--smbk-space-inset-2xs);
}

.smbk-link__icon:last-child {
  margin-inline-start: var(--smbk-space-inset-2xs);
}

.smbk-link--size-md {
  font-family: var(--smbk-typography-body-md-font-family);
  font-size: var(--smbk-typography-body-md-font-size);
  font-weight: var(--smbk-typography-body-md-font-weight);
  line-height: var(--smbk-typography-body-md-line-height);
  letter-spacing: var(--smbk-typography-body-md-letter-spacing);
}

.smbk-link--size-md .smbk-link__icon {
  font-size: var(--smbk-size-icon-sm);
}

.smbk-link--size-sm {
  font-family: var(--smbk-typography-body-sm-font-family);
  font-size: var(--smbk-typography-body-sm-font-size);
  font-weight: var(--smbk-typography-body-sm-font-weight);
  line-height: var(--smbk-typography-body-sm-line-height);
  letter-spacing: var(--smbk-typography-body-sm-letter-spacing);
}

.smbk-link--size-sm .smbk-link__icon {
  font-size: var(--smbk-size-icon-xs);
}

/* The size of the text around it, as in a heading or a card title: every part of the face comes from
   the parent, and the icon takes the text's size. The underline stays. */
.smbk-link--size-inherit {
  font: inherit;
  letter-spacing: inherit;
}

.smbk-link--size-inherit .smbk-link__icon {
  font-size: inherit;
}

/* ---- touch: a link standing on its own takes an invisible press area ----
   On a touch screen an invisible area, centred on a standalone link, takes the press out to the comfortable target
   in each direction it falls short of it, and halfway to a link standing right under it; its words, its underline,
   its focus ring and its place stay as drawn. A
   link inside a sentence keeps its line, so a press on the words round it never follows the link. */

@media (pointer: coarse) {
  .smbk-link--standalone {
    position: relative;
  }

  .smbk-link--standalone::after {
    content: '';
    position: absolute;
    inset: min(0%, (100% - var(--smbk-size-target-comfortable)) / 2);
  }

  /* Links standing one under another, a stack's gap apart: halfway into it. */
  .smbk-link--standalone + .smbk-link--standalone::after {
    inset-block-start: max(min(0%, (100% - var(--smbk-size-target-comfortable)) / 2), var(--smbk-space-stack-md) / -2);
  }

  .smbk-link--standalone:has(+ .smbk-link--standalone)::after {
    inset-block-end: max(min(0%, (100% - var(--smbk-size-target-comfortable)) / 2), var(--smbk-space-stack-md) / -2);
  }
}

/* ---- high contrast (forced colors) ---- */
/* In Windows high-contrast mode the browser drops fills and shadows; this puts the meaning back with the
   user's own colors. Nothing here applies outside that mode. */

@media (forced-colors: active) {
  .smbk-link[aria-disabled="true"] {
    color: GrayText;
  }
}
Tokens it reads
Link tokens
Token and CSSValuePreviewFoundation
color.text.link--smbk-color-text-linklight: #232527dark: #e7ebf0changes with themeColor
typography.body-lg--smbk-typography-body-lg-font-family--smbk-typography-body-lg-font-size--smbk-typography-body-lg-font-weight--smbk-typography-body-lg-line-height--smbk-typography-body-lg-letter-spacing--smbk-typography-body-lg-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 20pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
color.text.link-underline--smbk-color-text-link-underlinelight: #23252730dark: #e7ebf030changes with themeColor
border-width.link-underline--smbk-border-width-link-underline1.5pxBorder width
space.link-underline--smbk-space-link-underline4pxSpacing
color.text.link-hover--smbk-color-text-link-hoverlight: #111213dark: #f3f5f8changes with themeColor
color.text.link-underline-hover--smbk-color-text-link-underline-hoverlight: #4e555e80dark: #9ba5b180changes with themeColor
color.text.link-pressed--smbk-color-text-link-pressedlight: #373d43dark: #c4cdd8changes with themeColor
color.text.link-underline-pressed--smbk-color-text-link-underline-pressedlight: #4e555edark: #9ba5b1changes with themeColor
focus.ring.width--smbk-focus-ring-width2pxFocus
color.border.focus--smbk-color-border-focuslight: #cc0d0ddark: #f34336changes with themeColor
focus.ring.offset--smbk-focus-ring-offset2pxFocus
radius.full--smbk-radius-full9999pxRadius
color.text.link-disabled--smbk-color-text-link-disabledlight: #606a75dark: #9ba5b1changes with themeColor
color.text.subtle--smbk-color-text-subtlelight: #4e555edark: #9ba5b1changes with themeColor
size.icon.md--smbk-size-icon-md20pxSize
space.inset.2xs--smbk-space-inset-2xs2pxSpacing
typography.body-md--smbk-typography-body-md-font-family--smbk-typography-body-md-font-size--smbk-typography-body-md-font-weight--smbk-typography-body-md-line-height--smbk-typography-body-md-letter-spacing--smbk-typography-body-md-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 16pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
size.icon.sm--smbk-size-icon-sm16pxSize
typography.body-sm--smbk-typography-body-sm-font-family--smbk-typography-body-sm-font-size--smbk-typography-body-sm-font-weight--smbk-typography-body-sm-line-height--smbk-typography-body-sm-letter-spacing--smbk-typography-body-sm-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
size.icon.xs--smbk-size-icon-xs12pxSize
size.target.comfortable--smbk-size-target-comfortable44pxSize
space.stack.md--smbk-space-stack-mdcomfortable: 12pxcompact: 8pxchanges with densitySpacing
Manifest
link.manifest.json
{
  "name": "link",
  "block": "smbk-link",
  "summary": "Text that goes somewhere, in three sizes or the size of the text around it, with an optional icon; underlined, unless it stands on its own. As a button it stays in the color of the words around it and opens something where it stands.",
  "adapt": "css",
  "axes": {
    "size": {
      "values": [
        "lg",
        "md",
        "sm",
        "inherit"
      ],
      "default": "lg",
      "description": "Figma calls these Large, Medium and Small, each a body preset; inherit takes the size of the text around it, as in a heading or a card title."
    }
  },
  "flags": {
    "standalone": {
      "description": "A link standing on its own, outside running text: underlined on hover and press only."
    },
    "pressable": {
      "description": "Words that are pressed rather than followed, such as a name that opens its card: a button in the color of the text around it, its line always there."
    }
  },
  "parts": [
    "icon",
    "label"
  ],
  "figmaNodeId": "4129:21956"
}