How anchor <a> work

I googled for a MageOverflow post how anchor work, so I don't have to write it down myself. But I couldn't find any.

If you only want to know, how a anchor (JS/CSS script link) needs to be built to work, scroll down.

So I'll do it myself, please send me links on Twitter or via mail if you find a better tutorial, so I can link it here.

Parts of a URI

As you can read on the parse_url doc every URI consists of the following parts:

  • scheme
  • host
  • port
  • user
  • pass
  • path
  • query
  • fragment

Some of them can be omit, but they exists, even if they are empty.

                    hierarchical part
                    authority               path
  └┬┘   └───────┬───────┘ └────┬────┘ └┬┘           └───┬───┘ └──┬──┘
scheme  user information     host     port            query   fragment

  └┬┘ └──────────────┬───────────────┘
scheme              path  

Thankfully borrowed from wikipedia


There are a lot of schemes, like file://, tcp://, tel://, mailto:.

Username and password

Usernames are used for example in ftp links. You can use them also in http links, to submit them to a .htaccess auth.


The hostname is often a domain, like, but it can use an IP address too:


Many schemes define default ports:

  • http: 80
  • ftp: 21
  • ssh: 22

So you can omit the port.


The parts before, including port are important to find the server (at least for http), so called authority. Starting with the path, we are on our way through the server to the right place.

We need to distinguish between directories and files, everything ending in a / is a directory, everything else is a file:



We can add additional informations, so the server knows, what we want


And we can link into whatever comes back.

What is the problem with all this?

Default values or omitting parts

For the following I'm only talking about http because the problems which motivate me to write this are all http related.

  • scheme - the same as the page we are on (http(s))
  • host - the same we are on, e.g.
  • port - 80/443 (or the same we are on)
  • user - I think none, but I'm not sure
  • pass - I think none, but I'm not sure
  • path - "/"
  • query - none
  • fragment - none

The following examples assume we are on the page:

You can only omit from left to right. This means of you want to omit the port, you have to go without scheme and host too!

Omitting scheme

When we omit the scheme, we use the same, as the page we are on.

If we link to // we will use http, because we are currently on an http served page. Please note the two // of the starting url.

But this means especially, we can include (third party) js and css files, based on the current scheme!

Don't use

but instead


(or even better

Omitting host

We can omit the host, it would look like this:


Then we assume the scheme is http and the host is It is important to understand, that this url is absolute. It takes the scheme, the host and the path and builds it together:

So if we move the blog from to lets say all links will break, because

this is built:
and here the blog post lives now

Omit the path

if you want to link relative you need to omit the first /, like so:


Here it is important to understand, that the relative link is relative to the current directory we are in. If our blog post urls are "directories", like this:

We have a problem, because the created link appends the new path the the current one:

and this URL is most likely wrong and broken.

As far as I know is there no solution for this problem, except knowing your base url and built your link upon this base url.

We get the same problem with css and js files! If we make them absolute:


we can't easily move them into a subdirectory, if we make them relative:


they will break on "deeper" pages, like:


Because the script doesn't live in


Omit the other parts


You can't omit the port (I think). It would look like this:


But this is rendered like a relative path (omitting the path).

User and password

User and password is "removed" by the browser from the current url, so the browser doesn't "know" anymore these details. If you want to use them, do it explicit.


Querys as fragments are part of a single request, therefore they are not removed from the url as user and password, but still not used in any other url on the page.

Hope this helps. If I have forgotten anything, please let me know: @Fabian_ikono