Appearance
Lesson 1 — Companion reference
This is your reference for Lesson 1 and its independent practice. You do not need to memorize every tag or property. Look up the part you need, try the example, and return to your own work.
Today we use plain HTML, CSS, VS Code, Live Server, and a browser. The Live Server extension serves your saved files locally and reloads the page when you save. No Vite, npm, or generated application is needed.
Find what you need
| I want to… | Read… |
|---|---|
| Understand HTML, CSS, JavaScript, and the DOM | The web page mental model |
| Open my page with Live Server and make changes | Working with local files |
| Choose the right HTML element | HTML essentials |
| Label and validate a form | Forms and accessibility |
| Make a page readable at different sizes | CSS essentials |
| Inspect a page and run Console expressions | DevTools reference |
| Fix a problem | Troubleshooting |
1. The web page mental model
Think of your web page in three layers:
text
Saved files on disk
├── index.html → content and meaning
└── style.css → appearance
│
▼
Live Server
(local HTTP)
│
▼
Browser
│
├── Reads HTML
├── Builds the DOM
├── Applies CSS
└── Renders what users seeJavaScript will eventually be another layer. It can read and change the DOM, respond to actions, and work with data. You will learn to write it properly in the next lessons.
Three things that sound similar
| Thing | What it is | How to inspect it |
|---|---|---|
| HTML source | The file you saved | Open index.html in VS Code |
| DOM | The browser's current object representation of the document | Use the Elements panel |
| Rendered page | The visual result | Look at the browser window |
If you edit a heading only in Elements, the browser may immediately show your change. But your file has not changed; refreshing loads the original text again.
Short version
Source is saved. DOM is live. CSS affects how the DOM looks.
2. Working with local files
2.1 Folder layout
For today's work, keep things simple:
text
my-page/
├── index.html
└── style.cssThe index.html document references the stylesheet using a relative path:
html
<link rel="stylesheet" href="./style.css" />./style.css means "the file named style.css in the same folder as this HTML file."
2.2 Install and use Live Server
Install once:
- In VS Code, open Extensions.
- Search for Live Server.
- Select the extension published by Ritwick Dey (
ritwickdey.LiveServer). - Click Install.
For each HTML exercise:
- Open your exercise folder in VS Code (File → Open Folder).
- Open
index.htmlin the Explorer. - Right-click the file and select Open with Live Server. You can also use Go Live in the status bar.
- The browser opens at an address like
http://127.0.0.1:5500/index.html. The port may differ. - Edit
index.htmlorstyle.css, then save the file. Live Server should automatically reload the page. - To stop the server, select the Live Server status control in VS Code or use the command Live Server: Stop Live Server.
If reloading does not happen, refresh manually and check that you are editing the same folder and file Live Server is serving.
2.3 file:// versus http://
file:// | http://localhost / http://127.0.0.1 |
|---|---|
| Opens a file directly from disk | Loads a file through a server running on your own computer |
| Does not make a normal HTTP request for the document | Uses ordinary HTTP requests and response status codes |
| Some browser features behave differently or are restricted | Closer to how browser-hosted web applications work |
| Not our standard preview workflow | Our Lesson 1 preview workflow |
The local server is not an online deployment and does not store form submissions. You will learn HTTP in more depth later.
Demo forms do not save requests
Our example form uses method="get". After valid submission, the browser may place the entered values in the page URL, but no backend receives or stores a travel request. Always use invented practice information.
3. HTML essentials
3.1 A minimal document
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Page</title>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<header><p>My Site</p></header>
<main>
<h1>Welcome</h1>
<p>Hello from my first page.</p>
</main>
<footer>Training example</footer>
</body>
</html>The important lines are:
<!doctype html>: tells the browser to use modern standards-mode processing.lang="en": declares the document language.<meta charset="UTF-8">: identifies the character encoding.<meta name="viewport" ...>: helps mobile browsers lay out the page as intended.<title>: appears in the browser tab, not in the page body.<h1>: the visible page heading.<link ... href="./style.css">: loads the stylesheet from the same folder.
3.2 Which element should I use?
| You want to… | A good choice |
|---|---|
| Show introductory site content | <header> |
| Group navigation links | <nav> |
| Identify the primary page content | <main> |
| Group related content under a heading | <section> |
| Show one self-contained card or news item | <article> |
| Show a list of items | <ul> with <li> |
| Show a table of actual data | <table> |
| Move to another location/page | <a href="..."> |
| Offer a user action | <button> |
| Receive input | <form> and its controls |
<div> is still useful for generic layout grouping. It simply does not describe the purpose of its contents as clearly as the semantic elements do.
3.3 Heading hierarchy
A clear page can use:
text
h1 Travel Requests
h2 Available journeys
h3 Porto workshop
h3 Lisbon meetings
h2 Request a tripHeading levels communicate a structure. Do not choose <h3> only because you like its default font size. Choose the level that matches the content, then change its appearance with CSS if needed.
3.4 Links to sections of the same page
html
<a href="#request">Go to the request form</a>
<section id="request">
<h2>Request a trip</h2>
</section>The part after # refers to an element's id on the page. That ID must exist and should be unique.
4. Forms and accessibility
4.1 A labeled input
html
<label for="work-email">Work email</label>
<input
id="work-email"
name="workEmail"
type="email"
autocomplete="email"
required
/>Each attribute serves a different purpose:
| Attribute | Purpose |
|---|---|
id | Uniquely identifies the element in the document |
for on <label> | Connects label and input through matching IDs |
name | Names the field value for normal form submission |
type | Chooses an appropriate browser control and some built-in validation |
required | Tells the browser not to accept an empty value for normal submission |
autocomplete | Helps browsers suggest appropriate saved values |
Try it: click the visible label text. The matching input should receive focus. If nothing happens, compare for and id letter by letter.
4.2 Common form controls
| Field | Example | What the browser provides |
|---|---|---|
| Name | <input type="text"> | Text entry |
<input type="email"> | Some email-format checking | |
| Date | <input type="date"> | Date entry; UI varies by browser/system |
| Number | <input type="number" min="1" step="1"> | Numeric entry and range/step validation |
| Destination | <select> | Choice from options |
| Notes | <textarea> | Multi-line text entry |
For a required destination select, the first option should have an empty value:
html
<label for="destination">Destination</label>
<select id="destination" name="destination" required>
<option value="">Choose a destination</option>
<option value="porto">Porto</option>
<option value="lisbon">Lisbon</option>
</select>4.3 Native validation: useful but limited
These attributes can provide checks without your writing JavaScript:
html
<input type="email" required />
<input type="number" min="1" step="1" required />But remember:
- Email validation checks the shape of a value; it does not prove the address exists.
requiredchecks that an input has a value; it does not prove the value is true.- HTML checks help users, but do not replace server-side validation in real applications.
4.4 What happens when we submit a demo form?
A demonstration form may use:
html
<form action="#" method="get">
<!-- labeled controls -->
<button type="submit">Submit demo form</button>
</form>After all required controls are valid, the browser may navigate and put the submitted values in the URL as query parameters. Live Server will continue to serve the page, but no information is saved because we have not built a service to receive and store it.
Use invented names and emails when experimenting. GET form values may become visible in the URL and browser history.
4.5 Keyboard access and visible focus
Use Tab to move forward between interactive elements and Shift+Tab to go backward. Verify that the focused element has a visible outline or other indicator.
You can improve focus visibility with:
css
:focus-visible {
outline: 3px solid darkorange;
outline-offset: 2px;
}Do not remove the browser's default outline unless you provide an accessible replacement.
5. CSS essentials
5.1 Selectors
css
p { /* every paragraph */
line-height: 1.5;
}
.card { /* class="card" */
padding: 1rem;
}
#request { /* id="request" */
margin-top: 2rem;
}
.card h3 { /* h3 inside a card */
margin-top: 0;
}A class can be reused across many elements. An ID should identify one element on the page.
5.2 Spacing and the box model
text
margin
└── border
└── padding
└── contentpaddingadds space inside a box's border.bordersurrounds the padded content.marginadds space outside the border.
A helpful rule is:
css
* {
box-sizing: border-box;
}It means an element's declared width includes its padding and border, but not its margins.
5.3 Flexible widths
Avoid designing only for one screen size.
css
.container {
width: min(100% - 2rem, 900px);
margin-inline: auto;
}The container can become narrow on smaller screens but does not grow indefinitely on large screens.
5.4 A little Flexbox
css
.field {
display: flex;
flex-direction: column;
gap: 0.35rem;
}In this example, the label and input stack vertically.
You can also arrange cards in a wrapping row:
css
.cards {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.cards > * {
flex: 1 1 15rem;
}5.5 A media query, if you need it
css
@media (min-width: 700px) {
.request-form {
max-width: 38rem;
}
}A media query changes styles when its condition is met. You do not need a media query for every responsive layout; flexible widths and wrapping often solve the problem on their own.
5.6 Common layout check
At a narrow screen width, check that:
- text is not clipped;
- you can still read each label and input;
- buttons can be reached and used;
- the entire page does not scroll horizontally;
- focus remains visible.
6. DevTools reference
6.1 Elements
Use Elements when you want to know:
- What HTML/DOM element am I looking at?
- Which class or ID does it have?
- Which CSS rules apply?
- Is the label's
forthe same as the input'sid?
Steps: right-click the visible part → Inspect → select the element → examine Styles.
Changes made in Elements are normally temporary. Your saved files remain unchanged.
6.2 Console
The Console lets you inspect the current page and, later, debug JavaScript.
Type these commands one at a time:
javascript
document.titlejavascript
document.querySelector("h1")javascript
document.querySelector("h1").textContentjavascript
document.querySelectorAll("input").lengthjavascript
console.log("The Console is working")querySelector returns the first matching element or null. If the element exists, .textContent reads its text. querySelectorAll(...).length counts matching elements.
You can also change the live page:
javascript
document.querySelector("h1").textContent = "Temporary heading"Refresh and the original heading should return, because the source file did not change.
When a Console expression fails
Check quotation marks, parentheses, and the CSS selector. Also check whether the element exists. If document.querySelector(...) returns null, reading .textContent from it will cause an error.
6.3 Network
The Network panel helps investigate loaded resources and, in later lessons, HTTP/API requests.
Today Live Server supplies files over HTTP. Reload with the Network panel open, then find index.html and style.css. Successful requests will usually have status 200. A stylesheet link to a nonexistent path will typically have status 404. The browser may also show other requests used by Live Server itself.
When something does not load, check the path referenced in your HTML:
html
<link rel="stylesheet" href="./style.css" />Then confirm that the file is really named style.css and is next to index.html.
6.4 Device toolbar
Use the device toolbar in DevTools (or resize the window) to test a narrow viewport. A useful comparison is approximately 375 CSS pixels wide versus a desktop width.
Check the page, not just the screenshot: can you still read and operate everything?
7. Troubleshooting
| Problem | Likely reason | First action |
|---|---|---|
| Browser shows old text | File not saved, or a different file/folder is being served | Save the correct file; check the Live Server URL; refresh manually if needed |
| Browser displays HTML tags as plain text | File may have been saved incorrectly | Confirm .html extension and open index.html with Live Server |
| CSS does not appear | Wrong link path or filename | Confirm href="./style.css" and folder location |
| Clicking a label does not focus the field | for and id do not match | Compare exact attribute values |
| In-page navigation does not move to a section | href="#..." does not match a section ID | Check both values |
| A field is not submitted | It may lack a name | Inspect the control's attributes |
| Required selection accepts a placeholder | Placeholder may have a nonempty value | Set the initial option to value="" |
| Page overflows on mobile | Fixed widths or unwrapped content | Inspect CSS widths in Elements |
Console expression returns null | The selector found no matching element | Inspect the actual tag/class/ID |
| Console expression produces an error | Syntax mistake or accessing a missing element | Read the message; check characters and selection |
| Valid form changes the URL after submit | GET form fields become URL query parameters | Expected for the demo; nothing is stored; use sample data |
| Network shows no HTTP requests for your page | Opened via file:// rather than Live Server | Right-click index.html → Open with Live Server |
| Go Live is missing | Extension not installed/enabled or no folder open | Install Live Server (Ritwick Dey), open the folder, and reload VS Code if needed |
| A different page opens | Live Server serves a different folder or file | Open the correct project folder; right-click its index.html |
| Stylesheet request is 404 | Wrong filename or relative path | Check href="./style.css" and the file location |
A repeatable debugging approach
text
Observe → Explain → Change one thing → Save → Check reload → RetestThat approach is more reliable than changing multiple unrelated lines and hoping for the best.
8. Self-check
Why is <main> better than a generic <div> for the main content?
It describes the purpose of that region and improves the document's semantic structure.
What is the difference between class and id?
A class groups elements, usually for reuse and styling. An ID uniquely identifies one element within the document.
What is the difference between id and name on a form control?
The ID identifies the control in the document and can connect it to a label. The name identifies the value in form submission.
Why can a form reject an empty required field with no JavaScript file?
The browser implements built-in HTML constraint validation.
How can the page change in DevTools without index.html changing?
DevTools can edit the live DOM or applied styles in memory. Those changes are not automatically written to the original source files.
Can we inspect HTTP status codes using Live Server?
Yes. The browser requests HTML and CSS using HTTP from your local computer. Successful requests commonly have status 200; missing files commonly have status 404.
9. Small examples for the practice
Use these as references, not as a complete solution.
A journey card
html
<article class="card">
<h3>Example trip</h3>
<p>Duration: 2 days</p>
</article>A labeled field
html
<div class="field">
<label for="department">Department</label>
<input id="department" name="department" type="text" required />
</div>Cards that wrap
css
.card-list {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}An email field
html
<label for="email">Email</label>
<input id="email" name="email" type="email" required />10. Useful documentation
- MDN — HTML introduction
- MDN — Document structure
- MDN — HTML forms
- MDN — Label element
- MDN — Input element
- MDN — Required attribute
- MDN — CSS basics
- MDN — DOM introduction
- Chrome DevTools — Inspect the DOM
- Chrome DevTools — Console
Ready to work independently? Open the Lesson 1 practice.