Skip to content
academia.sh

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.

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 base element 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 rel attribute declares the link’s relationship to its target; on links that open in a new context, the noopener relationship 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.

Start typing to search.

↑↓ Esc navigate · open · close