Lecture 2 Structure: HTML Markup

Topics for today

In the previous lecture, we talked about the difference between structure and presentation. So what is structure, and what is presentation? Take a look at these two elements. They look identical. But they do not have the same *meaning*. One is a top-level heading, and the other is regular text, styled to look big and bold. What difference does it make?
  • Same visual presentation (though this may differ per browser), but different meaning.

Why do semantics matter?

Not everyone browsing the Web is sighted

Screen readers depend on semantically correct HTML

Not everyone browsing the Web
is able to use a mouse

Keyboard navigation depends on semantically correct HTML

Focus

  • Focus determines where keyboard events go in the page at any given moment. It is widely understood to be the currently active element.
  • The Tab key moves focus to the next element in the tabbing order. Shift + Tab does the opposite, focusing the last element in the tabbed order.
    • Try it yourself: Click on the page on the right and press Tab a few times.
  • By default it's rendered as a blue fuzzy outline or a dotted solid one, but the styling can change with CSS. However, it is very important that there is styling for it, as keyboard users depend on it.
  • Users with various disabilities use the keyboard for navigation, but also power users often prefer the keyboard, as they find it more efficient.
  • Some resources to read more about focus:

Common focusable elements

Autofocus

<input type="text" autofocus>
  • Use autofocus when there's a clear starting point.
  • Which dimension of usability does this help?

Not everyone browsing the Web is human

Software (search engines, social media sharing etc) depend on semantically correct HTML

Not every browser is visual

There are also several text-based use cases, such as text-based browsers, and web scrapers.

Machine readable content is future-proof

Well written HTML naturally accommodates even use cases that did not exist when it was written. For example, Safari’s Reader mode, which strips out all the ads and other distractions. When it first rolled out, no website had any special support for it. But on websites where the HTML was well structured, it was able to extract the main content and display it in a clean format.

Semantic HTML is easier to maintain


			­		</div>
				</div>
			</div>
		

			­		</ul>
				</nav>
			</header>
		

			­		</div>
				</div>
			</div>
		

			­		</article>
				</section>
			</main>
		

			­		</div>
				</div>
			</div>
		

			­		</article>
				</section>
			</aside>
		
Semantic HTML is also easier to read and edit. It's easier to know where you are in the code when there's more variability in the elements used, compared to when everything is a div or a span. Remember, your code is also an interface; for yourself and other people. Which dimensions of usability does this help?

article or li?

Sometimes which element is most semantically appropriate is not quite straightforward, and there may be multiple correct answers. Here is an example: a list of products. Is a `<li>` more appropriate (since this is a *list*), or an `<article>` (since each product is an article (item))?
🤢
Let’s inspect what Amazon actually uses. A plain meaningless `<div>`?! Why is that? Many potential reasons: - Frameworks typically don’t understand meaning, and generate divs. - Could be older code (`<article>` and friends is relatively new)

Tables & meaning

In the early days, when CSS was less powerful, this kind of thing used to be very common, (ab)using a table to put things next to each other. About 15 years ago, even entire websites were laid out with tables, one cell for the header, one cell for the sidebar, one cell for the content etc. What is wrong with it?

Tabular data

The `<table>` HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. Take a look at this browser compatibility *table*, that is certainly tabular data! What about this summary element? Is that tabular data?

Semantic HTML

Document Object Model (DOM)

Trees (data structure)

You may have seen trees as a data structure before. Relationships between nodes (parent, child, sibling, ancestor, descendant) are borrowed from family trees. It is essential to understand tree relationships when using Web Platform technologies, as they are used in a variety of things.

DOM hierarchy

<li> HTML elements are <strong>objects</strong>, with a hierarchy called <em><abbr title="Document Object Model">DOM</abbr> tree</em> </li>
HTML start and end tags are not on/off instructions, but delimiters for the boundaries of HTML elements. Therefore, there is also a containment relationship between HTML elements that start *inside* others. These containment relationships create a tree, that is called *the DOM tree*.

Remember this?

What we wrote


				<!DOCTYPE html>
				<title>Hello world</title>
				<p>Hello <em>world</em> 👋
			

What the browser generated


				<!DOCTYPE html>
				<html>
				<head><title>Hello world</title></head>
				<body><p>Hello <em>world</em> 👋</p></body>
				</html>
			

Our DOM Tree

Document node Element nodes Text nodes
  • The browser’s internal model of our HTML is called the DOM Tree
  • It’s a hierarchy of objects of different types, such as:
    • Document: This is the root node, and does not correspond to any HTML element.
    • HTMLElement: Every HTML element, such as html, body, or em is of this type. Usually, they merely inherit from HTMLElement, and are an instance of a more specific type such as HTMLHtmlElement, HTMLBodyElement and so on.
    • Text: Text nodes, such as "Hello ", "world", and "!" in our example. These never contain any other element, they are always leaves.
    • Comment: HTML comments (<!-- like this -->) are represented by objects of this type.
  • This hierarchy of objects is crucial for CSS styling, as we will see in a couple lectures.
  • We can interact with, and manipulate the DOM tree via JavaScript!

Same content hierarchy, different DOM tree hierarchy

The structure of heading elements and sectioning elements creates the *content hiearchy* (also called *document outline*). This has to do with the meaning that is created by these elements. The DOM tree is a different hiearchy, and has to do with the types and relationships of elements on the page.

CSS selectors & the DOM

A large part of CSS selectors has to do with selecting elements based on their relationships with other elements in the DOM tree. Let's explore some of these. In the first lecture, we saw [*element selectors* (also called *type selectors*)](https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors) that select all elements of a given type. * We can use whitespace to target elements based on a *descendant* relationship (*descendant combinator*) * We can use a `>` symbol to target direct children (*child combinator*) * We can use a `~` symbol to target siblings that come after (*sibling combinator*) * We can use a `+` symbol to target the next sibling (*adjacent sibling combinator*) * Things after colons, like the `:nth-child()` here are called a *pseudo-classes*, and filter the selector they're attached to further. This particular pseudo-class filters selectors based on their index among their siblings. You can even use entire patterns like e.g. `:nth-child(3n+2)` which matches the 2nd, 5th, 7th etc children. * We will take a proper look at selectors later. The takeaway here is to show you how strongly related the DOM is with selectors.

The DOM Tree

Interactivity

Buttons & Forms

  • The button element creates buttons.
  • These buttons don’t do anything by themselves, but you can make them useful via JavaScript or form elements.
  • The action attribute of form elements controls which file will receive the submission. By default it's the current file.
  • What’s submitted? Only elements that are both enabled and have a name attribute.
  • target="_blank" works here too, to submit the form in a new tab

Use appropriate controls

<input type="text" placeholder="YYYY-MM-DD">

				<input type="number" name="day">
				<select name="month">
					<option>Jan</option>
					<option>Feb</option>...
				</select>
				<input type="text" name="year">
			
<input type="date" />

Sometimes the differences are subtle

<input type="text">
<input type="email">
Also, the fact that these differences are subtle now, doesn't mean they will remain subtle. By using the right input type, you opt in to any future usability improvements.

Multiple choices: usability tradeoffs


				<label><input type="radio" name="letter"> A</label>
				<label><input type="radio" name="letter"> B</label>
			

				<select name="letter">
					<option>A</option>
					<option>B</option>...
				</select>
			

				<input list="letters" />
				<datalist id="letters">
					<option>A</option>
					<option>B</option>...
				</datalist>
			

Depending on the number of options, different form controls are more appropriate for usability:

  • For < 5 options, prefer radios if there is enough space, as they are the most efficient. Users will be able immediately scan how many options they have and what each of those options are, without clicking (or typing) anything to reveal this information, and make their selection with a single click.
  • Between 6-20 options, <select> menus are ideal
  • For longer than 20 options, search time for <select> menus becomes longer than typing the first few characters. In those cases, use <input> with <datalist for autocomplete)

Two choices: Checkbox or radio?

When dealing with two options, a good rule of thumb is to use a checkbox if the answer is a simple yes/no, and radio buttons when the two options are alternatives.

The order of options matters too!

“This is not bad design, this is very good design that just happens to be evil” --> In UI design, this is called a *dark pattern*. We will talk a bit more about them later in the semester. [Watch the entire excellent talk here](https://vimeo.com/165123760).

Reactive Templating


				<article class="story">
					<img src="https://..." alt="...">
					<h3>Title</h1>
					<p>Content</p>
					<a class="read-more" href="...">Read more</a>
			

				{% for story in stories %}
					<article class="story">
						<img src="{{ story.image }}" alt="{{ story.imageDescription }}">
						<h3>{{ story.title }}</h1>
						<p>{{ story.content }}</p>
						<a class="read-more" href="{{ story.url }}">Read more</a>
					</article>
				{% endfor %}
			
- Writing HTML by hand can be repetitive. The same fragments with small differences are repeated across pages (headers, footers, menus etc) as well as within the same page, to display lists of data.

Editor-based approaches

- Some approaches to reducing repetition center around editing tools (e.g. snippets or [Emmet](https://emmet.io/), shown here and already integrated in your editor) - However, this doesn’t help when data changes and HTML needs to be re-generated. - It also bloats the HTML file with repetitive code.
- There are languages that generate HTML as output, allowing for abstractions and automation. Some are regular fully fledged programming languages that can also be used for templating (e.g. PHP) and some are domain specific, and are designed for templating only (e.g. [Nunjucks](https://mozilla.github.io/nunjucks/)).]) - Apps manage data in machine readable form, and an important step is presenting data in human readable form. Templating has emerged as a great way to do that.

But what if the data changes?

Google Sheets

You have likely used reactive programming before, even if you don’t know it. Spreadsheets are the canonical example of reactive programming. When you change the value of a cell, all the cells that depend on it are automatically updated.

JS


			let a = 1;
			let b = 2;
			let sum = a + b; // 3
			a = 3;
			console.log(sum); // still 3
		
This is not how most programming works, such as JS or Python. In imperative programming, you have to manually update the value of `sum` when you change `a` or `b`.

CSS is reactive

JS


			button.addEventListener("mouseenter", function() {
				button.style.boxShadow = "0 0 5px gold";
			});
			button.addEventListener("mouseleave", function() {
				button.style.boxShadow = "";
			});
		

CSS


			button:hover {
				box-shadow: 0 0 5px gold;
			}
		

VueJS

[VueJS](https://vuejs.org/) (syntax shown here also uses [`<v-app`](https://mavue.mavo.io/v-app/) from [MaVue](https://mavue.mavo.io)) allows us to create UIs and write JS that utilize reactivity. This makes DOM updates much easier to program compared to raw JS. `v-model` is a Vue *directive*: A special attribute that tells Vue to do something. In this case, it tells Vue to keep the `a` and `b` properties and the input values in sync. The values of directives are JavaScript expressions. Why the name `v-model`? It comes from the software engineering concept of "model-view separation", i.e. the idea that the view (UI) is largely a deterministic function of the data. The `{{ }}` syntax allows us to reactively output the value of a JavaScript expression. You should read more about [Vue’s templating syntax in the official documentation](https://vuejs.org/guide/essentials/template-syntax.html). One thing to keep in mind is that there is a different syntax for outputting expressions in regular text, and a different one for outputting expressions in attributes.

JSON data

{ "name": "Lea", "age": 37, "numbers": [1, 1, 2, "three"], "unique-numbers": new Set([1, 1, 2, 3])[1, 2, 3], "nested": { "visible": true, "missing": null }, }
A lot of Vue revolves around synchronizing a View (UI) to match a data object. So how is data specified in JS? The syntax is largely similar to Python, with JS object literals being similar to dictionaries, and arrays being similar to lists. There is also a more restricted syntax which is called JSON and is also used as a textual data exchange format. The main differences are that in JSON: - Properties must always be quoted. In JS, properties that are valid identifiers (e.g. `age`) can be unquoted. - Trailing commas are not allowed - `null` is the only empty value allowed - While values in JS could be anything, JSON only supports strings, numbers, booleans, arrays, objects, and `null`. - Strings can only be double-quoted (`"foo"`, not `'foo'`).

VueJS (no <v-app>)

This is closer to how Vue is used in the wild. We will mostly use the [`<v-app>`](https://mavue.mavo.io/v-app/) element in the slides to keep examples shorter, but the homework skeleton is using this syntax as it allows for more flexibility, and makes it easier to add methods, computed properties etc.

VueJS is data-first

A design principle of Vue is that the source of truth is the *data*. If you have conflicting values in your HTML they will be ignored — and a warning will be printed out. Check out the console to see the error.

Vue Lists

- A very powerful feature of Vue is the ability to *repeat* an HTML structure as a template for each item in a list of data. - The [`v-for`](https://vuejs.org/api/built-in-directives.html#v-for) directive is used to do this. - The [`v-if`](https://vuejs.org/api/built-in-directives.html#v-if) directive is used to conditionally show an element. Note that `v-if` *removes the element from the DOM entirely*. If you only want to hide it, use [`v-show`](https://vuejs.org/api/built-in-directives.html#v-show) instead.

Actions

- Vue also allows us to execute code when something happens - The syntax is an attribute starting with `@` followed by the event name (e.g. `click`) - It is an alias of the [`v-on`](https://vuejs.org/api/built-in-directives.html#v-on) directive

Not just clicks!

- After `click`, `input` is probbly the most common event and fires when the value of a form control changes - Other useful events are [`keyup`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event) (when a key is released) and [`submit`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event) (when the value of an input changes) and

Simple abstractions

- The JS syntax is more convenient when we want to abstract away complex actions and calculations - Computed properties and methods allow us to abstract away complex calculations or actions and keep our templates cleaner. - Methods can also *modify* data! - Note that we use `this` to access our root-level data in JS-land. You can also use `app` (the return value of the `createApp` function) - Want to inspect the current state of your data? Use `globalThis.app = app` in your JS, then `app` becomes a global variable you can play with in the console. Though you should probably use the [Vue devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) instead.

Web apps with HTML?

Mavo


			<body>
				<h1>My tasks</h1>
				<p>0 done of 1 total</p>

				<ul>
					<li>
						<input type="checkbox" />
						<span>Do stuff</span>
					</li>
				</ul>
			</body>
		

			<body mv-app="todo" mv-storage="local">
				<h1>My tasks</h1>
				<p>[count(done)] done of [count(task)] total</p>

				<ul>
					<li property="task" mv-multiple>
						<input property="done" type="checkbox" />
						<span property="taskTitle">Do stuff</span>
					</li>
				</ul>
			</body>
		

			<body mv-app="todo" mv-storage="local">
				<h1>My tasks</h1>
				<p>[count(done)] done of [count(task)] total</p>

				<ul>
					<li property="task" mv-multiple>
						<input property="done" type="checkbox" />
						<span property="taskTitle">Do stuff</span>
					</li>
				</ul>
				<button mv-action="delete(task where done)">
					Clear completed
				</button>
			</body>
		

Try Mavo out


			<link rel="stylesheet" href="https://get.mavo.io/mavo.css"/>
			<script src="https://get.mavo.io/mavo.js"></script>
		

or just visit play.mavo.io and start coding!

A brief, messy history of HTML

SGML: A meta-language to generate markup languages, with custom syntax, described by a DTD.

Tim Berners-Lee adapts IBM Starter Set, a markup language written in SGML, adds <a> and calls it HTML 1. A specification never existed.

HTML 1 elements

<title> <nextid> <a> <isindex> <plaintext> <listing> <p> <h1> <h2> <h3> <h4> <h5> <h6> <address> <dl> <dt> <dd> <ul> <li>
Source

IETF publishes a specification (RFC) for HTML 2, using SGML properly, with a DTD. No software actually used the DTD to display HTML, only validators. In fact, most HTML documents were not valid SGML.

HTML 3.0 adds math, figures, tables, stylesheets. IETF rejects as “too ambitious” and closes its HTML WG.

HTML moves to W3C, founded by Tim Berners-Lee. The far less ambitious HTML 3.2 is published standardizing what was already implemented. Adds <style> and <script> reserved for future use.

HTML 4 deprecates presentational HTML, adds frames, extends forms.

XHTML 1 is published. Like HTML4, but with XML syntax. Separates parsing from semantics and makes HTML extensible. Draconian error handling (in theory)

XHTML 2: Fresh start, theoretically pure vocabulary with little concern for backwards compatibility. Browsers refuse to implement, lose faith in W3C, found WHATWG

HTML 5 “paves the cowpaths”, standardizes long supported features, adds video, audio, new input types, sectioning, generated graphics, <svg>, <math>, figures, custom data-* attributes. Breaks compatibility with SGML, defines its own compatibility-oriented parsing.

W3C and WHATWG continue to work on HTML 5 independently, often diverging. Browsers follow the WHATWG spec. On 28 May 2019, the W3C announces that WHATWG would be the sole publisher of the HTML and DOM standards.