WEB DEVELOPMENT · GUIDE
Relative vs. Absolute URLs: A Guide for Directory-Based Websites
Understand why a link works on your homepage but breaks three directories deeper.
When a site uses real directories and index.php files, its URLs are pleasantly readable. But links and image references can become confusing as pages move deeper into the directory tree. A stylesheet that works on the homepage may fail on a tutorial page because the browser is resolving the same relative reference against a different base URL.
The solution is to distinguish a complete URL, a reference from the site root, and a reference from the current document. These are browser addresses. They are separate from the filesystem paths PHP uses when it includes a file. Keeping those two systems straight makes a small directory-based website much easier to maintain.
An absolute URL names the destination
A complete absolute URL includes the scheme and host, such as https://www.knut-edvart.com/programming/. It identifies the destination without relying on the current page’s directory. Use this form for external websites and places where the reference must stand on its own, such as a sitemap or a canonical URL in the page head.
An absolute URL also commits to a particular host. If you copy a production page into a staging site, absolute internal links may still send you to production. That is sometimes intentional but often surprising. For normal links within a site deployed at the domain root, a root-relative reference is usually easier to reuse.
A leading slash starts at the site root
The reference /css/style.css means the path starts at the root of the current origin. From either the homepage or a deeply nested article, it resolves to the same stylesheet. A link to /tools/ works similarly. On our PHP site, this is a useful convention for shared navigation, JavaScript files, images, and category links.
<link rel="stylesheet" href="/css/style.css">
<script src="/javascript/main.js" defer></script>
<a href="/programming/">Programming</a>
The leading slash does not mean the root directory of your server’s filesystem. It is part of a URL. Also, root-relative references assume the website occupies the domain root. If you publish the same site under example.com/demo/, /css/style.css still points to example.com/css/style.css, not to the demo directory. A subdirectory deployment needs a consistent base path or adjusted references.
No leading slash means resolve from the document
A reference such as images/photo.jpg is resolved against the current document’s base URL. From https://example.com/tutorials/php/, it points to https://example.com/tutorials/php/images/photo.jpg. From the site homepage, the same reference points to https://example.com/images/photo.jpg. That difference explains many missing images on nested pages.
The dot segments ./ and ../ refer to the current directory and its parent. They can be useful for content intentionally kept beside a page, but long chains of parent references become fragile when you reorganize directories. For shared assets, prefer a consistent root-relative convention if your deployment allows it.
Trailing slashes affect the base
Consider two base URLs: https://example.com/tutorials/php/ and https://example.com/tutorials/php. The first ends in a directory-like path. The second treats the last segment as the part to replace when resolving a simple relative reference. As a result, image.png resolves under /tutorials/php/ in the first case and under /tutorials/ in the second.
const a = new URL('image.png', 'https://example.com/tutorials/php/');
const b = new URL('image.png', 'https://example.com/tutorials/php');
console.log(a.href); // https://example.com/tutorials/php/image.png
console.log(b.href); // https://example.com/tutorials/image.png
A web server may redirect a directory request to its slash-ended form, but understand which URL is ultimately used as the base. Consistent internal links and canonicals help keep this predictable. The HTML <base> element can change reference resolution across a document, so check for it when a link behaves unexpectedly. Do not add one merely to patch a single broken image.
CSS assets resolve from the stylesheet
A relative reference inside an external stylesheet is resolved against that stylesheet’s URL. If /css/style.css contains url(../images/background.png), the image is requested from /images/background.png. The depth of the HTML page does not change that CSS reference. This is different from an <img src="..."> reference written directly in the page.
Use the browser’s network tools to see the actual requested URL for a missing asset. The request often reveals the problem immediately: an extra directory, a wrong host, or a repeated path segment. Inspecting the resolved request is more useful than repeatedly changing strings until one happens to work.
PHP includes use filesystem paths
A browser requests /css/style.css, but PHP might include a template from a path such as /home/account/public_html/layout/header.php. These serve different purposes. Use __DIR__ or a defined project root when locating include files; use public URLs in generated HTML. A server filesystem path should not be placed into an image source or a visitor-facing link.
<?php
// From a page one directory below the project root:
require dirname(__DIR__) . '/layout/render.php';
// HTML generated by the template uses public references:
// <link rel="stylesheet" href="/css/style.css">
This is also why a template can load correctly while its stylesheet fails: the PHP include succeeds on the server, but the browser separately resolves the stylesheet URL. For more on predictable local paths, see the PHP text-file tutorial.
A convention you can maintain
Use complete HTTPS URLs for external links, canonicals, sitemaps, and sharing-image metadata. Use root-relative references for shared internal links and assets when the site lives at the domain root. Use document-relative references when the relationship to a nearby file is intentional. Before publishing, test the homepage and one deeply nested article, because a reference that works at the root can hide a problem farther down the tree.
Reference: MDN relative URL resolution and CSS url().