Lesson 11 / 25
Links
Resolving relative and absolute addresses, determining the base address, the information link text carries, and link relationship declarations.
Contents
Lists grouped content, but the document is still closed in on itself. A link is the element that connects a document to another resource, and it is what turns the web from a pile of documents into a network.
The link element a declares its target with the href attribute. This lesson takes up how
that attribute’s value is interpreted, what the text needs to carry, and the attributes that
declare the link’s relationship to its target.
Resolving the Address
The What the Browser Does lesson in the How the Internet Works course separated an address’s parts — scheme, host, port, path, query, fragment. The address written in a document most of the time does not carry all of these parts; missing parts are completed from the base address.
The base address is, by default, the document’s own address. The resolution rule is defined and gives the same result on every client.
// links.mjs — resolving relative addresses against the base address const base = "https://example.test/station/north-slope/measurements.html"; const candidates = [ "log.html", "./log.html", "../summary.html", "../../index.html", "/about.html", "//other.test/data.json", "https://other.test/data.json", "?type=humidity", "#temperature", "data/2024.csv", ]; console.log("base:", base); for (const candidate of candidates) { console.log(candidate.padEnd(28), "->", new URL(candidate, base).href); } console.log("--- the base element changes the base ---"); const newBase = new URL("/archive/", base).href; console.log("new base:", newBase); console.log("log.html".padEnd(28), "->", new URL("log.html", newBase).href);
base: https://example.test/station/north-slope/measurements.html log.html -> https://example.test/station/north-slope/log.html ./log.html -> https://example.test/station/north-slope/log.html ../summary.html -> https://example.test/station/summary.html ../../index.html -> https://example.test/index.html /about.html -> https://example.test/about.html //other.test/data.json -> https://other.test/data.json https://other.test/data.json -> https://other.test/data.json ?type=humidity -> https://example.test/station/north-slope/measurements.html?type=humidity #temperature -> https://example.test/station/north-slope/measurements.html#temperature data/2024.csv -> https://example.test/station/north-slope/data/2024.csv --- the base element changes the base --- new base: https://example.test/archive/ log.html -> https://example.test/archive/log.html
The output distinguishes five separate forms.
Same-directory relative: log.html and ./log.html give the same result; the directory
the document sits in is the base. Note that the document’s own name is dropped in resolution —
measurements.html is not part of the result.
Parent-directory relative: ../ goes up one directory on every repetition.
Root-relative: an address starting with / writes the path from the root; the host and
scheme come from the base. When the document moves within the directory tree, these addresses
do not change; relative ones do.
Scheme-relative: an address starting with // takes only the scheme from the base. Tying
the scheme to the document is not preferred, because it allows moving from an insecure context
to an insecure target; the scheme is written explicitly.
Same-document relative: addresses that carry only a query or a fragment keep the
document’s own path. Fragment addresses in the form #temperature never go out onto the
network at all; the target is the element in the document carrying that identifier.
Changing the Base Address
The base element, written in the head section, changes the base for every relative address
in the document.
<head> <base href="/archive/"> </head>
The output’s last section shows the effect: the same log.html value resolves to a different
address. This element is found at most once in a document and affects addresses written after
it; that is the reason it is written early.
Because its effect spreads across the whole document, this element is used carefully. It is not a decision affecting one section, it is one affecting every relative address — including fragment addresses in the document.
Characters in the Address
An address is written with a limited character set. Characters outside this set — Turkish letters, spaces — are converted to bytes with percent-encoding.
// encoding.mjs — non-ASCII characters and spaces in an address const base = "https://example.test/station/"; for (const candidate of ["ölçüm raporu.pdf", "veri/2024 mart.csv", "arşiv/kuzey-yamaç"]) { console.log(JSON.stringify(candidate), "->", new URL(candidate, base).pathname); } console.log("--- the host name is encoded with a separate rule ---"); console.log(new URL("https://ölçüm.test/veri").href);
"ölçüm raporu.pdf" -> /station/%C3%B6l%C3%A7%C3%BCm%20raporu.pdf "veri/2024 mart.csv" -> /station/veri/2024%20mart.csv "arşiv/kuzey-yamaç" -> /station/ar%C5%9Fiv/kuzey-yama%C3%A7 --- the host name is encoded with a separate rule --- https://xn--lm-4ia2d6a.test/veri
Every %XX pair is one byte, and the bytes are produced with the rule defined in the
Character Encodings lesson; because the letter ö takes two bytes, it converts to two pairs.
A space becomes %20.
The last line shows that the host name is handled with a separate rule: the path portion is written with percent-encoding, the host name with the ASCII representation stated in the What Is a Domain Name lesson. The same address’s two parts go through two separate encodings.
Writing file names with ASCII characters makes this conversion unnecessary and keeps the address readable; it is not mandatory, but it keeps the address short in the source text.
Link Text
A link’s text should declare what the target is. The criterion for this is not the sentence around it: screen readers present the links inside a document as a list, and the user scans that list by looking at their text.
<!-- carries no information once taken out of context --> <p>For daily measurement files, <a href="/data/log">click here</a>.</p> <!-- understandable on its own --> <p>Measurements are published <a href="/data/log">as daily files</a>.</p>
In the second way of writing, the link text defines the target. Two links in the same document carrying the same text but going to different targets is also a situation to avoid.
A link is for going to a resource, not for an action that does not leave the document — deleting a record, submitting a form. The button element is used for actions; the distinction will be covered in this topic’s form lessons.
The Target’s Type and Relationship
The download attribute requests that the target be downloaded instead of displayed, and
optionally gives a file name. The type attribute declares the target’s content type; it is
a hint, not binding.
The rel attribute declares the link’s relationship to its target. Its values are
space-separated keywords, and each one is defined.
<p>Raw data: <a href="/data/2024-03.csv" download type="text/csv">March records</a></p> <p>The method is defined in the <a href="https://other.test/standard" rel="noopener external"> measurement standard</a>.</p>
The target="_blank" attribute opens the target in a new context. Everywhere this attribute is
written, rel="noopener" is also written: it prevents the opened document from reaching, via
script, the document that opened it. Opening in a new context is itself a decision that
deserves review; it breaks the user’s expectation of going back, and whether the document
expects this behavior cannot be told from it.
The rel attribute is not specific to the a element. The link element in the head section
uses the same attribute and declares resources related to the document — a style file, an
icon, the same document’s version in another language, a paginated index’s previous and next
pages. On both elements, rel is the declaration “this address is in this relationship with
me.”
In the Station Document
<h2>Data Access</h2> <p>Records are published <a href="data/">as daily files</a>. The measurement method <a href="../method.html">is shared across the network</a>. Raw data files can be downloaded as <a href="data/2024-03.csv" download type="text/csv">March records</a>.</p>
All three links are written as relative and depend on the document’s place in the directory
tree. If the document moves, the ../method.html link breaks; root-relative writing prevents
this break but makes it harder to publish the document at another root. The choice between the
two forms of writing is a decision about where the document will be published.
Summary
- Relative addresses are resolved against a base address; the base is, by default, the document’s own address, and the document’s file name is dropped in resolution.
- There are five relative forms: same-directory, parent-directory, root-relative, scheme-relative, and same-document; fragment addresses never go out onto the network.
- The
baseelement changes the base for every relative address in the document and is found at most once in a document. - Link text should define its target even when taken out of context; screen readers present links as a list.
- The
relattribute declares the link’s relationship to its target; on links that open in a new context, thenoopenerrelationship is also declared.
Next Step
At this point the document can connect to other resources. What is left is this topic’s last structure: two-dimensional data. Measurement records are not a list, they are a table — every row has more than one field, and every field has a heading. The next lesson takes up table elements and shows how a data cell’s associated headings are computed.
To keep your progress and take notes, Log in
My notes
Log in to take notes.