target='_blank' doesn't validate

Many web developers work hard to make sure web pages pass the W3C's HTML validation test. But site owners often ask for links to outside, or external, websites to open in a new window. (Site owners are afraid, apparently, that once a visitor leaves a site they will never come back!)

The easiest way to accomplish opening a page in a new window (or tab), which all major browsers support, is to use the target attribute of the anchor element:

<a href='http://osric.net/' target='_blank'>osric.net web hosting</a>

This is such a common practice that you might ask, why is it not included in the HTML specification? I don't know the answer to that, but I would guess that the HTML specification allows for browsers (or user agents) that cannot spawn a new window, such as the text-based Lynx browser. Also, usability experts recommend against opening links in new windows because it breaks the back button, and users can easily open a link in a new browser window or tab if they choose.

Javascript Solutions using window.open()

There are a few ways we can open the link in a new window that will validate, which involve using window.open()

Using the onclick attribute

<a href='http://osric.net/' onclick='window.open("http://osric.net");return false;'>osric.net web hosting</a>
Good example using the onclick attribute
osric.net web hosting (opens in a new window)

Now the URL is listed in 2 places, and that's never a good thing. Referencing this.href will allow us to keep in just one place:

<a href='http://osric.net/' onclick='window.open(this.href);return false;'>osric.net web hosting</a>
Better example using the onclick attribute
osric.net web hosting (opens in a new window)

This is good, but there is a possibility that a user will have his or her browser security settings such that all pop-ups, which includes windows opened with window.open(), will be blocked even if the action is initiated by the user. window.open() returns a Boolean value indicating the failure or success of the window opening.

<a href='http://osric.net/' onclick='return !window.open(this.href);'>osric.net web hosting</a>

If the window opens, the expression evaluates as, and returns, false. If it fails to open, the expression evaluates as, and returns, true--meaning that the link opens normally (but in the same window).

Best example using the onclick attribute
osric.net web hosting (opens in a new window)

What is this?

A note about this.href and this: although this.href works in the above examples, and would work below in most browsers, Internet Explorer returns undefined for this.href in the examples below.

When using the onlick attribute, this referred to the anchor element, of which href was a property. When assigning a function to the onclick object property, this is the href value. I don't know why and haven't yet run across any explanations.

One thing to note in either case is that the URLs are absolute: <a href='/chris/accidental-developer/'>Accidental Developer</a> returns a value of http://osric.com/chris/accidental-developer for this.href (or this) on this server.

Using the onclick object property

Some developers prefer to avoid using the onclick attribute within a tag, and prefer to assign an onclick property to the DOM object programmatically. (This could have the unintended consequence of overriding a previously applied onclick property, or overring an inline onclick attribute.) Here are a couple examples:

Using a CSS class name to identify outside links and attach the event handler

I prefer this method. Anyone looking at the code can see that the link is marked "external," and a CSS style could be used to insert an external link identifier (as below).

<style type='text/css'>
	.external {
		background-image:url(/chris/images/external-link.png);
		background-position:right center;
		background-repeat:no-repeat;
		padding-right:14px;
	}
</style>
<a href='http://osric.net/' class='external'>osric.net web hosting</a>
<script type='text/javascript'>
	// Get all the anchors in the entire document
	// (You can also use document.links to get the links)
	var anchors = document.getElementsByTagName('a');

	// Loop through the anchors and add the click handler if it includes the CSS class 'external'
	for ( var i in anchors ) 
		if ( anchors[i].className && anchors[i].className.indexOf('external') != -1 )
			anchors[i].onclick = function () { return !window.open(this); };
</script>
Example assigning onclick property by class name

Detecting external links and assigning the onclick property programmatically

The following example checks to see if the site domain name is part of the destination URL. If not, it sets the link to open in a new window. Something like this could be applied to an existing site without searching through the code to identify external links, although it could potentially mis-identify an external link as internal (e.g. http://www.google.com/search?q=osric.com contains the site domain name).

<a href='http://osric.net/'>osric.net web hosting</a>
<script type='text/javascript'>
	// Get all the anchors in the entire document, or in this case, a subset of the document
	// use document.getElementsByTagName('a') or document.links to get all anchors
	var anchors = document.getElementById('externalLinks').getElementsByTagName('a');

	// Loop through the anchors and add the click handler if it includes the CSS class 'external'
	for ( var i in anchors )
		// Look for our domain, e.g. osric.com, and add a click handler if we don't find it
		if ( anchors[i].href && anchors[i].href.indexOf('osric.com') == -1 ) 
			anchors[i].onclick = function () { return !window.open(this); };
</script>
Example detecting external links and assigning the onclick property

Attaching an Event Handler

Internet Explorer uses object.attachEvent(), but not object.addEventListener(). Firefox (and others) use object.addEventListener(), but not object.attachEvent(). In the case of Internet Explorer, the this context is not passed to the handler function, making it trickier to access information about the object upon which the user acted. O'Reilly's Dynamic HTML, 2nd Edition recommends against attaching the event handlers, saying that "Tag attribute and object property assignment are the two event binding techniques that work best across all browsers." QuirksMode.org also has interesting info on this subject; see Advanced Event Registration Models for details.

If you use a Javascript framework such as jQuery, you can use their methods of attaching event handlers--the frameworks see to cross-browser compatibility. Check out jQuery's click() method. Attaching event handlers does have a distinct advantage: an object can have mutiple event handlers (including for the same event, e.g. multiple click handlers), so assigning a click handler to open a link in a new window would not necessarily interfere with any other click handlers (or onclick attributes) that the object may have.

<ul>
	<li><a href='http://osric.net/' class='external'>osric.net web hosting</a> (opens in a new window)</li>
	<li><a href='/chris/accidental-developer/'>The Accidental Developer</a></li>
</ul>
<script type='text/javascript' src='/chris/javascript/jquery-1.4.3.min.js'></script>
<script type='text/javascript'>
	$('#jqueryExamples').find('a.external').click( function() { return !window.open(this); });
</script>
Examples using jQuery

Questions? Comments? Leave a message for me on the associated blog post: Opening links in a new window without the target attribute