HTML

Elements

<a>

<datalist>

<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)

With #transition-behavior

dialog, [popover] {
    transition-property: opacity, display;
    transition-duration: 0.25s;

    /* when setting `display: none`, keeps the element visible until the end of the transition */
    transition-behavior: allow-discrete;

    @starting-style {
        /* triggers fade in when showing */
        opacity: 0;
    }
}

dialog:not([open]) {
        /* triggers fade out when hiding */
        opacity: 0;
    }
}

[popover]:not(:popover-open) {
        /* triggers fade out when hiding */
        opacity: 0;
    }
}

Dismiss by clicking outside contents

<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)

<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>
Click to open

This text is inside the details element

Exclusive accordions

<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>
Flavors

Heading best practices

<hgroup>

<img>

alt vs. title attributes

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>

Even if you nest an <input> inside a <label>, you should still use the for attribute on label to link the two, as some screen readers don't recognize association through nesting.

Preload files

<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>
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

Preload JavaScript modules

<head>
    <link rel="modulepreload" href="module.js" />
</head>

<menu>

<script>

async vs. defer

See also

<section>

<table>

<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>
Front-end web developer course 2021
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>

<video>

Attributes

inert

  • lets you mark an element and its descendants as non-interactive, but still visible
  • inert elements:
  • use it on sections of content - if you want to disable an individual control use disabled instead example: disabling elements outside of a dialog (though the element does this by default when opened with showModal())
  • don't use it on elements with children that are important to understanding the page, since it will remove them from the accessibility tree
  • popover

    lets you show any element as a non-modal overlay on the top layer for modal overlays (which block interaction with the rest of the page), use
  • popovers come in two types:
  • Toggling

    <div id="popoverExample" popover="auto">This is a popover!</div>
    
    <button popovertarget="popoverExample">Show Popover</button>
    

    Styling

    With #transition-behavior

    dialog, [popover] {
        transition-property: opacity, display;
        transition-duration: 0.25s;
    
        /* when setting `display: none`, keeps the element visible until the end of the transition */
        transition-behavior: allow-discrete;
    
        @starting-style {
            /* triggers fade in when showing */
            opacity: 0;
        }
    }
    
    dialog:not([open]) {
            /* triggers fade out when hiding */
            opacity: 0;
        }
    }
    
    [popover]:not(:popover-open) {
            /* triggers fade out when hiding */
            opacity: 0;
        }
    }
    

    Events

    event.target vs event.currentTarget

    <div id="parent" onClick="handler()">
        <div id="child"></div>
    </div>
    

    mouseover vs. mouseenter

    input vs. change

    DOMContentLoaded vs. load

    The 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.

    Other

    Quick test image URLs

    https://picsum.photos/200/300
    
    https://picsum.photos/seed/seedGoesHere/200/300
    

    Load CSS asynchronously

    <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
    <noscript><link rel="stylesheet" href="styles.css"></noscript>