Using <base href/> with Anchors
Posted by Roger Keays, 26 June 2007, 11:26 AM
A <base href="homepage-url"/> tag in the header of the pages in your site is enormously convient for building sites which can be moved from one domain or location to another. Unfortunately, there is one downside - it breaks anchor links. In this blog I explain the whole problem with the base tag and show you how you get around the problem with broken anchor links.
The purpose of the <base/> tag is to specify the base location for resolving relative urls. It was only ever meant to be used for viewing a page where the document root is not available (for example, from an email) and should technically point to the actual document location, rather than the homepage. However, there are two significant advantages to the latter:
- Your site can be easily ported to a new location; and
- Your web applications can be built without any reference to the location they are installed.
Any HTML purist and they'll tell you that using <base href="homepage-url"/> to artificially rewrite all your urls relative to your homepage or application context is abusing the intended use of the tag. Well, okay, so that's not what it was designed for, but I'm fairly certain HTML wasn't design to build applications like Google Maps either, but people did it anyway.
The problem
The Achille's Heel of the base href tag is that anchor links will all resolve to the homepage unless you include the relative path of the document also. For example, if the base href was http://www.example.com, notice how the following urls are resolved:
Relative URL Absolute URL Broken: #anchor http://www.example.com/app#anchor Corrected: page#anchor http://www.example.com/app/page#anchor
This doesn't cause a problem if you are happy to manually include the page location in each anchor link. For our CMS however, we wanted the editor to do this work for us and there are two problems with making this transparent to the user:
- When new pages are created they don't yet have a URL, and
- If the user changes the url of a page, the links need to be updated also.
The solution
To solve this problem we turned to our temperamental friend, Javascript. Javascript can be used to fetch the absolute location of a document, and then just add the anchor on the end. All that we needed was to program the editor to insert anchor links to look like this:
<a href="javascript:;" onclick="document.location.hash='anchor';">Anchor</a>
These links downgrade gracefully when javascript is not available and simply do nothing when they are clicked.
View a demonstration of the javascript anchors.
Comment posted by: Michael Fritz on 25 March 2008, 8:41 PM
brillant simple solution!
Comment posted by: wally on 6 April 2008, 12:31 AM
This doesn't work.
First of all you don't close the onclick, secondly this is not SEO-friendly. I solved it like this.
<a href="page.html#anchor" onclick="document.location.hash=this.href.split('#')[1];return false;">Go to anchor.</a>
This way googlebots and suchlikes can index your page and still be able to follow your links. Because googlebots do (presumably) not have javascript enabled and they will not be able to follow your links.
Best regards,
wally
Comment posted by: Roger Keays on 6 April 2008, 12:57 AM
Hi Wally,
Thanks for the comments. I fixed up that onclick attribute. As for search engines not following the links, I'm not sure I would be too worried seeing as this method only works for anchors on the current page. Presumably if a search engine bot could find the current page it wouldn't need to be told which to anchor regions to index, as it would index the whole page by default.
Comment posted by: wally on 7 April 2008, 2:19 AM
Hi Roger,
Okay, the links may not be of importance to the search engines but I find it better to know where I'm heading i.e. being able to se the #anchor. Also, you cannot open the links in a new window/tab.
Comment posted by: Greg Pool on 6 May 2008, 2:50 AM
Good solution, but the best is to resolve to the actual file and not the document root. Then you wouldn't have to use JavaScript.
Here's the W3C on Links in HTML Documents. The key is "The path information specified by the BASE element only affects URIs in the document where the element appears."
It's even better if you can create the BASE HREF dynamically, like in PHP or XSL. I did this with the latter, and it meant I got the benefit of resolving URLs on a server with lots of virtuals in addition to making my anchors still work.
Comment posted by: Matt Montag on 27 February 2009, 8:28 AM
Here is my approach to the problem - insert this script before your close body tag and it will rewrite all the in-page anchor tags.
var anchors = document.getElementsByTagName("a");
var basehref = document.getElementsByTagName("base")[0].href;
var url = window.location.href;
if(url.indexOf("#") > 0) url = url.substr(0, url.indexOf("#")); //strip hash
if(basehref) {
for(var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
poundPos = anchor.href.indexOf("/#");
if (poundPos > 0) {
anchor.href = url + anchor.href.substr(poundPos + 1);
}
}
}
Comment posted by: Roger Keays on 28 February 2009, 11:16 AM
Hey Matt, nice solution. I guess it won't make any sense to search engines, but they should just see those anchors as links to the base href page so no big deal.
Comment posted by: Marcelo Oliveira on 13 March 2009, 7:02 AM
tks a lot.
here's another solution:
http://howtobuildawebsite.blogspot.com/2007/11/base-href-and-named-anchors.html
Comment posted by: Dmitris on 30 September 2009, 5:45 AM
Here the solution if using jQuery
$("a[href^='\#']").click(function(e){
e.preventDefault();
document.location.hash=this.href.substr(this.href.indexOf('#')+1);
})
Add a comment
Please visit http://www.ilikespam.com/blog/using-base-href-with-anchors to add your comments.