Note: This site might seem inactive… That’s because it is. Don’t worry though, I’m still coding webpages and stuff! If you’re interested, I suggest you get a translator and head over to Qiwi; or you could just check the latest site we’ve been working on: Apotheek Goethals – Debrabandere. Enjoy!
Absolute relative links
One of the features that aren’t (yet) implemented into WordPress, is the use of relative links. A relative link is a link to a page or a file which is located on the same site the page containing the link is on. *gasp* For example, if I want to link to http://mathiasbynens.be/portal from this page, there’s no need to use <a href="http://mathiasbynens.be/portal"> — <a href="/portal"> would work just as well, and even saves us a couple of bytes. It would take quite some time to get that working in WP; there would have to be a “Relative Blog Address” variable, which then would be used in all cases (permalink generation et al) except for syndication feeds and for trackbacking other people’s posts.
Since I really wanted to support relative links on this site, but lacked the time to mess with WP like that, I quickly wrote this little hack:
<?php
function relative_links($str) {
$url = 'http://mathiasbynens.be';
$str = str_replace("'" . $url ."/", "'/", $str);
$str = str_replace('"' . $url . '/', '"/', $str);
$str = str_replace('"' . $url . '"', '"/"', $str);
$str = str_replace("'" . $url . "'", "'/'", $str);
return $str;
}
ob_start('relative_links');
?>
I have this code in my header, before my DOCTYPE declaration, though it should work anyhow — no matter where you place it. Why so many lines? Let me explain. The code on line 4 takes care of links like <a href="http://mathiasbynens.be/whatever/">, while the code on line 5 handles stuff like <a href='http://mathiasbynens.be/whatever/'>. Personally, I don’t (have to) use the lines 6 (<a href="http://mathibus.com">) and 7 (<a href='http://mathibus.com'>), as I’m a trailingslasher by nature. However, lots of people aren’t. WordPress even uses naughty links like that by default…
The reason why the script checks for the trailingslashed root URI and then replaces it with a slash instead of looking for the untrailingslashed URI and simply removing it, is because autrement linking to free cached pages of your site wouldn’t work.
Feel free to use the above script — I’d like to have as many folks as possible taking my lead (rrrright!). Therefore, I also created a WP plugin. It’s codenamed Relative Links for WordPress, and can be used out-of-the-box, requiring absolutely no configuration.
Use (one of) these scripts! It’ll make a) your site load faster, b) me happy, and c) the web a better place.
Comments (30)
Listed below are the responses for this entry.
Trackbacks & Pingbacks (3)
Listed below are resources on the web that mention this article.
-
- Wordpress Plugin Competition Blog: Absolute Relative Links:
Absolute Relative Links
I believe relative URIs with absolute paths (such as/pluginblog/instead ofhttp://weblogtoolscollection.com/pluginblog/, which is an absolute URI with an absolute path) should be used […]- Trackback made on April 10th, 2005 @ 1:47 pm
-
- verbage.net: The making of this blog:
The making of this blog
Having spent a considerable amount of time setting up and tweaking this blog to get it looking the way it does, I figured it would be appropriate to inagurate my (third) attempt at blogging with a post on just that — the fashioning of this blog. […]- Trackback made on June 27th, 2005 @ 11:10 pm
-
- С хаком по жизни » » Несколько доменов один wordpress:
[…] Методика относительных ссылок разобрана здесь на английском языке. Заключается она в добавлении обработчика, работающего на регулярных выражениях для обрезания текущего домена из ссылок. […]
- Pingback made on December 11th, 2007 @ 3:52 pm
I’m not sure it would really make an appreciable benefit. From the time WordPress
include()s the plugin file, parses its contents, and begins buffering output through four string replacements, you’ve got a very slightly “expensive” operation going on. Does the extra HTTP latency and HTML parsing time on your multi-gigahertz system really suffer because of those extra 9 characters in URIs?If that’s the way you feel about it, you should use the non-plugin code. ;) Note that I choose for string replacements through
str_replace()instead ofpreg_replace()because of speed and “expensiveness”. Really, fourstr_replacements won’t make a distinct difference as for page generation time.That wasn’t my point. The reason why I like relative links so much, is because I believe it is part of designing with web standards.
Hold on, aren’t those absolute links? I thought relative links were links that are relative to the current directory…
So if you were browsing
http://mysite.com/mathias/about.php, and clicked a link which used the code<a href="blog.php">Click me!</a>then you’d go tohttp://mysite.com/mathias/blog.php. That, in my understanding, is a relative link. Then an absolute link would have a slash in front, and instead take you tohttp://mysite.com/blog.php. Right?… You got me there for a second, Jon! Damn… Good point. I must admit I never really thought about it that way before. However, let me explain how I ever got to naming this type of links “relative”.
Let’s say you’re browsing
http://example.com/something/. In my understanding, the following definitions are correct:<a href="http://example.com/foo-bar/">link text</a>(would obviously point tohttp://example.com/foo-bar/)<a href="/foo-bar/">link text</a>(would point tohttp://example.com/foo-bar/as well)<a href="foo-bar/">link text</a>(would point tohttp://example.com/something/foo-bar/)I just call them that as they’re relative to… the site host. If you would place this document on your web server, the references to stuff on my site wouldn’t quite work anymore, would they?
Having said that, “loose” links should never be used except for with on-page links (with anchors).
I’ve always wondered the same thing about WP. Why don’t they use relative links instead of absolute? I’m sure they have some reason…
I read up on stuff and have a bit of a better understanding now:
The browser’s job is to parse all URIs in a document, and make sure that they are absolute. It does this by first finding the base URI, which is usually the URI of the current document, and then changing any relative URIs into absolute URIs ready to be followed.
It would seem, as far as I understand things, that your “relative” and “loose” links are both relative URIs, technically, as they both depend on a base URI in order to be resolved.
For a guaranteed headache, I recommend RFC 1808 — Section 3 is probably the most useful part.
Nick, I’m guessing that is because b2 never supported what I call “relative links”. Like I said, rewriting all WP functions that involve permalinks would be quite a hassle. Plus, as far as I know (?), syndications feeds do not support relative links, so all those functions would have to depend on
$doing_rss.So, Jon, what are these links? How should they be referred to? Where’s Anne van Kesteren when you need him?
(Note to self: that headache thing really works.)
I’m guessing that they’re just a type of relative link, but I’ll ask Anne about it when I next see him on MSN.
Links such as
<a href="http://example.com/foo-bar/">link text</a>are absolute. Links such as<a href="/foo-bar/">link text</a>AND<a href="foo-bar/">link text</a>are relative to the base URI, which is inferred by the browser unless there is a<base href="http://example.com/" />element (see the W3C specs).The abovementioned relative links are relative with regards to the
<base>of the site (which is the object of nomenclature here). However, even within “canonically” relative URIs, you still have absoluteness and relativity regarding file hierarchy. For example,<a href="foo-bar/">link text</a>is relative with regards to the file hierarchy and the site<base>. However,<a href="http://example.com/foo/bar/../../">link text</a>is absolute with regards to its<base />but relative in its traversal down and up the file hierarchy.I must be missing something here.
I’d say links such as
<a href="/foo-bar/">link text</a>are relative to the base URI; links like<a href="foo-bar/">link text</a>are relative to the request URI.Good point — it’s all definitions. Once again, it shows that web design isn’t that much different from life.
By the way,
<base />is nasty, and should thus not be used.Mathias, as explained here the base URI in the context of relative URIs is (by default) the current document, NOT the document root (aka. the domain).
Hehe. Those you use are actually absolute links. Relative links are
../../images/background.png. I see you guys have covered a lot of the theory there, but that’s just it. But to prove your case true: absolute links should be possible. They are a requirement for any well-structured site.I just can’t perceive why it is an issue. I realize what you are saying about WordPress not being able to support relative URIs. But why go through programmatic code and time to specifically replace out the domain in the URI (just leaving in an absolute path to the file hierarchy), when the browser is just going to calculate the
<base />anyway and substitute it right back in? What is the difference here with your method?Let’s get back to the naming discussion. Alright, I got it. They’re not relative links, even though they’re relative to the site domain. But there is a difference, right? You guys told me stuff like
<a href="/">link text</a>is absolute — but how about<a href="http://example.com/">link text</a>?We got a bit of a contradiction going on here. Basil says:
…but then he goes:
But that’s not all of it — oh, confusion in my mind — Rob says:
So, what are they? Both relative and absolute? If the plugin is named incorrectly, how should I entitle it? ?
I don’t know, Basil, I guess it’s just me :) It does reduce file sizes with some bits, maybe that’s why. In my struggle for perfection, I tend to remove all “redundancies” from my web pages. It’s just not necessary to use those nine explicitly state the domain name in these cases.
Jonathan reread the specs, and it seems both
../../whatever/etc and/whatever/are relative, because they are relative to the domain. But it’s all rather vague. I still prefer to call/whatever/an absolute link. Or path, rather.AFAIK, an absolute link is like this:
http://www.example.org/. On the other hand, no matter what server you’re on,/dir/is a relative link.The conclusion? In none-too-correct terms, if you include the domain name and the protocol, it’s an absolute link, otherwise it’s a relative link.
I’m waiting with bated breath to be proved wrong. :-)
This is all a bit confusing for me. What’s the advantages? Disadvantages?
Building on what Rob said, I think there are two things we are dealing with here: paths, and URIs. The path is simply where you are linking to in relation to the document root, wheras the URI is where you are linking to in the universe. Both paths and URIs can be relative or absolute, so:
I may well be wrong, so don’t quote me on that, but it’s my current understanding. I’m going to email Anne.
Because the relativity and absoluteness here can be taken with regards to two different things, we must clarify once and for all the exact definition of a “relative URI” as opposed to an “absolute URI”. What is the frame of reference here? The W3C describes the differences in specific:
Therefore, as far as I can ascertain from the W3C, a URI is absolute if and only if it contains a site domain. Thus, the criterion for determining whether or not a URI is relative must be whether or not it needs to be resolved to a
<base />. As such, the original entitlement of your plugin is correct. As I wrote above:With this in mind, relative links such as
<a href="/people/faculty/Jones.html">...</a>are still absolute to the file hierarchy in the sense that they resolve to the site’s top-level DocumentRoot as opposed to traversing the hierarchy with... But the primary means of differentiation here must be with respect to the<base />, not with respect to the file hierarchy (in terms of the nomenclature of relative URIs).For further reading, RFC 1808 describes exactly how to resolve relative URIs (especially since most relative URIs are also relative towards their file hierarchies, and have their own rules of resolving with respect to that). Some of the examples in that RFC are also on their own page, where you can hover over the link to see how your browser resolves the relative URI. Finally, I dug up one of Tim Berners-Lee’s old documents from CERN that describes relative naming a little bit further.
Finally, with regards to the plugin, it does indeed convert absolute URIs to relative URIs, but keeps them absolute with regards to the file hierarchy of the site. It’s a bit, erm, overkill (:-D) to work that hard to strip out something that is going to be inferred by the browser anyway, but all the more power to you, Mathias, for the idea, implementation, and provocative discussion.
Aankhen, your comment echoes the thoughts I had whilst writing this post exactly!
Well Indranil, the advantages are slightly smaller file sizes, which might result in bandwidth savings, and the warm fuzzy –feeling. Also, on sites that work with both the
www.subdomain and without, relative links allow users to keep browsing the site with their preferred subdomain. Zeldman uses as much relative URIs as possible, for which I’m very grateful. (I just can’t standwww.!) As for using relative links, there are absolutely no disadvantages. However, using the plugin may slow page generation down for like half a millisecond. You’ve been warned :POh my god, Jon, that makes so much sense it just has to be right!
Hurrah! :) Also thanks, Basil, for the link to that Addressing URIs: Relative Naming page, on which is stated:
…which proves Jon to be as correct as I thought he would be!
Sorry, I forgot about this discussion. I talked with Anne on the subject, and among other things, he said he’d heard:
../something/and the like/something/http://example.com/whatever/That is pretty much the same as my path/URI explanation, although I prefer to differenciate the two to makes things crystal clear.
He also highlighted that
http://example.com/onedirectory/../anotherdirectory/is actually a perfectly valid (albeit useless) way to express a URI. Of course, this would be an absolute URI, with a relative path.Thank you both, Jon and Anne. I think all my questions have now been answered:
http://example.com/whatever/http://example.com/shizzle/dizzle/../whatever//whatever/../whatever/By the way, I didn’t know that absolute URI/relative path combination was possible — très cool!
To be 100% correct, I should’ve named the plugin , but I don’t think the title is incorrect.
Or you could have put ;). But yeah, the title is still correct really. Has been an interesting discussion.
Mathias, I’ve activated this plugin on my site. Great, my homepage size has been reduced by approx 11%.
But, Atom feeds receive broken URLs. Without digging into the WordPress core code, I’ve modified the
ifexpression that decides if we do the call toob_start().Now it’s like this:
if(!strstr($_SERVER['REQUEST_URI'], $url . '/wp-admin') && !strstr($_SERVER['REQUEST_URI'], 'atom')) { ob_start('relative_links'); // do not filter in admin section and Atom feeds }A provisional hack ;)
Hey Choan, thanks for that. I was already checking for RSS feeds in the latest version of the plugin, but it seems like I forgot about Atom indeed!
Anyway, I solved this problem in a slightly different manner (
global $feed;,if((!strstr($_SERVER['REQUEST_URI'], $url . '/wp-admin')) && (!$feed)) ob_start('mj_relative_links');) than you did. Version 1.1 of the Relative Links for WordPress plugin is now available! :)I installed your plugin and it works fine but it inserts a in my search box on the front page as well as inserts another in the admin login name and a in the password field. I reactivated the plugin on my site so that you could see the effect. I use a slightly modified version (PHP code wise) of Kubrick on Wordpress 1.5.1. Could it be an interference with other plugins (if such a thing is possible)? I run quite a few there:
Man I am so glad I’m not the only one who was confused about this topic… Glad our *cough* clients *cough* don’t read these — I hope :p
Thanks for the plug-in! I had to switch from a
.comto a.neta bit back, and the domain change was throwing off all my old links. I used your plug-in to name the root as the old domain, and now all those old links work!I saw a couple references above to RFC 1808. Please refer to RFC 2396, as it makes changes to relative URI handling. From Appendix G2, non-editorial changes from RFCs 1738 and 1808:
Section 5 of RFC 2396, “Relative URI References”, is the proper reference as it supersedes RFC 1808.
Awesome plugin, thanks Matt.
I have one request though - how can I override the plugin for a specific link? For example I am trying to add “digg this” buttons which require the full URL of the post to be output, and at the moment Relative Links is chopping out the domain part of the URL.