Links
Links are the entire reason the web is called a web: they are what connect isolated documents into something navigable, and they are how search engines discover pages at all (crawlers literally follow a elements from page to page). A page nobody can link to effectively does not exist.
The a element (anchor) turns anything into a link. Its href attribute (you met attributes in lesson 2-1) holds the destination:
<a href="https://developer.mozilla.org">MDN docs</a> <a href="/courses">Courses</a> <a href="#pricing">Jump to pricing</a> <h2 id="pricing">Pricing</h2>
Three kinds of destination:
- Absolute URL: a full address starting with
https://. Goes anywhere on the web. - Relative path: starts with
/(or nothing). Stays on the same site. - Fragment: starts with
#. An id is an attribute that gives one specific element a unique name on the page, like theid="pricing"on theh2above. A fragment link scrolls to the element whose id matches, with no page load. (ids return in lesson 3-1 to pair labels with inputs, and in unit 4 as CSS selectors.)
What a fragment link needs
For <a href="#team"> to scroll somewhere on click, an element with id="team" must exist on the page.
A fragment link targets an id, and the browser looks for the one element carrying that id and scrolls it into view.
| Markup | Result of the click |
|---|---|
an element with id="team" exists | the page scrolls to it |
| no such id | nothing happens |
If no element carries that id, the click does nothing at all, silently, which is a bug worth recognizing on sight. Ids must also be unique within a page, since a duplicate leaves the browser to pick one.
Images
img is a void element (no closing tag, lesson 2-1) with two attributes you should treat as mandatory:
<img src="/photos/team.jpg" alt="Four students at a whiteboard">
srctells the browser where the image file lives (absolute or relative, exactly likehref).altis a text description. Screen readers speak it, search engines index it, and the browser shows it when the image fails to load.
Write alt as if describing the photo to someone over the phone. Purely decorative images get an empty alt="", which tells screen readers to skip them. Omitting alt entirely is worse: many screen readers then read the file name out loud.
What alt text does when the image works
When an image loads perfectly, its alt text does nothing visible, and screen readers and search engines still use it.
alt is invisible while the image renders, and it is still doing its two most important jobs, describing the picture to screen reader users and to search engines.
| Situation | What alt does |
|---|---|
| image loads | invisible, still read by assistive tech |
| image fails to load | displayed in place of the picture |
| a purely decorative image | left empty on purpose, alt="" |
The third row is worth knowing, because an empty alt is a deliberate signal that the image carries no information, which tells a screen reader to skip it instead of announcing a filename.
A link and an image on one page
The a element wraps only the words that should become clickable, and img stands alone with no closing tag.
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Links and images</title> </head> <body> <h1>Useful things</h1> <p>Read the <a href="https://developer.mozilla.org">MDN docs</a> to go deeper.</p> <img src="team.jpg" alt="Four students working at a whiteboard"> </body> </html>
| Attribute | Element | Holds |
|---|---|---|
href | a | the destination |
src | img | the file to display |
alt | img | a description of the picture |
Only the words "MDN docs" sit inside the anchor, which keeps the clickable area meaningful instead of swallowing the whole sentence.
A good alt describes the picture rather than the file, so alt="Four students at a whiteboard" is useful where alt="team.jpg" is not. When the file is missing, the browser shows that text, which is also what a screen reader announces.
Rejecting unsafe link destinations
Pages often build links from data, and unsafe destinations such as javascript: URLs must be rejected. link(text, url) returns a full anchor tag when the destination is safe, and the bare text otherwise.
function link(text, url) { if (url.startsWith("https://") || url.startsWith("/")) { return '<a href="' + url + '">' + text + "</a>"; } return text; } console.log(link("Docs", "https://developer.mozilla.org")); console.log(link("Courses", "/courses")); console.log(link("Hack", "javascript:alert(1)"));
Output
<a href="https://developer.mozilla.org">Docs</a> <a href="/courses">Courses</a> Hack
| Destination | Verdict | Returned |
|---|---|---|
https://... | safe | a full anchor |
/courses | safe, same site | a full anchor |
javascript:alert(1) | unsafe | just the text |
startsWith returns a plain boolean, so the two checks combine with ||. Using single quotes around the outer string keeps the inner double quotes readable without escaping, and the unsafe case needs only one line, returning the text with no tag at all.
This allow-list shape is the right instinct. Listing what is permitted is far safer than trying to enumerate every dangerous scheme.