Tiny External Link Shield — auto-mark & harden outbound links

November 28, 2025

Tiny “External Link Shield” for Safer Outbound Links

When you link out to other sites, it can be useful to give visitors a small visual hint that they’re about to leave your domain, and to harden those links with safer rel attributes. This tiny “External Link Shield” snippet automates that without needing a plugin or a big front-end framework.

It quietly walks your page, finds links that go off-site, and enhances them in a single pass. Internal links to your own domain (and any domains you whitelist) are left alone, so your navigation and local pages behave as usual.

What this snippet does

This tiny “External Link Shield” walks your page, finds links that go off-site, adds a small ↗ icon, and automatically hardens them with rel="noopener noreferrer". You can also whitelist your own network domains so they’re treated as internal links.

Copy-paste snippet (CSS + JavaScript)

The CSS below adds the visual indicator after external links, and the JavaScript handles the detection and hardening of those links:

<style>
  /* External link visual hint */
  a.vibe-external {
    position: relative;
    padding-right: 0.3em;
  }

  a.vibe-external::after {
    content: "↗";
    font-size: 0.8em;
    margin-left: 0.15em;
    opacity: 0.8;
  }

  /* Optional: tweak hover state */
  a.vibe-external:hover::after {
    opacity: 1;
  }
</style>

<script>
// Tiny "External Link Shield" — no dependencies
(function () {
  // Your primary domain (no protocol)
  var mainHost = window.location.hostname.replace(/^www\./i, "");

  // Optional: treat these as "internal network" domains
  var whitelistHosts = [
    // "example.com",
    // "another-site.net"
  ];

  function isWhitelisted(host) {
    host = host.replace(/^www\./i, "");
    if (host === mainHost) return true;
    for (var i = 0; i < whitelistHosts.length; i++) {
      if (host === whitelistHosts[i]) return true;
    }
    return false;
  }

  function isSpecialScheme(href) {
    return /^mailto:|^tel:|^javascript:/i.test(href);
  }

  function shieldExternalLinks() {
    var links = document.querySelectorAll("a[href]");
    if (!links.length) return;

    for (var i = 0; i < links.length; i++) {
      var a = links[i];
      var href = a.getAttribute("href");

      if (!href || href.charAt(0) === "#") continue;
      if (isSpecialScheme(href)) continue;

      var url;
      try {
        url = new URL(href, window.location.href);
      } catch (e) {
        continue; // skip invalid URLs
      }

      // Same host or whitelisted? Leave it alone
      if (isWhitelisted(url.hostname)) {
        continue;
      }

      // Mark as external
      a.classList.add("vibe-external");

      // Harden rel="noopener noreferrer" (and optionally "nofollow")
      var relParts = (a.getAttribute("rel") || "")
        .split(/\s+/)
        .filter(Boolean);

      if (relParts.indexOf("noopener") === -1) {
        relParts.push("noopener");
      }
      if (relParts.indexOf("noreferrer") === -1) {
        relParts.push("noreferrer");
      }

      // Optional: also add nofollow
      // if (relParts.indexOf("nofollow") === -1) {
      //   relParts.push("nofollow");
      // }

      a.setAttribute("rel", relParts.join(" "));

      // Optional: force external links into a new tab
      // if (!a.target) {
      //   a.target = "_blank";
      // }
    }
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", shieldExternalLinks);
  } else {
    shieldExternalLinks();
  }
})();
</script>

How to use it

Usage is simple: drop the <style> block into your main CSS file or inside <head>, and put the <script> block near the end of your pages before </body>. Once included, every page that uses that layout will automatically enhance external links.

  1. Include the CSS so .vibe-external links get the ↗ icon and hover effect.
  2. Paste the JavaScript into a global footer script or shared layout file.
  3. Update whitelistHosts with any domains you want to treat as “internal” (your own network, partner sites, or staging domains).
  4. Optionally uncomment the nofollow and target="_blank" lines if that fits your SEO and UX style.

How it decides what’s “external”

The helper normalizes your current hostname by stripping a leading www., so example.com and www.example.com are treated as the same site. Every link on the page is inspected:

  • Anchor links (starting with #) are skipped.
  • Special schemes like mailto:, tel:, and javascript: are ignored.
  • Any URL whose hostname is either your primary host or present in whitelistHosts is treated as internal and left unchanged.
  • Everything else is considered external, marked with vibe-external, and hardened with rel="noopener noreferrer".

This keeps your internal navigation clean while giving visitors a clear, consistent hint whenever they’re about to jump off to another site.

Why hardening external links is useful

Adding rel="noopener noreferrer" to outbound links helps prevent the new tab from gaining access to the original window via window.opener. That’s a small but meaningful security improvement, especially if you link to third-party content that you don’t fully control.

The visual icon also sets expectations: visitors can see at a glance that a link will take them elsewhere. That’s a nice touch for documentation, blogs, and tools where you cite external resources, partner sites, or reference material.

Customizing the icon and behavior

You’re free to tune the appearance and behavior of the “External Link Shield”:

  • Icon: change content: "↗" to another symbol like "⧉", "🔗", or even a small Unicode box that matches your visual style.
  • Hover feel: adjust the opacity or add color changes in a.vibe-external:hover::after if you want a more obvious hover state.
  • New tab behavior: uncomment the target="_blank" block if you prefer external links to open in a fresh tab, while keeping everything else the same.

Because this snippet is small and self-contained, it fits nicely into “vibe-coded” sites, lightweight blogs, or static docs where you want a bit more polish and safety around external links without pulling in a big plugin or reworking templates.

Comments (0)

No comments yet — be the first.

← Back to all scripts