External-link highlighter (with ↗ icon + rel fixes)
Auto-Mark External Links with an Icon and Safe Rel Attributes
This snippet walks your page looking for links that go off-site and enhances them automatically. It’s a small usability and safety layer that:
- Adds a tiny “external” icon (↗) after the link text.
- Sets
rel="noopener noreferrer"to protect against tab hijacking. - Optionally opens them in a new tab with
target="_blank". - Skips internal links on your own domain so your navigation stays untouched.
There are no dependencies and no build tools required — just a handful of CSS rules and a small vanilla JavaScript helper you can drop into your layout.
Copy-paste snippet (CSS + JavaScript)
The block below includes both the styling for the icon and the script that auto-detects external links based on the current hostname:
<style>
/* Style for external links */
a.vibe-external {
position: relative;
text-decoration: none;
}
a.vibe-external::after {
content: "↗";
display: inline-block;
margin-left: 0.25em;
font-size: 0.8em;
opacity: 0.75;
vertical-align: baseline;
}
a.vibe-external:hover::after {
opacity: 1;
}
</style>
<script>
(function () {
// Set this to false if you DON'T want new tabs
var OPEN_IN_NEW_TAB = true;
var currentHost = window.location.hostname.replace(/^www\./i, '');
var links = document.querySelectorAll('a[href^="http"]:not([data-no-external])');
links.forEach(function (link) {
try {
var url = new URL(link.href);
var linkHost = url.hostname.replace(/^www\./i, '');
// Treat same host as internal
if (linkHost === currentHost) {
return;
}
// Mark as external for styling
link.classList.add('vibe-external');
// Security: make sure rel is set
var rel = (link.getAttribute('rel') || '').split(/\s+/).filter(Boolean);
if (rel.indexOf('noopener') === -1) rel.push('noopener');
if (rel.indexOf('noreferrer') === -1) rel.push('noreferrer');
link.setAttribute('rel', rel.join(' '));
// Optional: open external links in a new tab
if (OPEN_IN_NEW_TAB) {
link.setAttribute('target', '_blank');
}
} catch (e) {
// If URL parsing fails for some reason, just skip that link
}
});
})();
</script>
How to use it
-
Paste the
<style>and<script>snippet into your base layout (footer, shared template, or theme file) so it runs on the pages you want. -
By default, any link starting with
httpthat doesn’t point to your current hostname will get:class="vibe-external", a ↗ icon, andrel="noopener noreferrer". -
If you have a special link you do not want treated as external, add
data-no-externalto it:
<a href="https://example.com" data-no-external>Leave me alone</a>
The script trims off www. from hostnames so example.com and
www.example.com are treated as the same site. That keeps your own links
from being mis-marked while still catching genuine off-site URLs.
Why this matters
Highlighting external links makes it clearer when a visitor is about to leave your site,
and setting rel="noopener noreferrer" helps prevent the new tab from being
able to control the original window. That’s a small but important safety improvement,
especially if you link out to third-party sites you don’t control.
You also get a consistent visual cue across your content, even if different authors or older posts weren’t manually adding an external icon. The snippet standardizes that behavior in one place.
Customizing the icon and behavior
You can tweak the appearance and behavior of external links with a couple of small changes:
-
Icon: Edit
content: "↗"in the CSS. You can swap it for"⧉","🔗", or any other symbol that fits your design. -
New tab behavior: Set
OPEN_IN_NEW_TAB = false;if you prefer external links to open in the same tab, while still keeping the icon andrelattributes. -
Styling: Adjust font size, margin, or opacity in the
a.vibe-external::afterrule to make the icon more subtle or more prominent.
Because this helper is just a few lines of CSS and JavaScript, it’s easy to add to existing projects and just as easy to remove later. It gives your site a clearer, more consistent treatment of external links without requiring a heavy plugin or template overhaul.
Comments (0)
No comments yet — be the first.