Opening external links in the same tab is a flow killer.
When taking users off site, it’s best to keep the source page open and force a new tab.
While you could manually add target="_blank"
to all external links, a little bit of JavaScript will help maintain your sanity and ensure nothing gets missed (cause, stuff always gets missed).
A simple way to accomplish this is by checking that a link’s hostname
is not equal to window.window.location.hostname
For Example:
link.hostname !== window.location.hostname
Legit Links
But, you’ll probably want to go a bit deeper and exclude potential false positives and special hrefs, like: mailto:
, tel:
, js click handlers, etc.
A utility to check for legit External Links, might look something like:
/**
* Checks if link is really external
* and not a 'fake' external (ie; mailto, tel, js handler)
* @param {HTML Element} link - single link instance
* @return boolean
*/
function isExternal(link) {
return (
link.hasAttribute("href") &&
!link.href.match(/^mailto\:/) &&
!link.href.match(/^tel\:/) &&
!link.href.match(/^#\:/) &&
link.hostname !== window.location.hostname
);
}
All Together Now
Our final JavaScript component:
- Loops through all a tags on the page (links)
- Checks that they’re a legit external link
- If so, adds
target="_blank">
The JavaScript
/**
* External Links
* Adds target="_blank" to real external links
* so they open in a new tab.
*
* @author Stephen Scaff
*/
const ExternalLinks = (() => {
const links = document.getElementsByTagName('a');
return {
/**
* Init
*/
init() {
if (!links.length > 0) return;
this.bindEvents();
},
/**
* Bind Events
*/
bindEvents() {
ExternalLinks.checkLinks();
},
/**
* ForEach Helper
* Ensure we can loop over a object or nodelist
* @see https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/
*/
forEach: function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
},
/**
* Helper to check if link is really external
* and not a 'fake' external (ie; mailto, tel, js handler)
* @param {HTML Element} link - single link instance
* @return boolean
*/
isExternal(link) {
return (
link.hasAttribute("href") &&
!link.href.match(/^mailto\:/) &&
!link.href.match(/^tel\:/) &&
!link.href.match(/^#\:/) &&
link.hostname !== window.location.hostname
);
},
/**
* Check Links
* Loops through page links, if external
* calls Speed Bump modal and applies follow link to btn.
*/
checkLinks() {
ExternalLinks.forEach (links, function (index, link) {
if (!ExternalLinks.isExternal(link)) return
link.target = '_blank';
});
},
};
})();
Init
// Initialize
ExternalLinks.init();
// Or, something like
import ExternalLinks from './components/_ExternalLinks.js'
ExternalLinks.init();
Github
You can go snag a version of ExternalLinks.js on the Githubs, Right Here.
The repo includes both ES5 and ES6 versions.
Reduced Example
Here's a simple CodePen demo.