<a>href to handle clicks (ex. for opening a modal) - use a <button> instead<datalist><option> elements to be shown as suggestions in an <input> element, while still letting the user enter a custom value
<optgroup><input> types:
textmonth, week, date, time, datetime-localrangecolor<datalist id="apps">
<option value="Obsidian"></option>
<option value="Apple Notes"></option>
<option value="OneNote"></option>
<option value="Notion"></option>
</datalist>
<label>
<span>What is your favorite notes app?</span>
<input type="text" list="apps" />
</label>
<dialog> (modals/popups).show() to show non-modally, or .showModal() to show modally
showModal() will render everything outside the dialog [[#inert]].close(), or submit a form inside the modal with method="dialog"
autofocus attribute on a child to focus it when the dialog opens::backdrop pseudo-element:modal pseudo-class will target only modal dialogs (as well as fullscreen elements)<dialog> element fill the screen, and remove its default styles<dialog> that closes it, but only if the <dialog> itself was clicked<dialog>
<div>Contents go here</div>
</dialog>
dialog {
border: none;
background: none;
width: 100%;
max-width: none;
height: 100%;
max-height: none;
&::backdrop {
all: unset;
}
> :first-child {
max-width: 100%;
max-height: 100%;
overflow-y: auto;
}
}
document.querySelector('border').addEventListener('click', function (e) {
if (e.target === this) {
this.close()
}
})
<details> and <summary> (accordions)open attribute to open and close<details name="exclusive" style="padding: 10px; border: 1px solid currentColor;">
<summary>Click to open</summary>
<p>This text is inside the details element</p>
</details>
This text is inside the details element
<details> elements have the same name attribute, only one can be open at a time
<fieldset> and <legend><fieldset>
<legend>Flavors</legend>
<label>
<input type="radio" name="flavor" value="chocolate">
Chocolate
</label>
<label>
<input type="radio" name="flavor" value="vanilla">
Vanilla
</label>
<label>
<input type="radio" name="flavor" value="strawberry">
Strawberry
</label>
</fieldset>
<h1> which describes the entire page<h3> inside <h1> without an <h2> in between)<hgroup><h1> - <h6>) with any number of related <p> elements<img>The alt attribute is used by screen readers, and is shown if the image fails to load. It should contain text that can replace the image. It should not repeat information that is already provided in the text accompanying the image.
The title attribute is displayed in a tooltip on hover. It should contain text that supplements the image, like a title or caption. It works on any element, not just img.
<img
src="./mona-lisa.jpg"
alt="Painting of a smiling woman, sitting with her arms folded"
title="Mona Lisa, Leonardo da Vinci, 1503-1506"
/>
If an image is also a hyperlink, the alt text should describe the function of the link.
<input> and <label>for attribute even if an <input> is nested within its <label>, as some screen readers don't understand the implicit relationship<link>styles.css loads font1.woff2 and font2.woff2, and script.js fetches data.jsonstyles.css
font1.woff2font2.woff2script.js
data.jsonrel="preload"<head>
<link rel="stylesheet" href="styles.css" />
<script src="script.js"></script>
<!-- preloading -->
<link rel="preload" as="font" crossorigin href="font1.woff2" type="font/woff2" />
<link rel="preload" as="font" crossorigin href="font2.woff2" type="font/woff2" />
<link rel="preload" as="fetch" href="data.json" type="application/json" />
</head>
font requires the crossorigin attribute - see CORS-enabled fetches on MDNcrossorigin with as="fetch" may cause the preloaded file to be discarded in Chromium and Safari
fetch() in JavaScript to fetch the preloaded file, set credentials: 'include' and mode: 'no-cors', and do not include any custom headers| Value | Applies To |
|---|---|
| audio | <audio> elements |
| document | <iframe> and <frame> elements |
| embed | <embed> elements |
| fetch | fetch, XHR |
| font | CSS @font-face |
| image | <img> and <picture> elements with srcset or imageset attributes, SVG <image> elements, CSS *-image rules |
| object | <object> elements |
| script | <script> elements, Worker importScripts |
| style | <link rel=stylesheet> elements, CSS @import |
| track | <track> elements |
| video | <video> elements |
| worker | Worker, SharedWorker |
as attribute required<head>
<link rel="modulepreload" href="module.js" />
</head>
<menu><ul>, but can be used as a semantic alternative<meta><meta name="viewport"> is used to adjust the layout viewport size on mobile - see CSS#Layout<script>async scripts:
defer scripts:
DOMContentLoaded will not fire until deferred scripts finish executingtype="module" are deferred by defaultasync and defer are both ignored for inline scripts<section><table>border-spacing: [horizontal] [vertical] adjusts the gap between cellsborder-collapse: collapse removes the gap between cells (overrides border-spacing), and prevents borders from doubling up
<tr> have no effect unless border-collapse: collapse is setborder-radius must be applied to td, not <th>/<tr>
<td><table>
<caption style="caption-side: bottom">
Front-end web developer course 2021
</caption>
<thead>
<tr>
<th scope="col">Person</th>
<th scope="col">Most interest in</th>
<th scope="col">Age</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Chris</th>
<td>HTML tables</td>
<td>22</td>
</tr>
<!-- ... -->
</tbody>
<tfoot>
<tr>
<th scope="row" colspan="2">Average age</th>
<td>33</td>
</tr>
</tfoot>
</table>
| Person | Most interest in | Age |
|---|---|---|
| Chris | HTML tables | 22 |
| Dennis | Web accessibility | 45 |
| Sarah | JavaScript frameworks | 29 |
| Karen | Web performance | 36 |
| Average age | 33 | |
<caption>caption-side CSS property can be used to set the position (top or bottom)<video>preload attribute lets you control how much data is preloaded
nonemetadata: only size, length, etcauto (or empty string): can preload the whole video (but not guaranteed)
hidden="until-found" is only supported in Chromium as of May 2025
hidden or hidden="hidden": acts like display: nonehidden="until-found": hides the element until its content is found using the Find feature, then the hidden attribute is removed
beforematch event is fired before removing the hidden attributedisplay: none | contents | inline won't be revealed by the Find featuredisabled instead example: disabling content behind a modal (though the element does this by default when opened with showModal())
auto: can be dismissed by clicking outside, only one can be shown at a time unless they're nestedmanual: must be explicitly closedpopovertarget="id"
popovertargetaction can be set to show, hide, or toggle - default toggleshowPopover(), hidePopover(), or togglePopover() on the popover elementtoggle event with oldState === 'closed' and newState === 'open' or vice versa
beforeToggle is also fired with the same properties just before the popover is shown/hidden<div id="popoverExample" popover="auto">This is a popover!</div>
<button popovertarget="popoverExample">Show Popover</button>
::backdrop:popover-open targets open popoversevent.target vs event.currentTargetevent.target is the element that received the eventevent.currentTarget is always the element that the event listener is attached to
target is the child and currentTarget is the parent<div id="parent" onClick="handler()">
<div id="child"></div>
</div>
mouseover vs. mouseentermouseover fires when the mouse enters the element, or a child of the elementmouseenter doesn't bubble, so it doesn't respond to the mouse moving in and out of childrenpointerover and pointerenterinput vs. changeinput events fire every time the value of a <input>, <select>, or <textarea> element changeschange events only fire when the change is committed by the user (ex. by hitting Enter), or the element loses focus
change when they are deselectedchange for checkboxes & radio buttonsDOMContentLoaded vs. loadThe load event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images. This is in contrast to DOMContentLoaded, which is fired as soon as the page DOM has been loaded, without waiting for resources to finish loading.
The DOMContentLoaded event fires when the HTML document has been completely parsed, and all deferred scripts (<script defer src="…"> and <script type="module">) have downloaded and executed. It doesn't wait for other things like images, subframes, and async scripts to finish loading.
DOMContentLoaded does not wait for stylesheets to load, however deferred scripts do wait for stylesheets, and DOMContentLoaded queues behind deferred scripts. Also, scripts which aren't deferred or async (e.g. <script>) will wait for already-parsed stylesheets to load.
Be careful using tooltip or toast components, as they're often not accessible:
https://picsum.photos/200/300
https://picsum.photos/seed/seedGoesHere/200/300
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>