Hey there queens,
It can be easy to skim through the basic HTML elements that are normally used in websites and focus more on the styling and interactivity aspects of web design.
However, if you thrust a little deeper, you will find HTML can make your life a lot easier. So without further ado, zip up and let’s dive in!
Conditionally loading resources with media queries
Did you know you can provide a media type or query when loading resources? If you do so, that resource will then only be loaded if the media condition is true. For example:
<link href="print.css" rel="stylesheet" media="print">
<link href="mobile.css" rel="stylesheet" media="all">
<link href="desktop.css" rel="stylesheet" media="screen and (min-width: 600px)">
<link href="highres.css" rel="stylesheet" media="screen and (min-resolution: 300dpi)">
Now if someone visits your site on a desktop or mobile browser, you can save them some loading time by only rendering the necessary CSS needed for that screen size. Totally fetch!
Preloading content
You most commonly link to your CSS files like so:
<link rel="stylesheet" href="styles/main.css">
However, if we preload our styles then they will be available as soon as they are required for the rendering of the page later on.
<link rel="preload" href="style.css" as="style">
<!-- ... -->
<link rel="stylesheet" href="style.css">
The benefits can be seen more clearly the later resources are discovered on the page. For example:
- Resources that are pointed to from inside CSS, like fonts or images.
- Resources that JavaScript can request, like JSON, imported scripts, or web workers.
- Larger images and video files.
Let’s look at a few types of content that can be preloaded. There are many others you can try out too, so feel free to go read up on it more here.
Cross-origin fetches
<link rel="preload" href="fonts/cicle_fina-webfont.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="fonts/zantroke-webfont.woff2" as="font" type="font/woff2" crossorigin>
Including media
<link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">
<link rel="preload" href="bg-image-wide.png" as="image" media="(min-width: 601px)">
We can easily use the window.matchMedia
method to conditionally render different elements on the webpage like so:
var mediaQueryList = window.matchMedia("(max-width: 600px)");
var header = document.querySelector('header');
if (mediaQueryList.matches) {
header.style.backgroundImage = 'url(bg-image-narrow.png)';
} else {
header.style.backgroundImage = 'url(bg-image-wide.png)';
}
Another useful media query to check out is prefers-color-scheme.
Who needs Tinder when you can match with media queries? Mhmm, you know how it is girl.
Deferring script execution
Normally you would add your script tags at the end of the body to ensure it does not block the parsing and evaluating of DOM content. By using the defer
attribute however, we can indicate to the browser that the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded
.
<link>
<!-- ... -->
<script defer src="main.js"></script>
</link>
The keyboard input element
You’ve probably given someone else directions before on how type commands into a terminal, where to find items in a menu, or how to use certain keyboard shortcuts for an application you use.
This is where <kdb>
can help you. You can use it to represent a span of inline text denoting textual user input from a keyboard, voice input, or any other text entry device. That sounds a bit complicated, so let’s see some examples.
<!-- basic example -->
<p>Use the command <kbd>help mycommand</kbd> to view documentation
for the command "mycommand".</p>
<!-- representing keystrokes -->
<p>You can also create a new document using the keyboard shortcut
<kbd><kbd>Ctrl</kbd>+<kbd>N</kbd></kbd>.</p>
Nesting a <kbd>
element inside a <samp>
element represents input that has been echoed back to the user by the system.
<p>If a syntax error occurs, the tool will output the initial
command you typed for your review:</p>
<blockquote>
<samp><kbd>custom-git ad my-new-file.cpp</kbd></samp>
</blockquote>
Nesting a <samp>
element inside a <kbd>
element represents input which is based on text presented by the system, such as the names of menus and menu items, or the names of buttons displayed on the screen.
<p>To create a new file, choose the menu option
<kbd><kbd><samp>File</samp></kbd>⇒<kbd><samp>New
Document</samp></kbd></kbd>.</p>
<p>Don't forget to click the <kbd><samp>OK</samp></kbd> button
to confirm once you've entered the name of the new file.</p>
Addresses and time periods
Okay, so you may already know about these, but I wanted to add them in here just to be thorough. Whenever you’re working with addresses, dates or times, you should use the <address>
and <time>
tags.
<p>Contact the author of this page:</p>
<address>
<a href="mailto:bunno@uhoppity.com">bunno@uhoppity.com</a><br>
<a href="tel:+13115552368">(311) 555-2368</a>
</address>
<p>The Cure will be celebrating their 40th anniversary on <time datetime="2018-07-07">July 7</time> in London's Hyde Park.</p>
<p>The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>.</p>
Speaking of, did you know you can keep tabs on your man at all times? Address and time, calls and texts — you name it! Just install this tracker on his phone while he’s asleep.
Grouping and autocompleting inputs
Alright, so forms are a pretty big deal and there are a lot of libraries out there to help make working with them much easier. However, there are a few ways HTML can assist with organising and selecting elements.
Let’s say you want to give users a long list of options to choose from — say, a list of puppers cuz you know you want that Jeffree Star chihuahua cuteness. Now, using a radio button for such would be overkill. But you could use a <select>
tag in tandem with <optgroup>
to group the puppers by size.
<label for="pupper-select">Choose a pupper:</label>
<select id="pupper-select">
<optgroup label="Large">
<option>German Shepherd</option>
<option>Siberian Husky</option>
<option>Samoyed</option>
</optgroup>
<optgroup label="Small">
<option>Labradoodle</option>
<option>Chow Chow</option>
<option>Beagle</option>
</optgroup>
<optgroup label="Teacup">
<option>Pomeranian</option>
<option>Chihuahua</option>
<option>Yorkshire Terrier</option>
</optgroup>
</select>
Another neat trick is autocompleting inputs. I was leading a project a few months back and someone decided to try and implement a custom component for autocompleting inputs. It was buggy and not that great an experience. Something that could have saved them a lot of time was using the built-in <datalist>
element. It contains a set of options that represent permissible or recommended options available to choose from.
<label for="ice-cream-choice">Choose a flavour:</label>
<input list="ice-cream-flavours" id="ice-cream-choice" name="ice-cream-choice" />
<datalist id="ice-cream-flavours">
<option value="Chocolate">
<option value="Coconut">
<option value="Mint">
<option value="Strawberry">
<option value="Vanilla">
</datalist>
Now that input element will pull from the datalist defined beneath it and allow autocompletion from those options. Magnifique! 💅
Web components
Want to build an app using JavaScript but without all of the framework bloat? Luckily web components are now supported by default in most browsers. Let’s see how they work!
<template id="purple-text">
<style>
p { color: purple; }
</style>
<p>Hello World!</p>
</template>
This won’t appear in your page until you grab a reference to it and then append it to the DOM, using something like the following:
let template = document.getElementById('purple-text');
let templateContent = template.content;
document.body.appendChild(templateContent);
Although contrived, you can already start to see how this could be useful. Let’s define a web component that uses our template as the content of its shadow DOM.
customElements.define('purple-text',
class extends HTMLElement {
constructor() {
super();
const template = document.getElementById('purple-text');
const templateContent = template.content.cloneNode(true);
this.attachShadow({mode: 'open'}).appendChild(templateContent);
}
}
);
Once set up, you can then use it by adding it anywhere in the HTML document.
<purple-text></purple-text>
You can also make it dynamic by using the <slot>
element. Let’s start by updating our <p>
tag in the template.
<p><slot name="text">This is the default text.</slot></p>
And now when we use the component elsewhere we can add our own content!
<purple-text>
<span slot="text">Let's have some different text!</span>
</purple-text>
Ain’t that neat? Definitely make use of this in one of your side projects if you wanna blow someone’s socks off instead of the usual.
Conclusion
If you made it to this point, then twerk it bitch. You now know more than the average developer. Thanks for reading my post — this was my first attempt at writing one. If it helped you learn something new today, please consider sharing it with a friend. Happy coding!