Favicons Next To External Links

Enhance user experience by displaying destination site icons using pure CSS--no JavaScript required.

When users encounter links on your website, they expect visual cues to understand where those links will take them. External links--links that lead to other websites--benefit from clear visual indicators that set them apart from internal navigation. While many sites use simple text icons like "[external]" or generic arrows, a more sophisticated approach displays the actual favicon of the destination site, giving users immediate visual recognition of where they'll land.

This technique has become increasingly popular among modern websites, and the best part is you can implement it entirely with CSS--no JavaScript required. By leveraging attribute selectors and pseudo-elements, you can create elegant, performant external link indicators that adapt to any web development design system.

External link indicators also contribute to better SEO performance by clearly signaling to search engines which links point to external resources, helping maintain a clean site architecture.

Why Add Visual Indicators to External Links

User Experience Benefits

External link indicators serve a crucial function in web usability. When users click a link, they have certain expectations about what happens next. Internal links keep them within your site ecosystem, while external links transport them to entirely different domains. Without clear differentiation, users may feel disoriented when they suddenly find themselves on an unfamiliar website, potentially mistaking this for a security breach or site error. By visually marking external links, you set clear expectations about the browsing experience ahead.

Beyond basic orientation, favicon indicators provide cognitive recognition benefits. Users who frequently visit certain sites develop visual associations with their favicons--the small brand icons that appear in browser tabs. When those same icons appear next to links, users can instantly recognize the destination without reading the URL, making their browsing decisions more efficient and informed.

Accessibility Considerations

Visual indicators must be implemented thoughtfully to maintain accessibility. Screen reader users receive information differently than visual users, so your external link indicators need appropriate ARIA attributes to convey the same information non-visually. Adding aria-label or visually hidden text ensures that users relying on assistive technologies understand when a link will take them off-site. Additionally, the visual indicator itself should have sufficient contrast and size to be perceivable by users with varying visual abilities.

For guidance on creating accessible web experiences, see our guide on making CSS animations feel natural which covers accessibility best practices, and learn about CSS hacks for targeting Firefox for cross-browser compatibility techniques.

Detecting External Links with CSS Attribute Selectors

The Foundation: Understanding Attribute Selectors

CSS attribute selectors provide a powerful way to style elements based on their HTML attributes. For external link detection, we leverage the href attribute that all anchor (<a>) elements possess. The attribute selector syntax uses square brackets to target elements with specific attribute values or patterns.

The most common approach for detecting external links relies on the starts-with (^=) operator. External URLs typically begin with http:// or https://, while internal links usually start with a forward slash (/) for same-page navigation or relative paths. By targeting links whose href attribute starts with http, we can identify external links without needing to manually add classes to each one:

/* Target all links starting with http */
a[href^="http"] {
 /* External link styles */
}

This selector catches both http:// and https:// URLs, making it comprehensive for modern web traffic. However, it also captures links to your own domain if your site uses absolute URLs internally, which leads us to the important consideration of excluding same-origin links.

Understanding how CSS specificity and precedence work is essential when combining multiple selectors. Our guide on CSS order and precedence explains how browsers resolve conflicting style rules.

Excluding Same-Origin Links

To avoid marking your own domain's absolute URLs as external, combine the selector with a :not() pseudo-class to exclude links pointing to your domain. This requires knowing your domain pattern, which works well for single-domain sites:

/* External links excluding your own domain */
a[href^="http"]:not([href*="example.com"]) {
 /* External link styles */
}

The *= operator matches any href containing "example.com" anywhere in the URL. For more precise matching, you can chain multiple conditions or use more specific patterns depending on your URL structure.

Implementing Favicon Icons with Pseudo-Elements

The ::after Pseudo-Element Technique

Once you've identified external links using attribute selectors, the ::after pseudo-element provides the ideal mechanism for adding visual indicators. Pseudo-elements create virtual elements that don't exist in the HTML but can be styled as if they were children of the selected element. The ::after pseudo-element appears after the content of the parent element, making it perfect for appending icons to link text.

The basic structure involves setting the content property to an empty string (required for pseudo-elements to render) and styling the pseudo-element as an inline block containing the favicon:

a[href^="http"]:not([href*="example.com"])::after {
 content: "";
 display: inline-block;
 width: 1em;
 height: 1em;
 margin-left: 0.25em;
 background-size: contain;
 background-repeat: no-repeat;
 vertical-align: text-bottom;
}

This CSS creates a 1em by 1em box positioned after the link text, with spacing controlled by margin-left. The vertical-align: text-bottom ensures the icon aligns nicely with the text baseline, creating a professional appearance.

Using SVG Icons as Background Images

The most common approach for external link icons uses SVG images as background-image. Inline SVG data URIs offer several advantages: they're self-contained, require no additional network requests, and scale perfectly at any size. For more advanced SVG techniques, explore our guide on glitch effects with SVG:

a[href^="http"]:not([href*="example.com"])::after {
 content: "";
 display: inline-block;
 width: 1em;
 height: 1em;
 margin-left: 0.25em;
 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewbox='0 0 12.2 12.2' width='14' height='14'%3E%3Cpath d='M5.7 0v1.5h4L4.5 6.7l1 1.1 5.3-5.2v3.9h1.4V0z'/%3E%3Cpath fill='none' d='M3.4 6.7l3-2.9H1.5v7h7V5.9l-3 2.9z'/%3E%3Cpath d='M8.5 5.9v4.9h-7v-7h4.9l1.5-1.6H0v10h10V4.4z'/%3E%3C/svg%3E");
 background-size: contain;
 background-repeat: no-repeat;
}

This approach uses a data URI containing an encoded SVG representing an external link icon. The SVG is URL-encoded, with special characters replaced by their percent-encoded equivalents to ensure the data URI parses correctly.

Dynamic Favicon Fetching with External Services

The IndieWeb Avatar Approach

A more sophisticated technique dynamically fetches the actual favicon of each linked site rather than using a generic icon. This approach uses the IndieWeb Avatar service, which acts as a favicon proxy, returning the favicon for any domain you request.

The implementation modifies the background-image property to use the service's URL format, with the target domain URL-encoded:

a[href^="http"]:not([href*="example.com"])::after {
 content: "";
 display: inline-block;
 width: 1em;
 height: 1em;
 margin-left: 0.25em;
 background-size: contain;
 background-image: url("https://v1.indieweb-avatar.11ty.dev/https%3A%2F%2Fwww.example.com%2F");
}

However, this presents a challenge: the URL must be specific to each linked domain. For a pure CSS solution, you would need separate rules for each domain you link to, which becomes impractical for sites with many external references. The solution involves using CSS custom properties or predefining rules for specific domains:

a[href*="github.com"]::after {
 background-image: url("https://v1.indieweb-avatar.11ty.dev/https%3A%2F%2Fgithub.com%2F");
}

a[href*="twitter.com"]::after {
 background-image: url("https://v1.indieweb-avatar.11ty.dev/https%3A%2F%2Ftwitter.com%2F");
}

This domain-specific approach scales reasonably well for commonly-linked sites and provides the unique visual recognition benefit of showing each site's actual favicon.

Performance Considerations

Using external services for favicon fetching introduces performance considerations. Each favicon requires a separate network request, potentially slowing page rendering. Several strategies mitigate this impact:

Preconnecting to the favicon service establishes early network connections, reducing latency for subsequent requests. Add this to your HTML <head>:

<link href="https://v1.indieweb-avatar.11ty.dev" rel="preconnect" crossorigin>

This tells the browser to establish the TCP connection and TLS handshake before the CSS is even parsed, shaving critical milliseconds from the favicon load time.

Consider lazy loading external favicons or using a fallback generic icon that loads immediately while the specific favicon fetches. This prevents layout shifts and provides immediate feedback to users. For more performance optimization techniques, learn about playing with flexbox for efficient layouts.

Preventing Orphan Icons

The Line-Wrapping Problem

A common issue with external link icons occurs when links wrap across multiple lines. Without special handling, the icon may wrap to the next line while the link text remains on the previous line, creating an orphaned icon that looks like a disconnected graphical element. This breaks the visual connection between the icon and its associated link.

Position-Based Solutions

Using position: absolute on the pseudo-element combined with position: relative on the parent anchor and padding on the anchor creates space:

a[href^="http"]:not([href*="example.com"]) {
 padding-right: 1.25em;
 position: relative;
}

a[href^="http"]:not([href*="example.com"])::after {
 content: "";
 position: absolute;
 right: 0;
 display: inline-block;
 width: 1em;
 height: 1em;
 background-size: contain;
}

The absolute positioning places the icon within the padding area, ensuring it never wraps independently. The anchor's position: relative establishes the positioning context. This technique effectively prevents orphaned icons across all line-wrap scenarios.

Note that this technique may have browser-specific behavior, and testing across target browsers is recommended. Some browsers handle the interaction between pseudo-elements and position: absolute differently, particularly with complex text layouts.

Styling Best Practices

Size and Scaling

The icon size should balance visibility with aesthetics. A 1em by 1em size (relative to the link's font size) ensures the icon scales proportionally with text when users adjust font sizes or when links appear in different contexts with different font sizes. This relative sizing maintains visual consistency across your site's typographic scale.

For flexible sizing that adapts to context, consider using em units for dimensions and background-size set to contain to ensure the icon always fits within its designated area without distortion. This approach handles SVG icons particularly well since they scale without quality loss.

Color and Contrast

Icons should have sufficient contrast against both light and dark backgrounds, particularly if your site supports both themes. Consider using current color values or CSS custom properties to make icons automatically adapt to text color changes:

a[href^="http"]:not([href*="example.com"])::after {
 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewbox='0 0 24 24' fill='%23currentColor'%3E%3C/svg%3E");
}

Using currentColor in SVG makes the icon inherit the element's text color, automatically adapting to hover states, dark mode, and any color overrides you apply to links.

Spacing and Alignment

The spacing between link text and icon affects readability and visual appeal. A margin-left of approximately 0.25em provides sufficient separation without creating an awkward gap. The vertical-align property should match your design's baseline expectations--text-bottom generally works well for inline text links, while middle or baseline may suit different contexts.

Test icons at various font sizes and contexts including headings, paragraphs, navigation menus, and button-style links to ensure spacing and alignment remain appropriate across all use cases. For more on creating polished, production-ready styles, explore our guide on transitioning gradients and learn about multi-line truncation with pure CSS.

Common Pitfalls and How to Avoid Them

Protocol Handling

Links beginning with // (protocol-relative URLs) should also be detected as external since they inherit the current page's protocol. Extend your selector to include these:

a[href^="http"],
a[href^="//"] {
 /* External link styles */
}

Mailto and Tel Links

Email and telephone links begin with mailto: and tel: respectively. These should typically not receive external link indicators since they trigger local applications rather than opening external websites:

a[href^="mailto:"],
a[href^="tel:"] {
 /* Reset any external link styles */
}

Place these rules after your external link styles to override them for these special link types.

JavaScript-Generated Links

Links added dynamically via JavaScript after page load will automatically receive your external link styles since the attribute selector targets elements based on their HTML attributes. Since the CSS attribute selector works with any matching element regardless of when it was added to the DOM, you don't need additional JavaScript to apply these styles.

Related CSS Techniques

This external link styling approach builds on fundamental CSS concepts that appear throughout modern web development. The attribute selectors and pseudo-elements used here are the same techniques employed in many of our other CSS guides. Explore our collection of web development guides for more advanced techniques, or learn about overriding default button styles to apply similar selector patterns to buttons.

Key Takeaways

Essential points for implementing external link favicons

CSS-Only Implementation

No JavaScript required--leverage CSS attribute selectors and pseudo-elements for clean, performant code.

Dynamic Favicon Fetching

Use services like IndieWeb Avatar to display actual site favicons for visual recognition.

Performance Optimized

Preconnect to external services and use relative units for responsive scaling.

Accessibility Compliant

Ensure screen readers convey external link information through ARIA attributes.

Frequently Asked Questions

Build Better Web Experiences

Learn more about our web development services and how we create performant, accessible websites.

Sources

  1. Zach Leat - CSS-only External Link Favicons - Innovative technique using IndieWeb Avatar service
  2. CSS-irl.info - Styling External Links with Attribute Selectors - Comprehensive guide on attribute selectors and pseudo-elements
  3. MDN Web Docs - Attribute Selectors - Official documentation on CSS attribute selector syntax
  4. MDN Web Docs - Pseudo-elements - Official documentation on CSS pseudo-elements