Math Jazz — Mathias Bynens’s shizzle, y’all



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.

Filed under PHP, XHTML, WordPress · February 19th, 2005

Comments (30)

Listed below are the responses for this entry.

  1. Basil Crow:
    This commenter’s Gravatar

    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?

    Comment posted on February 19th, 2005 @ 3:30 pm
  2. Mathias:
    This commenter’s Gravatar

    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 of preg_replace() because of speed and “expensiveness”. Really, four str_replacements won’t make a distinct difference as for page generation time.

    Does the extra HTTP latency and HTML parsing time on your multi-gigahertz system really suffer because of those extra 9 characters in URIs?

    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.

    Comment posted on February 19th, 2005 @ 3:44 pm
  3. Turnip:
    This commenter’s Gravatar

    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 to http://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 to http://mysite.com/blog.php. Right?

    Comment posted on February 19th, 2005 @ 3:58 pm
  4. Mathias:
    This commenter’s Gravatar

    … 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:

    Absolute link
    <a href="http://example.com/foo-bar/">link text</a> (would obviously point to http://example.com/foo-bar/)
    Relative link
    <a href="/foo-bar/">link text</a> (would point to http://example.com/foo-bar/ as well)
    Loose link
    <a href="foo-bar/">link text</a> (would point to http://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).

    Comment posted on February 19th, 2005 @ 4:14 pm
  5. Nick:
    This commenter’s Gravatar

    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…

    Comment posted on February 19th, 2005 @ 4:50 pm
  6. Turnip:
    This commenter’s Gravatar

    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.

    Comment posted on February 19th, 2005 @ 5:10 pm
  7. Mathias:
    This commenter’s Gravatar

    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.)

    Comment posted on February 19th, 2005 @ 5:38 pm
  8. Turnip:
    This commenter’s Gravatar

    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.

    Comment posted on February 19th, 2005 @ 7:34 pm
  9. Basil Crow:
    This commenter’s Gravatar

    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.

    Comment posted on February 19th, 2005 @ 9:04 pm
  10. Mathias:
    This commenter’s Gravatar

    I must be missing something here.

    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).

    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.

    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.

    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.

    Comment posted on February 19th, 2005 @ 9:22 pm
  11. Turnip:
    This commenter’s Gravatar

    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).

    Comment posted on February 19th, 2005 @ 10:06 pm
  12. Rob Mientjes:
    This commenter’s Gravatar

    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.

    Comment posted on February 19th, 2005 @ 11:22 pm
  13. Basil Crow:
    This commenter’s Gravatar

    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?

    Comment posted on February 20th, 2005 @ 3:34 am
  14. Mathias:
    This commenter’s Gravatar

    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:

    Links such as <a href="/foo-bar/">link text</a> AND <a href="foo-bar/">link text</a> are relative to the base URI […]

    …but then he goes:

    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.

    But that’s not all of it — oh, confusion in my mind — Rob says:

    Those you use are actually absolute links. Relative links are ../../images/background.png.

    So, what are they? Both relative and absolute? If the plugin is named incorrectly, how should I entitle it? Domain-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.

    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.

    Comment posted on February 20th, 2005 @ 9:45 am
  15. Rob Mientjes:
    This commenter’s Gravatar

    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.

    Comment posted on February 20th, 2005 @ 12:03 pm
  16. Aankhen:
    This commenter’s Gravatar

    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. :-)

    Comment posted on February 20th, 2005 @ 5:24 pm
  17. Indranil:
    This commenter’s Gravatar

    This is all a bit confusing for me. What’s the advantages? Disadvantages?

    Comment posted on February 20th, 2005 @ 6:00 pm
  18. Turnip:
    This commenter’s Gravatar

    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:

    /something/
    is a relative URI, but an absolute path
    ../something/
    is a relative URI, and a relative path
    http://example.com/
    …or anything that specifies the domain is both an absolute URI and an absolute path

    I may well be wrong, so don’t quote me on that, but it’s my current understanding. I’m going to email Anne.

    Comment posted on February 20th, 2005 @ 6:58 pm
  19. Basil Crow:
    This commenter’s Gravatar

    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:

    In general, a URL can be absolute:

    The work by <a href="http://www.newu.edu/faculty/Jones.html">Jones</a> ...
    or relative:

    <a href="Jones.html">...</a>

    <a href="faculty/Jones.html">...</a>

    <a href="faculty/Jones/Bio.html">...</a>

    <a href="/people/faculty/Jones.html">...</a>

    <a href="../faculty/Jones.html">...</a>

    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:

    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.

    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.

    Comment posted on February 20th, 2005 @ 9:18 pm
  20. Mathias:
    This commenter’s Gravatar

    Aankhen, your comment echoes the thoughts I had whilst writing this post exactly! If it’s not absolutely absolute, it’s gotta be relatively relative.

    What’s the advantages? Disadvantages?

    Well Indranil, the advantages are slightly smaller file sizes, which might result in bandwidth savings, and the warm fuzzy I semantically kick ass!–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 stand www.!) 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 :P

    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 […]

    Oh my god, Jon, that makes so much sense it just has to be right!

    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.

    Hurrah! :) Also thanks, Basil, for the link to that Addressing URIs: Relative Naming page, on which is stated:

    If a leading slash is present, the path is absolute.

    …which proves Jon to be as correct as I thought he would be!

    Comment posted on February 21st, 2005 @ 8:52 pm
  21. Turnip:
    This commenter’s Gravatar

    Sorry, I forgot about this discussion. I talked with Anne on the subject, and among other things, he said he’d heard:

    Relative
    for ../something/ and the like
    Absolute relative
    for /something/
    and finally, Absolute
    for 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.

    Comment posted on February 22nd, 2005 @ 8:20 pm
  22. Mathias:
    This commenter’s Gravatar

    Thank you both, Jon and Anne. I think all my questions have now been answered:

    Absolute URI, absolute path
    http://example.com/whatever/
    Absolute URI, relative path
    http://example.com/shizzle/dizzle/../whatever/
    Relative URI, absolute path
    /whatever/
    Relative URI, relative path
    ../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 Absolute Relative Links, but I don’t think the title Relative Links is incorrect.

    Comment posted on February 22nd, 2005 @ 9:21 pm
  23. Turnip:
    This commenter’s Gravatar

    Or you could have put Relative URIs ;). But yeah, the title is still correct really. Has been an interesting discussion.

    Comment posted on February 23rd, 2005 @ 5:28 pm
  24. Choan:
    This commenter’s Gravatar

    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 if expression that decides if we do the call to ob_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 ;)

    Comment posted on May 2nd, 2005 @ 6:10 pm
  25. Mathias:
    This commenter’s Gravatar

    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! :)

    Comment posted on May 3rd, 2005 @ 7:43 pm
  26. Yves:
    This commenter’s Gravatar

    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:

    • Get-a-Post
    • Hide/Cut Post Text
    • Identify External Links
    • IImage Browser
    • Bread Crumb Trail Generator
    • Markdown
    • JÄÅ Preview Plugin
    • Search Pages
    • Staticize Reloaded
    • StatTraq
    • Polyglot
    • Translate Categories
    • WordPress: Touched
    • WordPress Hashcash
    Comment posted on May 23rd, 2005 @ 9:21 pm
  27. Clint:
    This commenter’s Gravatar

    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

    Comment posted on May 27th, 2005 @ 1:11 am
  28. Chutney:
    This commenter’s Gravatar

    Thanks for the plug-in! I had to switch from a .com to a .net a 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!

    Comment posted on June 15th, 2005 @ 8:13 pm
  29. Eric:
    This commenter’s Gravatar

    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:

    RFC 1738 specified that the path was separated from the authority portion of a URI by a slash. RFC 1808 followed suit, but with a fudge of carrying around the separator as a “prefix” in order to describe the parsing algorithm. RFC 1630 never had this problem, since it considered the slash to be part of the path. In writing this specification, it was found to be impossible to accurately describe and retain the difference between the two URI and without either considering the slash to be part of the path (as corresponds to actual practice) or creating a separate component just to hold that slash. We chose the former.

    Section 5 of RFC 2396, “Relative URI References”, is the proper reference as it supersedes RFC 1808.

    Comment posted on July 10th, 2005 @ 2:14 am
  30. Harry Jones:
    This commenter’s Gravatar

    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.

    Comment posted on March 5th, 2007 @ 6:01 pm

Trackbacks & Pingbacks (3)

Listed below are resources on the web that mention this article.

  1. Wordpress Plugin Competition Blog: Absolute Relative Links:
    This commenter’s Gravatar

    Absolute Relative Links
    I believe relative URIs with absolute paths (such as /pluginblog/ instead of http://weblogtoolscollection.com/pluginblog/, which is an absolute URI with an absolute path) should be used […]

    Trackback made on April 10th, 2005 @ 1:47 pm
  2. verbage.net: The making of this blog:
    This commenter’s Gravatar

    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
  3. С хаком по жизни » » Несколько доменов один wordpress:
    This commenter’s Gravatar

    […] Методика относительных ссылок разобрана здесь на английском языке. Заключается она в добавлении обработчика, работающего на регулярных выражениях для обрезания текущего домена из ссылок. […]

    Pingback made on December 11th, 2007 @ 3:52 pm