The Web community is going crazy about SEO-friendly URLs like http://somesite.com/products/network/router/. Well, it looks much better than a script URL http://somesite.com/products.php?c=network&p=router which may actually serve the page behind the scenes. There are a lot of good articles on how to implement SEO-friendly URLs, for example this one or my own post. But they do not warn the reader about one usual problem: once you have updated your site to handle virtual paths you will probably get a bad surprise:
CSS, image and internal page links are totally broken!
Why? Because those links are usually relative to the page location. The browser has no idea about virtual folders and tries to get files from locations relative to the page URL context. For example, if there is a usual CSS link in the page header:
<link rel="stylesheet" href="style.css" type="text/css" media="screen" />
Then the browser will try to download non-existing file http://somesite.com/products/network/router/style.css and fail silently. No CSS style will be applied.
It’s incredible how many words were spoken about SEO-friendly URLs with almost no word about this relative link problem.
So, what you have to do? Don’t worry, there are multiple solutions available and I’ll try to explain them all.
Use <base> Tag in HTML Header
This is the most easy and reliable solution available. Absolutely the winner!
Just add a base tag with proper absolute location to head section of your page prior to any CSS link and the page will work again like a charm:
<head> <base href="http://somesite.com/" /> <link rel="stylesheet" href="style.css" type="text/css" media="screen" /> </head>
Well done! That’s all you really need.
The href parameter of base tag specifies the base path for relative links instead of a default page path.
Surprisingly, so useful tag is not well mentioned in manuals. But it is well supported by browsers and search engine bots so there is no need to worry about it. According to blooberry.com it is supported from IE 1.0, Opera 2.1 and Safari 1.0. Even Internet Explorer 5.0 supports it, LOL.
Base tag also works for relative URLs in CSS.
If there is any reason base tag can’t be used, please let me know in comments.
To avoid hard-coding absolute base path in every script you can set it as a constant. Alternatively, you can get it dynamically:
$baseUrl = dirname($_SERVER['PHP_SELF']).'/';
Other Solutions You May Want to Try
In case the solution with base tag is not an option, you can try one of the following solutions.
URLs relative to the site root
URLs beginning with a slash like /images/header.gif are considered relative to the site root folder. For example, if this link appears on any page of somesite.com it will always point to http://somesite.com/images/header.gif regardless of page URI.
This option is not acceptable if you need an ability to install your script in various locations of web server directory tree. For example, it will not work in your development environment if the URL of sandbox site copy is something like http://localhost/dev/somesite.com/.
But you can set up a virtual host in your development environment to use links relative to the site root. Thanks to Dan Lidral-Porter for the suggestion in comments to the article.
Absolutize URLs on-fly
With absolute site URL in hand you can convert relative links to absolute ones on page generation.
You can do this by adding absolute part when printing relative links:
<link rel="stylesheet" href="<?php echo $baseUrl; ?>style.css" type="text/css" media="screen" />";
Alternatively, you can do this by parsing HTML code and replacing relative links just before page output to the client. This is useful when you actually display HTML content loaded from another web site.
Have all shared stuff on an external domain
Since your CSS and JS may contain hardcoded URLs too and any change in the domain will affect them, you can move shared stuff to external cookieless domain and use absolute links to it.
(Thanks to Berny Cantos for the suggestion in comments to this article.)
Add rewrite rules for images, CSS, etc
Absolutely not recommended solution. Even while it works it results in terrible and badly extendable rewrite code.
Development of modern web sites always involves implementation of rewriting for SEO-friendly URLs. Keep in mind that you also need to solve relative link problem. Usage of base tag is the most recommended solution.