I\'ve never seen
The fact that I have never noticed
Working with AngularJS the BASE tag broke $cookieStore silently and it took me a while to figure out why my app couldn't write cookies anymore. Be warned...
Before deciding whether to use the <base>
tag or not, you need to understand how it works, what it can be used for and what the implications are and finally outweigh the advantages/disadvantages.
The <base>
tag mainly eases creating relative links in templating languages as you don't need to worry about the current context in every link.
You can do for example
<base href="${host}/${context}/${language}/">
...
<link rel="stylesheet" href="css/style.css" />
<script src="js/script.js"></script>
...
<a href="home">home</a>
<a href="faq">faq</a>
<a href="contact">contact</a>
...
<img src="img/logo.png" />
instead of
<link rel="stylesheet" href="/${context}/${language}/css/style.css" />
<script src="/${context}/${language}/js/script.js"></script>
...
<a href="/${context}/${language}/home">home</a>
<a href="/${context}/${language}/faq">faq</a>
<a href="/${context}/${language}/contact">contact</a>
...
<img src="/${context}/${language}/img/logo.png" />
Please note that the <base href>
value ends with a slash, otherwise it will be interpreted relative to the last path.
As to browser compatibility, this causes only problems in IE. The <base>
tag is in HTML specified as not having an end tag </base>
, so it's legit to just use <base>
without an end tag. However IE6 thinks otherwise and the entire content after the <base>
tag is in such case placed as child of the <base>
element in the HTML DOM tree. This can cause at first sight unexplainable problems in Javascript/jQuery/CSS, i.e. the elements being completely unreachable in specific selectors like html>body
, until you discover in the HTML DOM inspector that there should be a base
(and head
) in between.
A common IE6 fix is using an IE conditional comment to include the end tag:
<base href="http://example.com/en/"><!--[if lte IE 6]></base><![endif]-->
If you don't care about the W3 Validator, or when you're on HTML5 already, then you can just self-close it, every webbrowser supports it anyway:
<base href="http://example.com/en/" />
Closing the <base>
tag also instantly fixes the insanity of IE6 on WinXP SP3 to request <script>
resources with an relative URI in src
in an infinite loop.
Another potential IE problem will manifest when you use a relative URI in the <base>
tag, such as <base href="//example.com/somefolder/">
or <base href="/somefolder/">
. This will fail in IE6/7/8. This is however not exactly browser's fault; using relative URIs in the <base>
tag is namely at its own wrong. The HTML4 specification stated that it should be an absolute URI, thus starting with the http://
or https://
scheme. This has been dropped in HTML5 specification. So if you use HTML5 and target HTML5 compatible browsers only, then you should be all fine by using a relative URI in the <base>
tag.
As to using named/hash fragment anchors like <a href="#anchor">
, query string anchors like <a href="?foo=bar">
and path fragment anchors like <a href=";foo=bar">
, with the <base>
tag you're basically declaring all relative links relative to it, including those kind of anchors. None of the relative links are relative to the current request URI anymore (as would happen without the <base>
tag). This may in first place be confusing for starters. To construct those anchors the right way, you basically need to include the URI,
<a href="${uri}#anchor">hash fragment</a>
<a href="${uri}?foo=bar">query string</a>
<a href="${uri};foo=bar">path fragment</a>
where ${uri}
basically translates to $_SERVER['REQUEST_URI']
in PHP, ${pageContext.request.requestURI}
in JSP, and #{request.requestURI}
in JSF. Noted should be that MVC frameworks like JSF have tags reducing all this boilerplate and removing the need for <base>
. See also a.o. What URL to use to link / navigate to other JSF pages.
The base tag appears to have some non-intuitive effects, and I recommend being aware of the outcomes and testing them for yourself before relying on <base>
! Since I've discovered them after trying to use the base tag to handle local sites with differing urls and only found out the problematic effects after, to my dismay, I feel compelled to create this summary of these potential pitfalls for others.
I'll use a base tag of: <base href="http://www.example.com/other-subdirectory/">
as my example in the cases below, and will pretend that the page that the code is on is http://localsite.com/original-subdirectory
No links or named anchors or blank hrefs will point to the original subdirectory, unless that is made explicit: The base tag makes everything link differently, including same-page anchor links to the base tag's url instead, e.g:
<a href='#top-of-page' title='Some title'>A link to the top of the page via a named anchor</a>
becomes
<a href='http://www.example.com/other-subdirectory/#top-of-page' title='Some title'>A link to an #named-anchor on the completely different base page</a>
<a href='?update=1' title='Some title'>A link to this page</a>
becomes
<a href='http://www.example.com/other-subdirectory/?update=1' title='Some title'>A link to the base tag's page instead</a>
With some work, you can fix these problems on links that you have control over, by explicitly specifying that these links link to the page that they are on, but when you add third-party libraries to the mix that rely on the standard behavior, it can easily cause a big mess.
IE6 fix that requires conditional comments: Requires conditional comments for ie6 to avoid screwing up the dom hierarchy, i.e. <base href="http://www.example.com/"><!--[if lte IE 6]></base><![endif]-->
as BalusC
mentions in his answer above.
So overall, the major problem makes use tricky unless you have full editing control over every link, and as I originally feared, that makes it more trouble than it's worth. Now I have to go off and rewrite all my uses of it! :p
Related links of testing for issues when using "fragments"/hashes:
http://www.w3.org/People/mimasa/test/base/
http://www.w3.org/People/mimasa/test/base/results
Edit by Izzy: For all of you running into the same confusion as me concerning the comments:
I've just tested it out myself, with the following results:
#anchor
and ?query
would simply be appended to the specified <BASE>
).other.html
and dir/other.html
would start at the DOCUMENT_ROOT
with the given example, /other-subdirectory
being (correctly) treated as file and thus omitted.So for relative links, BASE
works fine with the moved page – while anchors and ?queries
would need the file name be specified explicitly (with BASE
having a trailing slash, or the last element not corresponding to the name of the file it's used in).
Think of it as <BASE>
replacing the full URL to the file itself (and not the directory it resides in), and you'll get things right. Assuming the file used in this example was other-subdirectory/test.html
(after it moved to the new location), the correct specification should have been:
<base href="http://www.example.com/other-subdirectory/test.html
">
– et voila, everything works as expected: #anchor
, ?query
, other.html
, very/other.html
, /completely/other.html
.
Drupal initially relied on the <base>
tag, and later on took the decision to not use due to problems with HTTP crawlers & caches.
I generally don't like to post links. But this one is really worth sharing as it could benefit those looking for the details of a real-world experience with the <base>
tag:
http://drupal.org/node/13148
Also, you should remember that if you run your web server at non-standard port you need to include port number at base href too:
<base href="//localhost:1234" /> // from base url
<base href="../" /> // for one step above
To decide whether it should be used or not, you should be aware of what it does and whether it's needed. This is already partly outlined in this answer, which I also contributed to. But to make it easier to understand and follow, a second explanation here. First we need to understand:
<BASE>
being used?For some examples, let's assume we have these URLs:
A) http://www.example.com/index.html
B) http://www.example.com/
C) http://www.example.com/page.html
D) http://www.example.com/subdir/page.html
A+B both result in the very same file (index.html
) be sent to the browser, C of course sends page.html
, and D sends /subdir/page.html
.
Let's further assume, both pages contain a set of links:
1) fully qualified absolute links (http://www...
)
2) local absolute links (/some/dir/page.html
)
3) relative links including file names (dir/page.html
), and
4) relative links with "segments" only (#anchor
, ?foo=bar
).
The browser receives the page, and renders the HTML. If it finds some URL, it needs to know where to point it to. That's always clear for Link 1), which is taken as-is. All others depend on the URL of the rendered page:
URL | Link | Result
--------+------+--------------------------
A,B,C,D | 2 | http://www.example.com/some/dir/page.html
A,B,C | 3 | http://www.example.com/dir/page.html
D | 3 | http://www.example.com/subdir/dir/page.html
A | 4 | http://www.example.com/index.html#anchor
B | 4 | http://www.example.com/#anchor
C | 4 | http://www.example.com/page.html#anchor
D | 4 | http://www.example.com/subdir/page.html#anchor
<BASE>
being used?<BASE>
is supposed to replace the URL as it appears to the browser. So it renders all links as if the user had called up the URL specified in <BASE>
. Which explains some of the confusion in several of the other answers:
<BASE>
differs from the one being called initially from the user)<BASE>
:
Say you want to "prettify" some URL using mod_rewrite
:
<DOCUMENT_ROOT>/some/dir/file.php?lang=en
http://www.example.com/some/dir/file.php?lang=en
http://www.example.com/en/file
Let's assume mod_rewrite
is used to transparently rewrite the user-friendly URL to the real one (no external re-direct, so the "user-friendly" one stays in the browsers address bar, while the real-one is loaded). What to do now?
<BASE>
specified: breaks all relative links (as they would be based on http://www.example.com/en/file
now)<BASE HREF='http://www.example.com/some/dir>
: Absolutely wrong. dir
would be considered the file part of the specified URL, so still, all relative links are broken.<BASE HREF='http://www.example.com/some/dir/>
: Better already. But relative links of "type 4" are still broken (except for "case B").<BASE HREF='http://www.example.com/some/dir/file.php>
: Exactly. Everything should be working with this one.Keep in mind this applies to all URLs in your document:
<A HREF=
<IMG SRC=
<SCRIPT SRC=