.htaccess rewrite URL leads to missing CSS

14,705

Not being able to find your JavaScript and CSS files is a client-side/browser issue related to your URL-path, it's not something that should be fixed in .htaccess (at least not in this case) - although it is because you are changing this URL-path (in .htaccess) that you are experiencing this problem.

This problem is caused by using relative URLs in your HTML. Relative to what? Remember, it is the user-agent/browser that resolves relative URLs in your HTML, not the server. So, you need to fix your URLs; not .htaccess.

For example, if you are referencing your CSS file with a relative URL of the form href="styles.css" (note, no slash prefix) and you are currently at the URL example.com/view.php?id=15 then the browser will naturally resolve your CSS URL and request example.com/styles.css (in the document root). However, if you are currently at the URL example.com/watch/15 (effectively in a /watch "subdirectory" [*1]) then the browser will resolve your relative CSS URL relative to a /watch subdirectory, rather than the document root, so you end up with an absolute/resolved URL of the form example.com/watch/styles.css.

([*1] Note that "subdirectory" in this context is not necessarily a physical subdirectory on your server - it is a "subdirectory" in the URL-path; an additional path-segment. But the browser does not know the difference.)

The same applies if you are using relative URLs in your custom error documents (defined with the ErrorDocument directive on Apache). The custom error document can potentially be called on any URL, so any relative URL to a static resource (CSS, image, JS, etc.) is going to be relative to the URL that caused the error, not relative to the error document itself (the location of which is effectively hidden from the user-agent).

If you changed your JavaScript and CSS URLs to be root-relative (starting with a slash) or even absolute then you would not get this problem. This would be the preferred method. Alternatively, you can use the base element...

base tag/element

Alternatively you can include a base element in the head section of your HTML document (although this is not without its caveats [*2]). This references the absolute URL that all relative URLs are relative to. In other words, since you are expecting these relative URLs to be relative to the document root then add the following to the head section:

<base href="http://example.com/">

Now, a relative URL such as styles.css referenced in a document at URL /watch/15 will request http://example.com/styles.css, not http://example.com/watch/styles.css.

[*2] There are, however, some caveats with using the base element. A primary concern is that any relative URL that is intended to target the current document will now target the base URL instead. This can effect in-page anchors like href="#top" and URLs of the form href="?sortby=date" etc. And also form elements that submit to themselves using an empty action attribute (eg. <form action="" ...). These relative URLs that target the current document will need to be modified to include the full URL of the current page (which may defeat the point of using the base tag as a workaround to begin with).

Reference:

Share:
14,705

Related videos on Youtube

StuckBetweenTrees
Author by

StuckBetweenTrees

Updated on September 18, 2022

Comments

  • StuckBetweenTrees
    StuckBetweenTrees over 1 year

    I am trying to make my url from this:

    example.com/view.php?id=15
    

    To this:

    example.com/watch/15
    

    My code in .htaccess is as follows:

    Options -Indexes
    Options +FollowSymlinks
    RewriteEngine On
    RewriteRule ^watch/([^/]+) view.php?id=$1 [NC]
    

    Now if I go to example.com/watch/15 it loads the content but without any JS, CSS because in this case it looks for CSS and JS under the /watch folder which doesn't exist.

    How do I make this option work properly? I don't want to create watch folder and copy-paste CSS and JS so it will embed properly.

  • StuckBetweenTrees
    StuckBetweenTrees over 8 years
    Yes it works once I add base in the head section. I wasted 2h trying to work it out and yet its simple as adding 1 line of code... Many thanks for your informative answer!