skip to content
Alert! Your web browser does not fully support Cascading Style Sheets! Our website works best using using one of the following modern web browsers: Chrome, Firefox, Edge.

HTML5 Tutorial

HTML5 Element List

HTML5 is almost identical to the much older standards - HTML 3.2 / HTML 4.1 / XHTML 1.0 / XHTML 1.1 - all of which we implemented in websites from the 1990's up until 2008, when the first HTML5 recommendations were released for review. Now here in 2022, we have fully embraced HTML5, CSS3, and all the newer changes coming on the horizon that advance better website technologies. However, the basic design of HTML5 is the same as old HTML. There really is nothing truly cutting edge. The same goes for ECMAScript 6 and later. Its the same basic server-client model, same basic HTML and JavaScript parsers, same DOM, same single threaded browsers, and the same basic client-server model of information delivery. In addition, the past 20+ years have left a trail of older web technology and web pages that still run perfectly well and makes companies billions of dollars every year! But many older browsers remain behind that do not support HTML5, or which only partially support it. Without careful HTML design, you risk locking out millions of viewers from your website. As the HTML5's new "Living Standard" slowly evolves, it will continue to leave a trail of partial support in modern browsers used today.

Most of the elements in HTML5 look and work the same as those in say old HTML 4.1 and XHTML, with a few exceptions that are important. That fact has allowed experienced web developers to build on best practices gained from the past in the infancy of the World Wide Web when browser support for HTML and CSS was spotty. Without going into too much detail here, I will simply list below the core HTML5 elements supported that are universal to most past and present HTML recommendations, and talk about items unique to HTML5 you should be aware of. I will also list a few HTML5 elements that I do not recommend, either because few modern browsers support them, they rely on heavy JavaScripting to function, or the technology behind them fails.

Along with examples of solid HTML that works in old and new browsers, I have also added a full list of important attributes I recommend for those elements that allow your HTML markup to work at its peak and give browsers, search engines, and screen readers the necessary information they need get the most out of your website and its markup or scripting code. After this HTML5 elements list, I have added a "Best Practices" section with advice and code examples you should consider that build on 20 years of my personal web development experience. I will always include code in both sections which you can cut-and-paste into your web projects.

Keep in mind, this tutorial is quite a comprehensive list, but not totally exhaustive. It is likely there are details left out on some things you use I do not that are helpful in projects. They may not be that valuable in designing good cross-browser HTML, however. I have added all the newest elements and attributes, even some cutting edge stuff not yet talked about online. So this tutorial is cutting-edge. But the basic idea behind good HTML markup practices is first committing to using a "core" set of HTML and CSS code that works in old and new browsers, as well as solid design principles that are reliable across all web projects and which will stand the test of time. The "test of time" concept is what makes them great. Using the latest and greatest HTML and CSS technologies does not always benefit your projects simply because you leave so many other user's behind when you do. Anything added AFTER good HTML is icing on a cake you should have already carefully baked. JavaScript API's, for example, should always be layered over good HTML practices. They should ONLY be the icing. They can never be the cake or replace good HTML coding practices. Good HTML and CSS code is what works reliably in many browsers with few changes over years and years, as scripts and API's come and go. When JavaScript API's and frameworks are stripped away, or die from disuse over time (which nearly all will do), remember that after the smoke clears, good content written in good 'ol reliable HTML will always remain behind as it has been for almost 30 years on the Internet, now. Remember that fact, Luke, and the "HTML Force" will be with you!

HTML5 Element Table
Element Name HTML Example
<a> anchor, link, hyperlink

Anchor

<a href="http://yourwebsite.com/" id="a1" title="View my Website" target="_blank" rel="noreferrer nofollow noopener" tabindex="0" aria-label="Your Website Link">A Hyperlink</a>
My Recommendations:
  1. The 'a' element defines a hypertext link or hyperlink, which contains a URI/URL location on the Internet you go to when the anchor element is clicked.
  2. The 'id' attribute value must be unique for each element id in the current web page. It identifies the element for faster script access and allows you to apply a CSS style with high selectivity than most elements and classes. Many people do not use "id", but I recommend you use it on links as it is quite important in uniquely identifying those elements in a page and makes manipulating them in JavaScript very easy. I generally use "id" on structural elements, as well as forms, menu items, and important elements I manipulate in the page.
  3. The 'href' attribute can be a hyperlink URI (http://example.com/), an internal page anchor/bookmark ("#"), blank, or an email address in the format of : "mailto:webmaster@domain.com?subject=mysubject&body=mybody". The latter will then attempt to trigger the users default email "client", if one is installed, and create an email with any attached "subject" or "body" text found in a query string within the link.
  4. Always add a 'title' attributes or "tooltip" to anchor elements so users on rollover know where the link goes or what it does before they click it. A 'title' attribute should always contain a text "description" of the element, not a "label" or alternative text like you see in images. When a user rolls over the element, the title usually describes what the link does. In addition, on rollover, most modern browsers display where the link goes ("href" value) at the lower left corner of the browser so the user knows where they are going before they click it. This is also a good security feature.
  5. The 'target' attribute allows the user to open the page in the same window or a different one when the link is clicked. "_blank" is commonly used to open a new browser window for the link so the user does not use their current page reference. In the old HTML4 days '_self' and names of frameset windows might use various values for 'target', but those are rarely used now.
  6. The 'rel' Attribute: The 'rel' attribute describes the relationship between the current document and a linked document. It really is only used on anchor links, forms, and the 'link' element where it often defines the link type associated with external files. Because its rarely needed in forms, the anchor tag is the only other element where you might find it useful. The "ref" attribute can be a variety of values, but most of the values associated with "rel" attributes are not supported in browsers, are experimental, deprecated, or rarely used. I will not cover the values for "rel" here when using 'link' elements. See that section for more info. Some values like "author", "bookmark", etc. might seem helpful on anchor tags, but are not widely used. Only a few "rel" values are truly helpful, which includes the ones in my code sample above.
    "noreferrer", "nofollow", or "noopener": This special set of attribute values is important, especially when linking to external websites via 'target=_blank', as shown in the sample code above. Adding all three attributes does NOT stop the link from working but adds additional hyperlink features. All are optional and can be mixed and matched. Add 'noreferrer' attribute on outgoing links when you don’t want other sites to know that you are linking to them. Adding the noreferrer tag to your links does not directly impact SEO but does have an indirect effect in your link building and promotion efforts by hiding your site from web domains that might be open to giving you traffic back. When you add 'nofollow' to an external link, you basically instruct search engines not to pass any Page Rank from one page to the other. In other words, you tell them to ignore that link for SEO purposes. It informs search engines that the link is commercial in nature, or that it’s a link you don’t endorse. 'noopener' prevents the opening page gaining any kind of access to the original page via a JavaScript function. Your link page and the new page have a parent-child relationships. The new page will have an access to your parent window object via 'window.opener' and it can navigate the linking page to a different URL using window.opener.location so can be security risk. This stops that risk. In all cases above, the links still function, they just don't pass any information beyond a plain hyperlink function. Note: The "rel" attribute is not supported by any Internet Explorer browser.
  7. The 'accesskey' attribute allows users to avoid using their mouse when clicking a link and instead use a special keyboard hot key combination (alt+a, or alt+shift+a, or apple key+a, etc.) to select the link on the page and then hit 'return' to open it. In the past, this was safe to do because all our users were on desktops. With mobile and other devices, you risk triggering unknown features on the device using the "accesskey" attribute, or they simply do not work. Because this feature could trigger other events on various devices or mobile phones, or may have limited browser support, I do not recommend you assign your links an access key.
  8. The 'tabindex' attribute is optional and allows users to tab through and select ordered lists of anchors or form controls with tabindex index values in specific orders. It is mostly an accessibility standard. If you leave this out, the browser establishes its own tab index, naturally, on interactive elements in your web page. Add "tabindex=0" to include the link in the browsers natural tab order, add "tabindex=-1" to exclude it, or add "tabindex=5" to make it a specific focus in a specific order in the list.
  9. The 'alt' attribute is not supported in anchors in XHTML and rarely in HTML5. So avoid using it in anchor elements. In some browsers it can work as a placeholder for a link when non-anchors are used as hyperlinks. An example would be a click-able div with an 'href' that has some content that is still downloading. Years ago we did use this attribute on links to provide alternate content for links. But today, avoid it.
  10. ARIA Attributes on Hyperlinks: We do not add ARIA role="link" as an attribute to anchors to assist screen readers in identifying it as a hyperlink as it is self-describing. The anchor 'a' element tells most screen readers it is a hyperlink by default. Only add the link role to a non-anchor used as a link. It's ok to add a 'aria-label' here to tell screen readers what the link does, but in most cases a 'title' tooltip attribute will assist in that function.
  11. There is a rich set of "pseudo-class" CSS styles you can now use to change the color and features of links based on user interactions like hover, focus, and other states. The colors you see applied here are defaults I set for anchor elements in my Universal CSS Framework that resets all HTML elements to a common style.
  12. Styling Links with CSS: CSS can be applied to links to color their text, add underlines, rollover colors, and more. By default, you can apply lots of styles and rollover events to links using CSS. But events connected to the rollover or click events is controlled by CSS and "pseudo-classes". An unvisited or new link is underlined and most often blue by default. A visited link is underlined and purple by default, in most browsers. An active link is underlined and red on click. Most often you apply pseudo-classes to control these colors. They should be added in your style sheet in a specific order in CSS so that the various combinations of color changes cascade over previous ones as users interact with your hyperlinks. The order is: ":link", ":visited", ":hover", ":focus", ":active". If you placed ":visited" after ":hover" you could never change the ":hover" color on ":visited" links. There are newer pseudo-classes, but support in newer HTML5 browsers is spotty and inconsistent. Most of these new ones affect links but also form inputs and other elements: ":disabled", ":checked", ":required", ":valid", ":invalid", ":optional", and ":readonly". Roll over the text example above to see how I have applied these colors. Note: New "privacy" concerns in modern search engines and in HTML5 now limit the properties web authors are allowed to change on "visited" anchors. So most of these properties and styles are removed and cannot be changed by web authors. Color in text is one you can still safely change. For that reason, the browsers now controls many of the style properties applied to text links for privacy reasons. If you see limitations on how your CSS is applied to HTML5 anchors, now you know why!
  13. Styling Image Links: If you choose to make an image a link (example: <a href="..."><img src="image.png" /></a>), the most common way to do this is to wrap a link tag around an image. This is superior to adding an "href" attribute to an 'img' tag, or adding CSS background images to elements then making them links. The reason is search engines like to associate the image with the link. Also, pure image links help the blind or people that need to know some visual image carries additional information (see my 'img' section below on how best to decorate images for ARIA and screen readers). If you use backgrounds, you destroy or hide all this valuable information.
    In CSS and web pages, when using image links, some strange design bugs can occur in older browsers. But there are simple fixes for them in CSS. One weird bug that haunted developers for years after 2000 was the weird issues that would occur when you wrapped anchor tags around images to create links. Often, browsers would add a strange "blue border" around the image when wrapped by an 'a' element. We got around this by simply adding a "border:0" in our CSS style sheets for anchor images like so: "a img {border:0;}". This usually occurred in IE 1-9, so this bug hung around for a long time. Sometimes image link would "flicker" or move when rolled over. To fix this one, make sure you always set a width and height on your image, or even the anchor wrapper itself. With locked down dimensions and zero borders, the browsers can do any monkey business on image links.
  14. * Additional attributes are available with various levels of browser support. Items without wide historical browser support are not listed here nor recommended unless you are targeting a special subset of browsers or using special JavaScript API that requires it.
<abbr> abbreviation

Abbreviation

<abbr title="World Health Organization">WHO</abbr>
The WHO was founded in 1948.
My Recommendations:
  1. The 'abbr' element defines an inline abbreviation or acronym and shows a full text translation on rollover.
  2. An abbreviation is text marked with an 'abbr' tag with a title giving the full text translation. Marking abbreviations can give useful information to browsers, translation systems, and search-engines. Note that this 'abbr' tag puts a nice dotted line under the abbreviation in some browsers you can customize in CSS.
<acronym> acronym

Acronym

<acronym title="World Health Organization">WHO</acronym>
The WHO was founded in 1948.
My Recommendations:
  1. The 'acronym' or inline abbreviation element is deprecated now and was a member of old HTML4. Old IE 4-5 and Mozilla 5 were the main supporting browsers of 'acronym'. Use 'abbr' instead.
<address> address

Address

<address>
  Visit us at:<br />
  My Business, Inc.<br />
  Box 123<br />
  Some City, CA<br />
  USA
</address>
Visit us at:
My Business, Inc.
Box 123
Some City, CA
USA
My Recommendations:
  1. The 'address' element defines a piece of block-level text representing the contact information for the author of a web page or online document. But it can be used for any address display in HTML.
  2. The 'address' element is usually displayed in italics and laid out in lines with break elements added for line breaks. You can customize its look-and-feel further with additional elements inside its tag. Address is a block-level element so performs like a 'div'.
  3. Use the 'address' element to list a address online. Search engines and special parsers may read the address data directly and use it in special ways that index location, as well.
<applet> applet, Java Applet

Applet

also see <audio>, <video>, <object>, and <embed>
<applet controls="controls" code="rain.mp3" width="300" height="200">
  Your browser does not support the applet tag.
</applet>
My Recommendations:
  1. The 'applet' element was used to display a multimedia file (primarily Java Applets) in a web page. This element has been deprecated. Use the 'video', 'audio', 'object', or 'embed' elements instead.
  2. As usual, always include an 'id' and a 'title' on these click-able multimedia objects.
  3. The 'applet' element became a popular alternative to Microsoft's 'object' element for ActiveX and the 'embed' element built by Netscape. It has been around since the 1990's, so was once a very popular element used to support Java objects in web pages. The browser will interpret the media player required based on the file extension and the 'type' attribute in the 'source' element and attempt to load a player to display it. However, because Java Applets are rarely used and remain a security risk in browsers, there really is no reason to use 'applet'. Most of the "other" media once supported by 'applet' were driven by deprecated players that have been discontinued. However, you may find older websites that still use 'applet'. If you are targeting still using Java Applets in older browsers, it might be useful to still use 'applet' in special limited cases.
  4. History: Prior to 2010 and the advent of HTML5, the 'applet', 'embed', and 'object' elements were used to display a wide range of multimedia objects in HTML including: Java Applets, Adobe Flash, plug-ins, ActiveX objects (in Internet Explorer only), images, video, audio, Windows documents, and older 3rd party applications in the browser. Keep in mind that for over a decade, web browsers viewed millions of multimedia objects this way. Many of these media types are now discontinued, no longer supported, or are security risks in the browser. For those reasons and more, these multimedia elements are generally not supported in HTML5. With the newer smart phone technology that came online after 2007, having limited CPU capacity and security concerns, it was decided that most of this new media would not be supported on mobile devices. And so tags like the 'applet' and 'embed' elements quickly died, even on desktop. Legacy websites today that still contain unique custom multimedia objects like this now must be removed or replaced with alternatives, as so many of the "players" that once supported rich media like this are no longer around to play them (post-2010). Flash for example, was recently discontinued just a few years ago, but was once hugely popular as a choice for highly interactive solution in thousands of websites. (I actually used to write Adobe Flash animations and applications in old Actionscipt.) This change has not stopped video, audio, or other applications from being embedded in web pages, however. HTML5 has simply come up with alternative elements. Keep that in mind. So, if you see these old elements and are deciding to remove them or update them, use the newer HTML5 elements available ('video' and 'audio', for example).
  5. As mentioned, do NOT use the 'applet' element as it is fully deprecated now and replaced by the <audio>, <video>, <object>, and <embed> elements.
<area> area, map area

Area

see <map>
My Recommendations:
  1. The 'area' element defines an area inside an image map element. See the <map> element for a full description.
<article> article

Article

See also <header>, <nav>, <main>, <footer>, <section>, and <aside>
<article id="article1" aria-label="Article1">Article 1</article>
<article id="article2" aria-label="Article2">Article 2</article>
Header
Main
Section
Article 1
Article 2
Footer
* A typical web page structure is shown above.

My Recommendations:
  1. The 'article' element is new in HTML5 and defines an independent, self-contained piece of page content. Typically, this is a structural element and is nested inside a 'main' and 'section' element. It is used for defining a larger block-level area of content in a web page. Unlike its twin, 'section' which can contain anything, 'article' usually contains text content. In HTML5, the 'article' is part of a set of new structural page elements that define the overall layout of most HTML5 website pages designed today (<header>, <main>, and <footer>, etc.).
  2. The New HTML5 Structural Elements include: header, nav, main, footer, section, article, and aside.
  3. ARIA: The 'article' element is a top-level, "self-describing" structure recognized by most modern screen readers without additional assistance. However, in the case of 'article' it is recommended you add an optional 'aria-label' of "Article {some label}" for each one added.
  4. Structure: Use article for wrapping around large textual blocks, blog posts, or smaller independent content areas within other parts of a page. 'article' can also be a parent for one or more 'section' elements. Articles can also be nested inside each other. Because 'article' is a universal structural element of modern HTML5 pages now, you will see 'article' appear in grids, flex boxes, and other CSS design and formatting structures. Nested articles can be floated side-by-side, hidden, or shown in many different configurations. Like sections, they can have headings and other page structures that a blog post or a content 'div' might have. Typically, articles are contained with a single 'section' element. But, some designers like to use one 'article' element per page and stack multiple sections inside them. I rarely use 'article' elements unless I am designing a news website or a corporate blog. I prefer the use of the 'section' element as a replacement for 'article' as it feels more semantic and generic for the majority of web pages built today. Note: Like all the other structural HTML5 elements, placement of multiple articles inside 'main' or 'section' will add important semantic structure to your pages in HTML. Know that 'article' does NOT come with a specific style. You must add that feature using CSS.
  5. See the <main> element section for more details about this new HTML5 element.
<aside> aside

Aside

See also <header>, <nav>, <main>, <footer>, <section>, and <article>
<aside id="complementary" role="complementary" aria-label="Aside">Aside</aside>
Header
Main
Section
Footer
* A typical web page structure is shown above.
My Recommendations:
  1. The 'aside' element is new in HTML5 and defines an independent, self-contained piece of page content. Typically, this is a structural element and is nested inside a 'main' element, as well as alongside a 'section' element. It is used for defining a larger block-level area of content in a web page. In HTML5, the 'aside' is part of a set of new structural page elements that define the overall layout of most HTML5 website pages designed today (<header>, <main>, and <footer>, etc.).
  2. The New HTML5 Structural Elements include: header, nav, main, footer, section, article, and aside.
  3. ARIA: The 'aside' element is a top-level, "self-describing" structure recognized by most modern screen readers without additional assistance. However, in the case of 'aside' it is recommended you add an ARIA role of "complementary" and an optional 'aria-label' of "Aside".
  4. Structure: Use 'aside' for a small side banner, image, content, or navigational structure in your page. Because 'aside' is a universal structural element of modern HTML5 pages now, you will see 'aside' appear in grids, flex boxes, and other CSS design and formatting structures. Like sections, they can have headings and other page structures that a blog post or a content 'div' might have. Typically, 'aside' floats beside a 'section' element. I rarely use 'aside' elements unless I am designing a website with advertising or sites that need important supplemental info on the side walls. Note: Like all the other structural HTML5 elements, placement of multiple 'aside' elements inside 'main' will add important semantic structure to your pages in HTML. But know that 'aside' does NOT float to the left or right of any element naturally. You must add that feature using CSS.
  5. See the <main> element section for more details about this new HTML5 element.
<audio> audio

Audio

<figure aria-labelledby="myaudio">
  <audio id="audio1" alt="audio: Rain Sounds" controls="controls" preload="metadata" title="An Audio File of Rain Falling" aria-label="Rain Sounds">
    <source src="rain.ogg" type="audio/ogg" />
    <source src="rain.mp3" type="audio/mpeg" />
    <p><strong>Sorry, this audio file will not play. Your browser does not support the audio element or the file formats available.</strong></p>
  </audio>
  <figcaption id="myaudio">"Rain Sounds" [<a href="http://creativecommons.org/licenses/by-sa/3.0" target="_blank" rel="noreferrer nofollow noopener">CC BY-SA 3.0</a>] , via <a href="https://commons.wikimedia.org/wiki/" target="_blank" rel="noreferrer nofollow noopener">Wikimedia Commons</a></figcaption>
</figure>
"Rain Sounds" [CC BY-SA 3.0] , via Wikimedia Commons

(If your browser supports the audio element above you should see an audio control and hear a rain sound when playing.)

My Recommendations:
  1. The 'audio' element is a new HTML5 tag used to embed sound content in web pages, including music, streams, or sound files. (It replaces the old 'object', 'applet', and 'embed' elements in HTML4).
  2. The audio tag works like the <picture> element with multiple fallback child <source> tags representing alternative audio file sources inside it. The browser will pick the first source file format it can play successfully from a list, or report a text message indicating no file format or audio element support.
  3. As always give your element an 'id' for script control and a 'title' attribute to tell users what the audio control will do.
  4. The 'src' attribute in 'source' elements must point to a valid audio file or the audio controls will not play a file when pressed.
  5. The 'alt' attribute in 'audio' elements helps screen readers and the blind identify the meaning of audio elements, just like images provide. For that reason, always add the "alt" attribute.
  6. The 'width' and 'height' attributes can be set on the element, as well as in CSS. I recommend you avoid the attribute versions and set dimensions in CSS so you have more flexibility and can use 'em' text units or percentages which allow the audio to fit various dimensions. Note: The audio element is a "replaced" inline element controlled by the operating system. I recommend you give it a "display:block" CSS value so you can at least control its borders, margins, and background features.
  7. The controls="controls" attribute specifies that audio controls should be displayed. By default it generally includes play, pause, volume, time, and playtime position controls. Note: There is a "controlless" version of the audio element, but I do not recommend you play audio without giving a user controls.
  8. The 'preload' attribute specifies a hint to the browser as to when the audio file should be loaded. "auto" generally means to load the complete file as the page loads, but some browsers may ignore this feature. "none" would mean to not load the audio file as the page loads and would load the file only when the play button is clicked. "metadata" would only load the metadata for the audio file as the page loads. The default value is different for each browser. The spec advises it to be set to "metadata", so I recommend that value be set so you don't slow down the display of your web page with large audio file downloads in the background. Note: These types of files are not true streams and are likely "on-demand" download streams buffered and negotiated with the server over HTTP, unlike a true audio streaming service and audio player would negotiate over a streaming protocol like udp/rdp, etc. So, keep that in mind if your page has lots of audio files on your server!
  9. There are other 'audio' attributes you can apply, like 'loop', 'muted', 'crossorigin', and 'autoplay' you can use for more control of your audio, though I do not recommend them.
  10. There are numerous scripted methods and events you can apply to your audio element along with scripts to fully control and customize your audio player.
  11. Beneath the audio control sample above I have added some small text with more info about the audio file as well as licensing information. This is generally good practice so users understand the source of the file and have access to more textual information about its licensing. Notice I wrapped a Figure with Figcaption around the audio element, so its text description becomes its caption. This allows it to work with captions as a 'picture' or 'img' element would do.
  12. CSS styling of the audio control is difficult if not impossible, so realize there is limited support for designing audio controls.
  13. Many modern mobile phone browsers as well as Internet Explorer 8 and earlier browsers on the desktop do not support the 'audio' element! These older agents prefer the 'embed' (non-IE) or 'object'(IE only) elements, instead. So, keep in mind the limited support many modern browsers may have for the audio control and its many features.
  14. I recommend use of the new HTML5 'audio' element, but with the understanding many older browsers will not support it. Be prepared to offer 'embed' and 'object' alternatives for wider support in older agents. (see my "best practices" section for how to do this). If you need more universal support for audio controls across devices and browsers consider building a JavaScript-based audio control.
<b> bold, bolder

Bold

This is some <b>bold</b> text.
This is some bold text.
My Recommendations:
  1. The 'b' element defines a piece of "bold" text.
  2. In my style sheets I always re-define the 'b' element as "bolder", not "bold", in font-weight value as you might have bold text that now must stand out and be bolder from the other text. So its a relative value.
  3. Do not use the 'b' element, but use 'strong' instead! Because 'b' is a purely visual element, use of its semantically important brother, <strong>, is recommended instead of 'b'. You can also use CSS styling and 'font-weight:bolder' on spans of text segments if you just want a design change, but its not as search engine friendly as 'strong'.
<base> base url

Base URL

<base href="/" target="_self" />
My Recommendations:
  1. The 'base' element specifies the "base URL" to use for all relative URL's or paths in your web page. The 'base' element always appears in the 'head' of your HTML page. It has been a part of the early HTML recommendations, though rarely used.
  2. Why Use the 'base' Element? The 'base' element resides in the <head> section of your HTML page and has no design function. It mainly affects links inside your web page but affects any element with a relative web path, as well. It tells the browser what the starting web root is under your website domain for all such "relative" URL's. If your HTML page has no 'base' element (which most do not), the browser defaults to the "base" URL or website domain itself. That means by default, all relative URL's resolve relative to the web root, or "https://yourwebsite.com/". You could set it to "/" if you have a site that might include an unknown number of domains pointing to the same website and web root. If you use 'base', also know it must come after your meta tags in the 'head' of your web page, but BEFORE all 'link', 'style', 'script', or other elements that reference relative URL paths.
    Most of the time you do not need the 'base' element, as relative URL's in your website (like paths to images, video, CSS files, or links) always use the path starting from the web domain and "web root" and resolve paths to files ok without any help. The browser will fill in the rest, which is usually done by adding the website's fully qualified domain plus "/" in the file path. Example: A relative URL in a web page to an internal page in a subfolder under it, like "myfolder/mypage.html", would work ok as is without any help. If that same page was off the web root it would also work the same as "/myfolder/mypage.html" (absolute URL) or "http://mywebsite.com/myfolder/mypage.html" (fully-qualified URL). The browser and server resolve it just fine. You could also let the server dynamically send you the right folder path with the image, link, etc. Most servers do that quite easily. Finally, you could simply ignore the domain part of the URL and use pure relative paths, like this "../myfolder/mypage.html", which says that a page in a folder next to "mypage" goes up to its parent folder then down into "myfolder" to find the page, ignoring the domain path. Browsers all do this naturally and have for over 20 years. In all of these cases above, you do not need the 'base' element.

    Where 'base' elements might help is specialized cases where you have multiple web applications housed under separate folders, but using the same website and domain, like so:

    • "http://mywebsite.com/application1" - Your "base" URL for pages under this path would become "/application1/".
    • "http://mywebsite.com/application2" - Your "base" URL for pages under this path would become "/application2/".

    Each of the "applications" above could be a folder path or a "virtual" path inside a common website but which need to use separate applications and application paths underneath "http://mywebsite.com/". By setting the base path to "/application1/" for all HTML pages inside the first path, you can then let all your relative URL's and links continue to use the same paths they always use, but let the browser inject the new application "base" path or root path into them. Example: The relative URL "myfolder/mypage.html" with the new 'base' path above added to the page would now resolve to "/application1/myfolder/mypage.html" (same as "http://mywebsite.com/application1/myfolder/mypage.html"). The idea here is to allow complex web applications with multiple subsections continue to use relative paths that do not change, but where only the top application path changes. Otherwise, you would have to include the new application path in every single URL in every application and page. It saves a developer the hassle of keeping some URL's inside different applications. However, in these rare cases, we still never needed "base", as we simply controlled paths on the server. It is MUCH easier to do this server side. For example, if every "user" or "product" or "administrator" needed their own path or web page based on an "id" in the path, we simply injected that path dynamically on the server in every web page and element for thousands of items or users like so: "/{server generated path goes here}/myfolder/mypage.html". That is much easier to do using server-side logic and more manageable that a hard-coded "base" value. So 'base' is again redundant.
    One "weird" use for 'base' URL's has been recent JavaScript API's like Google's Angular. These developers felt they needed this antiquated 'base' URL system to help their own pathing systems resolve. That is because they use an artificial "routing" system in JavaScript that builds off static URL's in the 'base' element, not the default web root of most website. Instead of building static folders to support testing or other configurations, or managing those paths in variables inside JavaScript, they like to use the artificial "base" paths that have no basis in real paths like most websites use. They also could have processed custom URL's in memory like a server does for paths, but rejected that idea, too, apparently. They also want to segregate their single page application this way from 3rd party applications that might conflict with theirs, or have the power to stick their pathing system into others without knowing the conflicts involved. They rely heavily on the static "base URL trick", which is yet another dependency. They also build a product that is heavily dependent on an internal, open source, UNIX-based "relative" pathing system using a "." syntax that is not web-friendly and does not always fit with how relative web paths work or resolve in websites. By relying on artificial paths and the 'base' path like this means they must rely on a static HTML path dependency that yet must fit into their own dynamic one. It is just bad design!
  3. 'base' Element Attributes: The only two attributes needed for 'base' are the "href" or URL static path and/or a "target" window. By default, you should set "href" set to "/" then customize it from there. his at least allows your paths to avoid static URL domain paths and so remain domain agnostic. If you do use 'base', make sure all your images, CSS files, JavaScript files, links, and other relative paths all resolve to that one web root path! The "target" attribute in 'base' is rarely used and is by default "_self", or posts the page into the existing one. You can use "_blank" to force all links with relative URL's to pop up into a new window or tab. The other values for "target" were mainly for frames, which are no longer used.
  4. Do Not Use the 'base' Element!: I cannot recommend use of this element as it adds too many dependencies to what should be a simple relative path system that works fine as is by default in all browsers and web server systems. Using the natural URL system means you have the freedom to use absolute paths from your web root or relative paths from within any folder in your website to any other file independent of the root. No extra work needed. If you find you do use multiple applications, try using the server to inject those application root paths dynamically (as described above). Most virtual web applications on web server under a given domain do this pathing for you, naturally. Otherwise, if you feel you need to use multiple applications in your website, try creating a subdomain for each major application under your domain instead of manipulating paths using 'base'. Example: "http://mysubdomain.mywebsite.com/". There are so many better solutions to solving pathing problems than using the 'base' element.
<basefont> basefont

Basefont

<basefont color="#000000" face="Verdana" size="+2" />
My Recommendations:
  1. The 'basefont' element was used to specify font styles for all elements under the 'body' element in a web page. It would be placed in the <head> section of a web page. 'basefont' has been around since the 1990's and early days of HTML and was still a part of HTML4. However, this element has been deprecated in HTML5, as it was a design element only.
  2. Do not use the 'basefont' element! Instead, use CSS style sheets to set default font styles on the 'body' element of your web pages. Those font styles then cascade down from 'body' to all other elements, just like 'basefont' used to do. Font styles are thus inherited by all your inline and text style inheriting elements.
<bdi> bidirectional isolate

Bidirectional Isolate

The user's score - <bdi>إيان</bdi> : 46
The user's score - إيان : 46
My Recommendations:
  1. The 'bdi' element isolates a part of "directional text" (right-to-left or left-to-right) that might be formatted in a different direction from other text outside it. Unlike its HTML4 cousin <bdo>, this element is new in HTML5, but sadly has no support in any Internet Explorer or in a few others. So, I do not recommend its use. Use <bdo> instead.
  2. If you did not wrap the Arabic above, when you start typing certain text after it, the text might be flipped to the opposite side of the text. If such text is injected into an element without the 'bdi' element, the browser's algorithm to set direction could flip text around the Arabic section above.
  3. The sibling element 'bdo' works the same but reverses the text direction.
  4. Avoid using 'bdi', as it has no support in IE 1-11. Use its cousin, <bdo> instead.
<bdo> bidirectional override

Bidirectional Override Text

Left-to-right - One type of text: <bdo dir="ltr">إيان</bdo>
Left-to-right - One type of text: <bdo dir="ltr">John Smith</bdo>

Right-to-left - One type of text: <bdo dir="rtl">إيان</bdo>
Right-to-left - One type of text: <bdo dir="rtl">John Smith</bdo>

Left-to-right - Mixed types of text: <bdo dir="ltr">John Smith and إيان</bdo>
Right-to-left - Mixed types of text: <bdo dir="rtl">John Smith and إيان</bdo>

Left-to-right - One type of text: إيان
Left-to-right - One type of text: John Smith

Right-to-left - One type of text: إيان
Right-to-left - One type of text: John Smith

Left-to-right - Mixed types of text: John Smith and إيان
Right-to-left - Mixed types of text: John Smith and إيان
My Recommendations:
  1. The 'bdo' element isolates a part of "directional text" (right-to-left or left-to-right) that might be formatted in a different direction from other text outside it and reverses its direction. This element has been in older HTML recommendations for years, so is supported widely across old and new browsers (unlike its cousin, <bdi>).
  2. The 'dir' attribute sets the new direction of the text. If 'dir=rtl', English text would change direction. Arabic or Hebrew text would not change as they are right-to-left in direction by default.
  3. The CSS property 'unicode-bidi' determines how text and Unicode languages change direction. Review those settings in more detail to combine mixed Unicode languages and text in this element and others.
  4. The sibling element 'bdi' works the same as 'bdo' but isolates the text direction without changing its current text direction.
  5. WARNING: Do not change a native Unicode language's native text direction unless you have a specific purpose in doing so.
<big> big, bigger

Big

This is some <big>big</big> text.
This is some big text.
My Recommendations:
  1. The 'big' element was used to show larger text in an inline block of text.
  2. Do not use the 'big' element as it is deprecated now and was a member of old HTML4. Use CSS and 'font-size:larger' on spans of text instead, like this (you would move the inline style below to a CSS class):

    This is some <span style="font-size:larger;">larger</span> text.

    This is some larger text.
<bgsound> background sound

Background Sound

<bgsound source="birdsounds.wav" loop="true" volume="20" />

My Recommendations:
  1. The 'bgsound' element is deprecated now but was a non-standard HTML tag that was used to play a small audio file in the background of a web page (often a .wav or .mp3 audio file). This element was a non-standard element, proprietary to browsers like old Internet Explorer v.5, and no longer supported in HTML5 browsers. At one time it was fun to use in older websites (pre-2001). But over time, it was not good useability to play music in web pages in which a user could not control the audio playback or volume. Besides, it is unlikely to work in modern browsers today as it has never been a part of the evolving HTML5 standards. Do not use <bgsound>. If you need sound in your website, use the <audio> element instead.
<blink> blink

Blink

<blink style="color:green;">This is some text that should flash on and off, if supported</blink>
This is some text that should flash on and off, if supported
My Recommendations:
  1. The 'blink' element is deprecated now and was a non-standard member of old HTML4. 'blink' used to create a section of inline text which flashed, on and off, in the browser.
<blockquote> blockquote, long quotation

Blockquote

I have decided to leave a quote below:
<blockquote cite="https://www.fi.edu/benjamin-franklin/famous-quotes">Well done is better than well said.<br />— Benjamin Franklin</blockquote>

I have decided to leave a quote below:
Well done is better than well said.
— Benjamin Franklin
My Recommendations:
  1. The 'blockquote' element defines a piece of block-level text representing a piece of quoted text from another source. It is usually indented as a block-level element. Note that it does not add quotations like 'q' does.
  2. The 'cite' attribute is used to define an online source for the quoted text and its web page.
  3. Always use 'blockquote' for larger separate blocks of text and 'q' for smaller inline quoted text.
<body> body

Body

see <html>
My Recommendations:
  1. The 'body' element defines the main content area of a web page. See the <html> element for a full description.
<bq> bq, block quotes

Block Quotes

<bq>
  <p>Quoted text goes here</p>
  <credit>Credit source text goes here</credit>
</bq>

Quoted text goes here

Credit source text goes here
My Recommendations:
  1. The 'bq' element is a deprecated tag from old HTML3 once supported in Internet Explorer 2 (1990s). It was used to display an early form of an extended block quote, which included a quotation text block and a 'credit' element for a quote source. This element was discontinued following adoption of <q>, <blockquote>, and <cite> elements. It is not part of HTML5. Do not use the 'bq' element.
<br> break, line-break

Break

This is an example of a line-break...<br />
...I am now on a new line!

This is an example of a line-break...
...I am now on a new line!
My Recommendations:
  1. The 'br' element defines a short line-break between two piece of content. The break element can be used to break inline or block-level elements, even add extra lines as space between two items.
  2. The right way to type a 'br' element is <br /> which has a space then forward slash to end the element correctly. This version is XML-compliant and ends the tag correctly. Do NOT use these forms: <br>, <br/> or <br></br>. The form, <br />, is 100% HTML5/XML/XHTML/XHTML5 compatible, while the other forms are not.
<button> button

Button

see <form> for more details using <button> in forms

A Button can "submit" Form Data

<form id="buttonform1" name="buttonform1" action="#" method="get" aria-label="Button Submit Form" title="Button Submit Form" autocomplete="off" autocapitalize="off" spellcheck="false">
<p>
  <label for="buttonexample_username" title="Username">&nbsp;<abbr title="required" aria-label="required">*</abbr>&nbsp;Username</label>
  <input type="text" id="buttonexample_username" name="buttonexample_username" value="" size="20" maxlength="20" title="Username" tabindex="0" autocomplete="username" autocapitalize="off" autocorrect="off" spellcheck="false" required="required" aria-required="true" aria-label="Username" />
</p>
<p>
  <label for="buttonexample_password" title="Password">&nbsp;<abbr title="required" aria-label="required">*</abbr>&nbsp;Password</label>
  <input type="password" id="buttonexample_password" name="buttonexample_password" value="" size="20" maxlength="20" title="Password" tabindex="0" autocomplete="new-password" autocapitalize="off" autocorrect="off" spellcheck="false" required="required" aria-required="true" aria-label="Password" />
</p>
  <button id="buttonexample_button1" name="buttonexample_button1" type="submit" value="submit" form="buttonform1" title="Submit" tabindex="0" aria-label="Submit">Submit</button>
</form>


A Button can send Name-Value Pairs Using the Same "name" Attribute

<form id="buttonform2" name="buttonform2" action="#" method="get">
  <button id="button2a" name="fruit" type="submit" value="apple" form="buttonform2" aria-label="Apple Button" title="Apple Button" tabindex="0" style="min-width:10em;">Apple</button><br />
  <button id="button2b" name="fruit" type="submit" value="pear" form="buttonform2" aria-label="Pear Button" title="Pear Button" tabindex="0" style="min-width:10em;">Pear</button>
</form>


A Button can also be a "Reset" Type, a Plain "Button" Type (no form submission), or "Disabled"

<form id="buttonform3" name="buttonform3" action="#" method="get">
<p>
  <label for="buttonname3" title="My Form Field">My Form Field</label>
  <input type="text" id="name3" name="buttonname3" value="" size="20" maxlength="20" title="name" tabindex="0" />
</p>
  <button id="button3a" name="button3a" type="reset" value="reset" form="buttonform3" title="Reset" tabindex="0" aria-label="Reset" style="min-width:10em;">Reset</button><br />
  <button id="button3b" name="button3b" type="button" value="plainbutton" form="buttonform3" title="Plain Button" tabindex="0" aria-label="Plain Button" style="min-width:10em;">A Plain Button</button><br />
  <button id="button3c" name="button3c" type="button" value="disabledbutton" form="buttonform3" title="Disabled Button" tabindex="-1" aria-label="Disabled Button" disabled="disabled" aria-disabled="true" style="min-width:10em;">A Disabled Button</button>
</form>




My Recommendations:
  1. The 'button' element defines a click-able button in the web page. The button element can be used to submit form data, reset form data, or be a plain, click-able button that does nothing until you attach a custom scripted event to it. The three types of buttons using the 'type' attribute are: "submit", "reset", and "button".
  2. The 'button' element by default works as a "submit" button in a form. If you leave off the "type" attribute, it remains a "submit" type by default. So, always explicitly set its type to avoid problems. When pressed it will post all of the form field's data as "name:value" pairs back to a server for processing, as well as the "name:value" pair of the button. This is important so you know "who" or "what" submitted your data! 'button' as "submit" types work just like an 'input' submit button "type". Data is posted to the server in a GET URL query string by default, or via a POST HTTP Host Header if the button or parent form have applied a POST type of form 'method'. The "reset" button type clears all form fields in the form associated with the button. The plain "button" type button can be used for processing many types of pressed button events using JavaScript methods (like "onClick="). But the "button" type button does nothing by default. Its just an empty button. It will not submit form data to the server or process any page events until you add JavaScript events to it.
  3. The 'type' attribute on buttons decides what type of button it is. As mentioned, the three types are "submit", "reset", and "button". If the 'type' is left off, it defaults to the "submit" button type and on click will submit all form field data. So be careful and always explicitly define a 'type' attribute on your button.
  4. The button 'id' is optional and must have a unique value. It is helpful when accessing and manipulating a unique button in your web page using JavaScript. I often match change both 'id' and 'name' attributes to use the same matching values on all my buttons so I can keep track of which button was clicked using a single identifiable button in both my client-side scripts and on the web server (see 'name' below). As a best practice ALWAYS use both 'id' and 'name' attributes just in case you need them.
  5. As mentioned above, the 'name' attribute is as important as the 'id' on buttons and is part of the "name-value" set for the "submit" button that is sent to the server on click. It helps you know what button was pressed when processing server-side data. If you use cryptic names, other developers do not know what the button does and have to dig around for it. Use simple names like "loginbutton" or something like that for the button name. It should also always be used with a unique name, like the 'id', unless part of a collection of buttons with the same shared name, with each button having unique values. The 'name' attribute is often used to associate the button with a form field of data it submits or identify which button was pressed among many fieldsets on more complex forms. The button 'name' attribute value along with its 'value' attribute value will be submitted to the server as a "name-value" pair along with all other name-value pairs of input controls within a parent form element when the button 'type' is "submit". Note: Some older browsers send just the text inside the button for the value (IE8, for example), so beware! As mentioned, it is critical if you have complex multi-form element pages with lots of buttons where you need to identify on the server which form data was submitted. I often match the 'id' and 'name' with the 'name' value so I can keep track of a single identifiable button in both my client-side scripts and on the web server. Also, in form fields the 'name' attribute is often parsed first as it is used when building name-value form field key-value pair data system sent to the server on submit. So, be sure to give each 'name' a unique value, match the unique name to the 'id' element, and be sure to put both first in the element!
  6. Always wrap a <form> element around your buttons and form fields! This tells the browser your button is associated with that form and will only submit its child input elements to the server if you have multiple forms of input fields to submit in a web page. You can still place the 'button' element outside a form if you give it a 'form' attribute to associate it with a specific form. In that case, it will still submit all input fields inside that specific form when pressed. However, I do not recommend you move any form controls or buttons outside of a parent form, as some older browsers may fail to submit data.
  7. Along with the 'form' element wrapper, always add the 'form' attribute to buttons with the 'name' attribute's value of the parent 'form' element, as mentioned above (example form="myform1"). This associates your button with a specific form of inputs they will submit to the server. Buttons without this 'form' attribute will not know which form to submit, and if you have several in a web page, could submit ALL forms and all form data to the server by mistake.
  8. As mentioned, the "button" type of button does not do anything. It will NOT submit input form fields to the server. As such use it for custom JavaScript events or triggers in your web page. The ideas of how to use "button" type 'buttons' is endless!
  9. formtarget, formaction, formmethod, formnovalidate, and formenctype are only needed if you plan to override the attributes on the parent 'form' element. However, these only work for the default or "submit" button types (see <input> "submit type element, as well). 'formtarget' specifies a keyword that indicates where to display the response that is received after submitting the form, like a new window. 'formaction' is used to add a server URL, and tells the browser where to send the form data. It is an override of the parent form's "action" attribute value, which is the same URL of the current web page if missing on the form. If different buttons need to submit data to different locations on the server for processing use this attribute. 'formmethod' is used to set either GET or POST method types for all form fields it submits. GET is the default. 'formnovalidate' forces no validation on all form field inputs on submit, again overriding the 'form' elements settings for the inputs. 'formenctype' applies only when you are using the POST method, submitting files using the 'input' element "file" type, and wanting to override the default form settings. Always use the XML-friendly version of these attributes. Example: "formnovalidate=formnovalidate". In most cases you do not need to set these attributes unless you have multiple submit buttons and need to override the parent form values for each one using buttons inside the form.
  10. As with all my interactive HTML elements, I encourage you to ALWAYS add a 'title' attribute to your buttons and an ARIA label. You do not need ARIA roles on buttons as they are self-describing. Adding titles and label attributes on buttons allows a user to know its function, its properties, and the type of data it submits. If its a button that is not a "submit" type, its important to have a title telling a user what it does before they press it. Otherwise, they have no idea beyond vague visual queues on the web page.
  11. Adding an accesskey attribute to a button with a letter representing the keyboard text to trigger it is optional and for accessibility. 'accesskey' values often do not work, so a better solution is to add "tabindex=0" to force the button into indexed list of tabbed form field items. Often buttons are added by the browser by default. A "tabindex=0" value forces it into the tab list then allows the browser to sort all "0" tabbed items naturally. Most browsers now support ENTER/RETURN key submissions. This means that when a user presses ENTER on their keyboard, the browser will locate the FIRST "submit" button type in the web page and press it, submitting the form data associated with it and its parent form wit all its associated form fields.
  12. How to Enable Enter/Return Key Submission: Often by default in modern browsers pressing the "RETURN" or "ENTER" key on a keyboard presses the form's "submit" button on a web page and submits the data. It is a fast way to have users submit data quickly. This natural "ENTER" keyboard button submission feature has been a feature of web browsers for decades! Many kids today design elaborate JavaScript rules to achieve this, but it's not necessary as its built into all form fields if you follow a few simple rules. To make sure this feature works, an input field or button inside the 'form' element must have focus, be set with the "autofocus" attribute, or be the first button of many listed in the form and be a part of the tabindex list created by the browser. In most cases all this is true and "ENTER" keypresses work fine. To verify this, the user should be able to "tab" into the form and be the first button reaching focus after all prior inputs have been tabbed through. You can also force them there by adding "autofocus=autofocus" but only if the web page does NOT require previous input of data first.
    Finally, as a last resort, you can add JavaScript to capture keyboard events. But using this simple HTML trick above that is not needed.
    WARNING: In rare cases where a web page has heavy user access, this ENTER key submission feature makes using your submission button faster and easier, but allow users to press "ENTER" before the page and its data is fulling loaded! If your web page or form field page isn't loaded by the time they press "enter", bad data or no data can be sent to the server (this has happened to me with time clock stamp web pages where impatient users press the key without waiting for the page to load....causing missing time stamp data on the server). In those rare cases, be careful and add "required" to a form field to make sure its manually filled out prior to submission, or consider capturing the "ENTER" key press event with scripts until the web page is fully loaded! That is one rare case where JavaScript does help.
  13. As mentioned above, add "tabindex=0" to all your buttons to make sure they are included in the browser's default tabindex listing. I recommend you always add "tabindex=0" to a 'button' element as it adds it to the global tab index list created by the browser for the web page. Add "tabindex=-1" to "disabled" buttons so users do not tab into them (Note: You can remove buttons and all other non-interactive elements in the page using "tabindex=-1"). You can also set specific tabindex values and create your own custom tab order. This is frequently done in form fields a user fills out in a specific order. If you have a specific need to include your button in a custom order of form fields and other buttons, again, add a specific unique tab order number to control what users fill out prior to submission. Setting "tabindex=1", for example, would start a user at a specific control and works like 'autofocus', for example. It controls where a user goes to in a page, initially. But realize, the "ENTER" key will still trigger the submission. Adding "required" or "validation" attributes and scripts to stop submission until fields have valid data is also important.
  14. You can also add "autofocus=autofocus" to enable a users browser to focus and select the button control after the page loads. The 'autofocus" attribute takes the user immediately to a specific item regardless of tabindex.
  15. "disabled=disabled" turns off the ability for a button to submit data or function. All button types would be affected. Note: In CSS I generally gray out disabled buttons and change the cursor rollover type back to the default (non-pointer or hand type).
  16. Can I Create Image Buttons? Yes! Because 'button' types unlike 'input' buttons can have HTML and image elements between their tags, you can actually style buttons to hold all kinds of images. You can also add a CSS image background to buttons to simulate an image button.
  17. ARIA: Notice in the examples above I have added ARIA and 'aria-label' attributes. In most cases screen readers will identify your buttons without assistance so the ARIA 'role' attribute is optional. Many screen readers will know its a generic button, but not know what it does or represents. For 'button' elements without a "type" added, I recommend you do add ARIA "role=button" to tell screen readers it is an active "submit" button. But, the 'aria-label' is also important in helping identify the element's purpose and should always be used, regardless.
  18. Styling a Button with CSS: Styling the 'button' element, cross-browser, is incredibly challenging in terms of designing buttons that look exactly the same between browsers, old and new. This is because buttons are "replaced" elements whose design and features are often controlled by the computer's OS. In addition, most browsers "default" to a specific button design that is often raised or gray in color, matching say a Windows or Mac dialog button. Below is CSS style for a simple, white, raised button style that works well in many types of browsers and which has been thoroughly tested. Just paste this CSS style code below in your web page's style sheet and watch all your button elements magically change design!


  19. Should I use 'button' or 'input' type submit buttons? Every form field should have a "submit" type of input or button, whether its a button of type "submit" or an input of type "submit". This is a general rule to follow when deciding whether to add the 'button' element to your page or not. Because many legacy browsers, like IE, are not consistent in how 'button' types submit "name-value" pairs versus the text inside, some people avoid 'button' elements and use 'input' types for form submission. Use buttons if you need to pass "name-value" pairs, otherwise use 'input' buttons. 'input' "submit" types seem to be more common. If you do use the 'button' element, I would make sure all my buttons have the above attribute values in case an older browser is targeted.
  20. Any Browser Issues? There are no really huge cross-browser issues, other that the minor data-submission Internet Explorer issues described above. Those are minor. 'button' has been around as an HTML element since the birth of most browsers, and has really not changed in HTML5, so is totally safe to use.
<caption> caption, table caption

Caption

<table style="border: 1px solid black;border-collapse: collapse;border-spacing: 0px;padding: 10px;vertical-align: top;">
  <caption style="color:blue;font-weight:bolder;">Your Table Caption Appears Here</caption>
  <thead>
    <tr>
      <th>header cell title</th>
      <th>header cell title</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>body cell text here...</td>
      <td>body cell text here...</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>footer cell text here...</td>
      <td>footer cell text here...</td>
    </tr>
  </tfoot>
</table>

Your Table Caption Appears Here
header cell title header cell title
body cell text here... body cell text here...
footer cell text here... footer cell text here...
My Recommendations:
  1. The 'caption' element is used inside a table only, and appears as a "title" at the top of your table grid. By default, a table caption will be center-aligned above a table. The purpose of the caption is to semantically label your tables and tell users and screen readers the subject or meaning of the tabular data.
  2. The 'caption-side' CSS style property is used to control where the caption should appear on the table and can be "top" (default) or "bottom". Note: IE 7 and older do not support this style property.
<center> center

Center

<center>My Text Is Centered</center>
My Text Is Centered
My Recommendations:
  1. The 'center' element was an old way to center text in HTML4 (pre-2001) but is deprecated now. It still may work in newer browsers, but DO NOT USE IT! Use CSS instead to control centering of text by placing the style on the block-level element holding the text. Example:

    <div style="text-align:center;width:100%;">Center My Text Using CSS</div>

    My Text is Centered Using CSS
<canvas> canvas

Canvas

also see <svg>
<canvas id="canvas1" style="background-color:#ccc;border:1px solid #666;" width="100" height="100">
Sorry, your browser does not support the new HTML5 canvas object.
</canvas>
<script type="text/javascript">
  var myCanvas = document.getElementById('canvas1');
  var myContext = myCanvas.getContext('2d');
  // draw colored boxes
  myContext.fillStyle = 'green';
  myContext.fillRect(10, 10, 20, 20);// x-y coordinates, x-y art dimensions
  myContext.fillStyle = 'red';
  myContext.fillRect(70, 10, 20, 20);
  myContext.fillStyle = 'blue';
  myContext.fillRect(10, 70, 20, 20);
  myContext.fillStyle = 'yellow';
  myContext.fillRect(70, 70, 20, 20);
  // draw a colored circle
  myContext.beginPath();
  myContext.globalAlpha = 0.6;// allows the circle to be semi-transparent
  myContext.arc(50, 50, 40, 0, 2 * Math.PI);// x-y coordinates, radius, start angle , end angle
  myContext.fillStyle = '#fff';
  myContext.fill();
  myContext.strokeStyle = '#aaa';
  myContext.stroke();
</script>
Sorry, your browser does not support the new HTML5 canvas object.

(The JavaScript used above in rendering this image is from the standard "Canvas Scripting API")

My Recommendations:
  1. The 'canvas' element is new to HTML5 and allows for dynamic, scriptable rendering of 2D shapes and bitmap images. The 'canvas' element has no drawing abilities of its own and is only a container for graphics (requires JavaScript using either the Canvas Scripting API or the WebGL API).
  2. The 'width' and 'height' attributes control the basic canvas element dimensions as well as the drawing surface. You can use CSS to control the element's size but NOT its drawing surface. Using the canvas attributes, you control both. So my recommendation is to use the 'width' and 'height' canvas attributes. Note: The default dimensions of the element and drawing surface is 300 pixels wide by 150 pixels high.
  3. SVG uses vectors to draw art in the browser window, while canvas uses rasters (bitmaps). This means that once a canvas is drawn it is forgotten by the graphics card and cannot be re-rendered, unlike SVG which has vectors that can change and be regenerated by the browser. Once a canvas is drawn and the bitmap is rendered, if it changes, it must be redrawn again with a new graphics object instance. It is not as efficient. So canvas is not recommended for dynamic screen rendering of artwork in HTML5.
  4. WARNING: The canvas object is heavily dependent on scripting, so is not a fully independent HTML feature. If scripting is turned off or unavailable in the user agent, the element is not rendered! Note: Internet Explorer 8 and older do not support the 'canvas' element. In addition, WebGL for high performance canvas rendering is NOT supported in IE 10 or below, Chrome 8 and below, and many other older user agents. There is also limited mobile browser support. For these reasons and more, use caution when supporting canvas imagery in the browser.
<cite> citation

Citation

<p>The <cite>Pieta</cite> is my favorite work by Michelangelo.</p>

The Pieta is my favorite work by Michelangelo.

My Recommendations:
  1. The 'cite' element defines an inline citation or title of a creative work, book, etc. It is not for citing an author's name, just their work or its title. 'cite' has been around since early HTML in the 1990's and fully supported.
  2. Cited text is usually in italics.
<code> code, computer code

Code

<code>
  &lt;p&gt;Here is my sample paragraph using HTML with the 'code' element&lt;/p&gt;
</code>
<p>Here is my sample paragraph using HTML with the 'code' element</p>
My Recommendations:
  1. The 'code' element defines an inline piece of user input text or computer code. It is commonly used with the 'pre' element, to wrap around HTML, CSS, and JavaScript code that is shared online by developers. This element is similar to <var>, <kbd>, and <samp> in that 'code' formats text to represent abstract computer programs, keys, equations, or ideas.
  2. Facts about the 'code' Element: 'code' text is usually in a monospace font by default to differentiate its purpose to the viewer. Also, text spacing and HTML formatting is NOT preserved when using the 'code' element. And all sample HTML must be escaped in order to display markup examples inside the 'code' element. If you do not escape your HTML it will be rendered in the browser instead of showing the markup code. In the example above, the HTML angle brackets (chevrons) are now escaped with special "ampersand-prefixed" escape characters ("<" brackets in HTML replaced with code, like "&lt;") to show you how that is done.
<col> column

Column

see <colgroup> and <table>

<table id="coltable1">
  <caption>My Table 'col' Example</caption>
  <colgroup>
    <col span="2" style="background-color: lightblue;" />
    <col style="background-color: lightyellow;" />
  </colgroup>
  <thead>
    <tr>
      <th style="width:auto;">header 1</th>
      <th style="width:auto;">header 2</th>
      <th style="width:auto;">header 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>body 1</td>
      <td>body 2</td>
      <td>body 3</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>footer 1</td>
      <td>footer 2</td>
      <td>footer 3</td>
    </tr>
  </tfoot>
</table>

Below, you can see that this element is only used for grouping columns for styling purposes, when CSS can do this much better without this element but using classes.

My Table 'col' Example
header 1 header 2 header 3
body 1 body 2 body 3
footer 1 footer 2 footer 3
My Recommendations:
  1. The 'col' element defines groups of columns within a table and is a child of a 'colgroup' parent element. It has no display or meaning beyond its use in tables in defining groups of columns. The 'col' element typically controls how CSS classes and styles will affect a span of columns throughout the table and is helpful if you need to design CSS styles on specific groups of columns. It is also used to help assistive devices understand how columns of meaningful data are grouped in tables.
  2. The 'span' attribute on each 'col' element determines how many columns in a table horizontally the grouping will hold and the group of columns the CSS styles will affect.
  3. CSS Support: CSS and pseudo-classes (example: td:nth-child(3){...}) on table cells can be used more effectively in setting styles than 'col' and 'colgroup' elements.
  4. Non-Browser Support: 'col' was never supported by the old Netscape 4 Series browsers between 1999-2001 when the browser wars were going on with Internet Explorer 4 and 5. So, by default 'col' was rarely used by most developers then, which continues till today.
  5. Column grouping, meaning, and styling is usually inferred by the table design itself, so 'col' is usually not needed. Example: Using well-named header cells can define what columns mean, and CSS can control designs on multiple columns now. Because CSS can be used to style any type of column grouping, use of 'colgroup' and 'col' is redundant, unless it is needed in more complex tables to confer some special column group meaning to screen readers or other assistive devices. So, 'colgroup' and 'col' is rarely needed. For these reasons, I rarely use 'col' and 'colgroup' elements. But if you have a complex table with lots of subtle data and are concerned about accessibility, these elements may have additional value. (See 'table' element recommendations for adding additional table cell and row designs.)
<colgroup> column group

Column Group

see <col> and <table>

<table id="coltable2">
  <caption>My Table 'col' Example</caption>
  <colgroup>
    <col span="2" style="background-color: lightblue;" />
    <col style="background-color: lightyellow;" />
  </colgroup>
  <thead>
    <tr>
      <th style="width:auto;">header 1</th>
      <th style="width:auto;">header 2</th>
      <th style="width:auto;">header 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>body 1</td>
      <td>body 2</td>
      <td>body 3</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>footer 1</td>
      <td>footer 2</td>
      <td>footer 3</td>
    </tr>
  </tfoot>
</table>

Below, you can see that this element is only used for grouping columns for styling purposes, when CSS can do this much better without this element but using classes.

My Table 'col' Example
header 1 header 2 header 3
body 1 body 2 body 3
footer 1 footer 2 footer 3
My Recommendations:
  1. The 'colgroup' element specifies a group of one or more columns and is a child of a 'table' parent element. It has no display or meaning beyond its use in tables. The 'colgroup' element wraps around one or more 'col' elements which define groups of table columns. See 'col'.
  2. If there are no child 'col' elements inside a 'colgroup' tag, then it may have a 'span' attribute with a value equal to the total number of columns in the table (example, <colgroup span="4" />). But this column grouping is inferred by the table headers and cells, so is redundant and rarely used.
  3. Note: The 'colgroup' element should not be confused with the 'colspan' attribute on 'td' cells which controls how many cells a single cell should stretch across.
  4. Column grouping, meaning, and styling is usually inferred by the table design itself, so 'col' is usually not needed. Example: Using well-named header cells can define what columns mean, and CSS can control designs on multiple columns now. Because CSS can be used to style any type of column grouping, use of 'colgroup' and 'col' is redundant, unless it is needed in more complex tables to confer some special column group meaning to screen readers or other assistive devices. So, 'colgroup' and 'col' is rarely needed. For these reasons, I rarely use 'col' and 'colgroup' elements. But if you have a complex table with lots of subtle data and are concerned about accessibility, these elements may have additional value. (See 'table' element recommendations for adding additional table cell and row designs.)
<credit> credit

Credit

<bq>
  <p>Quoted text goes here</p>
  <credit>Credit source text goes here</credit>
</bq>

Quoted text goes here

Credit source text goes here
My Recommendations:
  1. The 'credit' element is a deprecated tag from old HTML3 once supported in Internet Explorer 2 (1990s). It was used to display credit for a quote of text. This element was discontinued following adoption of <q>, <blockquote>, and <cite> elements. It is not part of HTML5. Do not use the 'credit' element.
<data> data

Data

<h4>Products List</h4>
<ol>
  <li>This is <data value="7345">Product #1</data></li>
  <li>This is <data value="1847">Product #2</data></li>
  <li>This is <data value="3890">Product #3</data></li>
</ol>

Products List

  1. This is Product #1
  2. This is Product #2
  3. This is Product #3
My Recommendations:
  1. The 'data' element links a piece of text or content with a value attribute inside the tag that is machine-readable. This element is typically used if there is direct web page processing of data by a script in which your web pages need to be in a certain format to serve both a human readable purpose and a computer processing purpose at the same time. As such this element relies on scripts to have any real use. This element does not have any design features.
  2. The 'value' attribute is required and used to assign a numeric or other value to the text wrapped by the 'data' element. In the example above, the 'data' element contains hidden product numbers inside its 'value' attribute associated with each product name.
  3. When might I need this element? One reason to use it would be to manage "name-value" pairs or for sorting of data. Your scripts might have thousands of pieces of HTML data like this they need to sort. Of course, modern JavaScript API's now allow you to download whole data sets and do sorting like this on the fly using more than one extra piece of data.
  4. Use the 'time' element instead if the data is time-based.
  5. Note: Using your web pages for storing data or data processing like this via the 'data' element and a scripted parser is rarely used. Today, there are much better ways to store data (JSON, XML, etc.) and distribute it (using modern JavaScript API's like Angular and React, for example). So if the 'data' element does serve a purpose it would have to be highly specialized. (See the use of the "data-" attribute elsewhere in this page for additional ways of storing data within elements.)
  6. Note: Internet Explorer does not support this element so in most cases it would be ignored. Because it degrades gracefully, however, this is not a block to using the 'data' element.
<datalist> datalist

Datalist

<form id="datalistform1" name="datalistform1" action="#" method="get">
  <label for="datalistname1" title="My Datalist">Double-lick to Choose a Browser from The Datalist:</label>
  <br />
  <input type="text" id="datalistname1" name="datalistname1" value="" size="20" maxlength="20" title="Double-click to Choose" aria-label="Browser" tabindex="0" list="browserlist" placeholder="Double-click to choose..." />
  <datalist id="browserlist" title="Browser List" aria-label="Browser List" role="listbox">
    <option value="Internet Explorer"></option>
    <option value="Firefox"></option>
    <option value="Chrome"></option>
    <option value="Opera"></option>
    <option value="Safari"></option>
  </datalist>
  <button id="datalistbutton1" name="datalistbutton1" type="submit" value="submit" form="datalistform1" title="Submit" tabindex="0" aria-label="Submit">Submit</button>
</form>

My Recommendations:
  1. The 'datalist' element is new in HTML5 and allows you to assign a select dropdown list to a input "text" box and narrow a user's choice of values. Currently in 2022, few of the new web browsers (and none of the old) consistently support 'datalist'. Therefore, its use is not recommended.
  2. Double-clicking the 'input' text box shows the datalist dropdown. The "suggested" choices provided by the 'datalist' are optional. A user can still override the list provided and type in their own text value into the input box. Note: The 'datalist' also works with other 'input' types, like the "number", "date", "email", and others. If the user has typed text in the box the datalist dropdown will not appear. The datalist is just an additional list of choices, or rather "suggested" values, and is helpful if you need to give users a limited selection of preferred options but also the freedom to add their own. Note: After users submit a choice from the datalist, on future datalists some browsers will show past choices listed before the default list of options.
    The 'datalist' works best with an 'input' box to receive the value from the 'datalist' when clicked. A "for" attribute is set on the 'input' that matches the datalist's 'id' attribute value. This associates it with the 'datalist'. As mentioned below, because 'datalist has poor browser support, this could fail and leave the user with no way to choose a value or know what options are available. So, its better to just stay with a traditional 'select' dropdown.
  3. The 'list' attribute of the 'input' element must match the 'id' of the 'datalist' element for the two to be connected and the input text box receive the datalist's 'value' attribute text when selected. 'name' is not supported.
  4. The datalist works with number, date, email and other input types.
  5. ARIA: You should always set an "aria-label" to tell screen readers what action to take on this new HTML5 element. Also, I recommend you add role="listbox", as its not clear that this new feature provides a list. This assists screen readers.
  6. Warning: There is limited browser support for the datalist! Internet Explorer 9 and earlier does not support the 'datalist, nor does the iPhone OS Safari browser released in 2018 or earlier. In addition, in the newest Chrome and Webkit browsers the list floats away from the input element when scrolling. For that reason, I do not recommend use of this new HTML5 element at this time! Because many browsers do not fully support this element and would not be able to choose any items, it does not degrade gracefully. A better option is to avoid the 'datalist' and just implement a plain 'select' dropdown HTML element with scripts that updates an 'input' element the minute the dropdown choice is selected.
<dd> description detail

Description Detail

see <dl>
My Recommendations:
  1. The 'dd' element is a piece of block-level text representing a description detail for a matching description term in a description list. The description list is often used to show a page's glossary, lexicon, or description of terms in key-value pairs. See the 'dl' element.
<del> deleted, strike

Delete

see also <in>

<p>Did you know my favorite color is <del>green</del> <ins>aqua</ins>.</p>

Did you know my favorite color is green aqua?

My Recommendations:
  1. The 'del' element represents a piece of inline text that has been recently deleted. The 'del' tag will draw a line through (strike) any text it wraps around.
  2. The 'del' element is often used to tell a reader of changes to text that are critical in representing the history of an edited document. An inserted text (<ins>) will often follow the deleted one (<del>) to indicate a replacement of new text for the deleted one and to emphasize the change.
<details> details

Details

also see <summary>

The "details" example is show below. It includes a 'summary' element with a click-able title which reveals additional 'details' element text below.


<details id="detailsexample1">
  <summary style="background-color: #ccccccff;box-shadow: 2px 2px 3px #aaa;">&copy; Copyright 2022</summary>
  <div style="margin:0;padding:.2em 1em;background-color: #efefef;box-shadow: 2px 2px 3px #aaa;">
    <p>Owned by Company ABC. All Rights Reserved.</p>
    <p>All content and graphics on this web site are the property of Company ABC.</p>
  </div>
</details>
© Copyright 2022

Owned by Company ABC. All Rights Reserved.

All content and graphics on this web site are the property of Company ABC.


My Recommendations:
  1. The 'details' element is new interactive element in HTML5 which shows a text summary and additional hidden text details that the user can see by clicking the summary text. This is usually created by the browser as a piece of title text with a dropdown toggle arrow that reveals hidden content when clicked. This element is typically used as a JavaScript-free toggle widget to disclose additional information if the user chooses to view it.
  2. The details element is comprised of a single click-able <summary> element or title, followed by multiple HTML content elements which will be hidden until the summary text is clicked. The supporting browser controls the hiding and click-able arrow interactive elements. Because the 'details' element is a "list", setting its CSS display to anything other than "display: list-item" will remove the dropdown toggle arrow. You can add your own custom toggle arrow but that is beyond the scope here as browser support would be very sketchy.
  3. The details hidden element is closed by default until clicked. But you can add the open="open" attribute to the 'details' element to show the hidden content by default.
  4. Always add a unique 'id' to the 'details' hidden element so it can be manipulated by scripts.
  5. IE "Fallback" CSS Design: Because IE1-11 doesn't understand the 'details' element or 'summary', its summary and content will both be shown opened, as if they were "clicked". When those elements have been given CSS background colors, all content is then displayed for those older browsers versus being hidden until clicked for more modern browsers. When that happens, the background colors I've applied above are partially shown as a strip of color above the text in the 'summary' element. That is why in my CSS I added the colors shown above. I've added a fallback CSS style of "background-color:#ccccccff" with alpha values at the end to force them to not show any background color in IE. The last two values of "#ccccccff" are CSS3 supported in newer browsers and define transparency alpha values of opaque (ff), which IE 1-7 versions do not understand so default to white when the full content of the details element is shown in these older browsers.
    WARNING: Changing the 'details' or 'summary' element's "display" or "list-item" properties destroys the ability of newer HTML5 browsers to render this interactive element correctly! So, avoid most structural style changes and try and just stick with font, borders, and background color changes.
  6. This Element is NOT an ARIA Button: Avoid adding the ARIA "role=button" attribute on this element or its children as it is not designed to be recognized by screen readers as a button. This will only confused screen readers believing they are either submitting data or launching off to some URL, or worse, triggering some unknown page event. Besides, the detail element should be known by modern screen readers that know HTML5, They also should see the 'summary' and 'details' element text quite easily without any added interactions.
  7. Because this element's interactive design is controlled by the web browser, there is limited CSS styling available for the details element. There are some specialized Chrome features but no wide support for customizing this element. But, I have added some additional styles in the example above to demonstrate what is possible.
  8. The details feature is not supported by Internet Explorer 1-11, and may have limited browser support in some older mobile phone browsers. However, if the feature is not supported, it simply shows the summary and all hidden content beneath it. Because this new HTML5 element degrades gracefully in older browsers, I support its use.
<dfn> definition

Definition


A Definition as Referenced By a Page Link

<p>Learn more about the <a href="#sun">Sun</a></p>
<p>The <dfn id="sun" title="Our Shining Celestial Body">Sun</dfn> is the name of the local star in our solar system.</p>

Learn more about the Sun

The Sun is the name of the local star in our solar system.


A Definition as Abbreviation

<p><dfn><abbr title="HyperText Markup Language - Version 5">HTML5</abbr></dfn> is the fifth version of the standard markup language used in creating web pages.</p>

HTML5 is the fifth version of the standard markup language used in creating web pages.

My Recommendations:
  1. The 'dfn' element represents a piece of inline definition text when its term is defined in a paragraph. It represents a piece of text that is going to be defined within a sentence. Use this element if you are explaining a term like in a dictionary definition directly in your text. The definition item is usually styled in plain italics.
  2. The 'title' element can be added to a 'dfn' tag to provide an additional definition text on rollover. See example above.
  3. Add an 'id' attribute so an anchor tag with a "#" and name of your id can be clicked and accessed in a larger page if referencing the definition. See example above.
  4. The 'abbr' element can wrap around a term inside the 'dfn' tag if the text is an abbreviation that needs to be listed in full. See example above.
  5. You can even wrap a 'dfn' tag around a term ('dt') in a "description list" ('dl') if the term is actually represented by a description that is a formal one, like from a dictionary. Example: <dt><dfn>HTML</dfn></dt>. See 'dl'.
<dialog> dialog, dialog box, modal, pop-up

Dialog


My Custom "Cross-browser Dialog Box"

(Paste the HTML and JavaScript block below into your web page to recreate my new and improved "cross-browser" HTML5 dialog box)


<div id="dialogbox_alt" role="dialog" aria-label="Alternate Dialog">
<dialog id="dialogbox" aria-label="Dialog" style=" display:none;
width: 20em;
min-height: 15em;
max-width: 50%;
padding: 1em;
background-color: #fff;
border: 2px solid #999;
border-radius: .5em;
/* center all dialogs */
position: fixed;
top: 50%;
left: 50%;
margin-left: -10em;
margin-top: -5em;
z-index: 99;
/* create background screen */
box-shadow: 0 0 0 9999px rgba(0,0,0,0.6);
">
<form id="formdialog1" action="#" method="get" style="position:relative;
width:100%;
height:100%;
padding:0;
margin:0;">
<span id="dialogcloser" style="display:inline-block;
cursor:pointer;
padding:.2em;
position:absolute;
top:-5px;
right:-5px;">X</span>
<div style="padding:1em;">
<p>
<label for="animals1" title="Animals">&nbsp;*&nbsp;Choose an Animal:</label>
<select id="animals1" name="animals1" size="1" required="required" aria-required="true" aria-label="List of Animals" tabindex="0">
<option value="" selected="selected">- choose an animal -</option>
<option value="elephant">Elephant</option>
<option value="zebra">Zebra</option>
<option value="lion">Lion</option>
</select>
</p>
<p>
<button type="submit" name="dialogconfirm" value="confirm">Confirm</button>
</p>
</div>
</form>
</dialog>
</div>
<button id="dialogopener" type="button">Open A Dialog Box</button>



My Recommendations:
  1. The 'dialog' element represents a dialog box/modal/window/popup/interactive box that is new in HTML5 and only appears when an event outside of HTML fires to open it. It is supposed to display a window or box on top of a web page, like a desktop Windows program might do. It is a very simple concept but fails in many browsers. Its is a simple element to implement until you realize it does not work without a lot of styled and scripted scaffolding. Unfortunately, the HTML5 'dialog' element is JavaScript-dependent, is not supported in many modern HTML5 browsers, and doesn't work in most of the other browsers but a few of the most recent. That is why I designed a cross-browser version above you can cut-and-paste easily and move on. The code above includes lots of additional styles and attributes, too many to list. But below I will just describe the core features of the main 'dialog' element, not the dependencies. But read below for all the dirty details.
  2. Add the 'id' attribute to this element so it can be accessed by scripts and styled.
  3. The open="open" attribute can be added to the 'dialog' element if you want the dialog popup to appear when the page loads. It is off by default, so the dialog remains hidden until shown. You must add scripts to a button with "onclick=showModal()" to open it. Note: This only works in 'dialog' supporting browsers.
  4. You can add a 'form' element with fields and buttons to a dialog so that when it appears it requires user to give focus to entering data apart from the rest of the page. If you do add a form inside 'dialog', setting the form's method="dialog" attribute will allow the form to automatically close when "submitted". Note: Again, this only works in 'dialog' supporting browsers. I ran this attribute value through the W3C validator and it rejected this value so it must be proprietary to a few user agents and not yet approved or widely adopted into the HTML5 "living" standards. UPDATE (11/2022): Updates to the 'dialog' element in WebKit browsers like Chrome recently changed this form method feature, so method="dialog" fails to submit HTML form data! Do not use method="dialog", but a plain form method like POST or GET.
  5. Dialog Boxes and their History of Confusion: The idea of the "dialog box" and the fun of stopping a page view and having an interactive box appear is a promise as old as the Web. But it is a history of many failures and half-attempted proprietary technology by people that failed to come together to define the "dialog" concept properly. That is why dialog boxes still FAIL to work today in many browsers! Trust me, I know as I have used all the JavaScripted versions for years and years.
    The dialog has been around since the birth of the Web! In the old days (c. 2000), the "dialog box" was often confused with many types of scripts and names. For starters, the term "dialog" was often used with the word "modal", which was a reference to the tendency of Windows desktop computers to display software confirmation or login boxes on top of other windows in the monitor. "modal" windows always implied a window that was a child of another. In the browser world, this often made no sense. This just added to the problem of understanding the "language" used to describe each type. All of the various window "types" had been called "dialogs" at one time or another. Example: A "pop-up" was really a call to an "opener" that actually created a true browser window that was a child of the parent browser window. Many people later called this a "modal" or "dialog". But it was not! Neither was the "confirm" or scripted window. The term "dialog" was then more commonly used for all of them over time, though confused with a variety of scripted versions, including the JavaScript "Pop-up" window, the JavaScript "alert" window, the JavaScript "confirm" window, Windows PC dialog windows created by the OS, and finally DHTML windows (which often were just versions of various JavaScripted windows). A last type of window used was the plain HTML "div" that floated over text, but which again was more of a sub-type of newer DHTML "dialogs" that over time tried to abandon popups and other proprietary scripted modal windows. All these were called "dialog", "popup", or "modal" windows at one time or another in the web world. Eventually a few companies popped up bragging about their powerful "modal window" systems when really it was more gobs of JavaScript or plugins we really didn't need. What is bizarre is that nobody could ever give you an accurate explanation of the differences, and still cannot today!
    Now that you are totally confused, how do you think we felt as developers when we found out that in order to create all these types of windows, each of the older browsers needed different versions or types of JavaScript calls, and that Internet Explorer had its own type of special Windows the others did not have, including proprietary login pop-ups only Windows supported! What made this idea worse, was the fact that custom browser "plugins/players" like Flash and Java had their own version of "dialogs", which we learned later came with security risks!
    To simply the idea of windows and pop-ups, and knowing some history of "dialogs", my list below should clarify everything so you understand that a "dialog" as used today using the new 'dialog' element uses plain HTML, yet remains JavaScript-dependent. All the others are various types of JavaScripted alerts, windows, and console views that in modern HTML are no longer considered "dialogs" but called something else, thank goodness. But in web developer groups online, the same confusing language will occasionally "popup". You have been warned! Keep in mind this information below is not a definitive list of all the "dialog" types, just the main ones I remember. Many of the later proprietary Mac OS, browser, or ECMAScripted version "modal" calls are not all covered here. But below you can begin to see why I still feel JavaScript is Evil, simply because it has allowed so many kooky events and calls to trigger things in browsers that still irritate users and developers alike.

    Types of Things People called "Dialogs"

    1. "Popup" - This really was the only true "popup" window in the Web World, though some called it a "dialog" window in their websites. At least they tried to design it to look like one. It is just an old JavaScript call to open a child window (window.opener) of the parent window. As such, it floated outside the browser itself and appeared more as a true browser tab or page detached from the main user agent. It even came with its own "href" location. The old advertisers online started to use "popups" to trigger adds starting in the late 1990's which led over time to spam and even security concerns. Ad blockers have long ago blocked these. Because of security concerns I believe the old popup model is blocked by default in all the modern browsers, even old IE.
    2. JavaScripted "ShowModalDialog" Box - If you ask me, this is the only thing that was ever a true "Modal" window in the Web World. This was a rarely used but strange little modal box, often used only in IE browsers to create a true modal window that was not a child of a browser window. Its now dead. Unlike "popup", it had poor support and even poorer styling options way back when. At one time is had a very slick looking interface that felt like a true modal window. Like all the others, it was a security risk at worst, a cross-browser headache at best as only Internet Explorer and a few Safari versions supported it.
    3. JavaScripted "alert()" box - We still use these scripted alert boxes for tested API's and for simple browser messages to the user. Some call these popups, modals, or dialogs but they are not. They are simply small scripted "alert boxes" that show a message and a button to close them. They pause all scripts and displays and are great when forcing users to take an action as they completely layer over the whole page. What is even better is they have wide cross-browser support going back to browsers created prior to 2000. But these are not dialogs, though you can make them large enough with text to look like a dialog.
    4. JavaScripted "confirm()" Box - This "confirm box" works the same as the scripted "alert()" box above, except it offers the user two interactive choices using an "Ok" or "Cancel" button option set. Depending on this choice, this allows the scripter to trigger different events based on the user's decision. It is still a great tool few young developers know about. But it is still not a dialog!
    5. DHTML "Modal Windows" - YES!! These were a true "dialog box", though most older Windows Desktop programmers thought these were just repeats of their old Windows modal windows. But they were wrong! There is too much to list here about DHTML dialog boxes, especially since its a dead technology. But in honesty, most of the JavaScript boxes kids use today is just building on top of older DHTML dialog scripts already built 20 years ago that JQuery and others hijacked. DHTML basically tried to redesign scripts to instead layer HTML boxes over other HTML, which is a true dialog box and gets us to where we are today. These HTML scripted boxes included all of the above circus tricks, with just more JavaScript manipulation of HTML and CSS for a richer display. This included custom "Microsoft Extensions for CSS" that allowed IE 6-9 to use CSS "behavior" properties to load scripts and DHTML. Few use this trick anymore as it is a dead technology. This is what our "dialog" element tries to replace today, but sadly still does not, simply because it still relies on scripting. It would be nice if the HTML5 guys had designed a dialog "button/box" combo you could customize instead. Then we would not need all of the above!
  6. Warning: 'dialog' has minimal browser support today! Internet Explorer 1-11, Safari version 12 or earlier (desktop and iPhone), and Firefox version 63 or earlier, Chrome version 36 or earlier, Edge 18 and earlier, and Opera 23 or earlier do not support use of the 'dialog' element. Because of lack of wider browser support I generally do not recommend use of the 'dialog' element. You can now create much simpler modal boxes with a 'div', absolute positioning, and z-index layers in CSS.
  7. CUSTOM DIALOG SOLUTION: Because I do not like Modernizr or "polyfills", I created a much simpler 'dialog' box above you can use that supports most browsers with either the 'dialog' element or a simpler scripted 'div' window for non-supporting browsers. The custom script and dialog solution I am posting above will solve most of your cross-browser issues using the new dialog modal window! It even works in Internet Explorer 5-11. The following features are listed below:

    Features of My Custom Dialog Box:

    • My Dialog Box design allows you to support HTML5 dialogs and modern modal windows in your website, while displaying simpler solutions for older browsers.
    • Dialog Box comes with a white, centered, rounded popup design you can customize.
    • Dialog Box has a sample form field with required dropdown and submit button that posts to the server and closes the dialog on submission.
    • Dialog Box has a cross-browser dark background CSS design in most older browsers
    • Dialog Box has an extra "close" button for improved assistive support
    • Dialog Box is fully compatible with many older browsers, including IE5-11
    • Dialog Box is one block of HTML and one block of legacy JavaScript designed for support in older browsers
    • Superior functionality in older browsers compared to JQuery Dialog, Modernizr, and more!
    • Heavy JavaScript API's, polyfills, Modernizr, JQuery, or other JS frameworks are NOT required!

    * Internet Explorer Browser Support:

    • IE 10-11 : Performs normally with background
    • IE 9: Performs normally but without a background
    • IE 7-8: Performs normally but without a background and no rounded borders
    • IE 4-6: Dialog appears inside its parent block, but is fully functional. Also, "position:fixed" is not supported in these browsers, so the box returns as part of the scrollable page.
<dir> directory, directory list

Directory

<dir>
  <li>Directory Item #1</li>
  <li>Directory Item #2</li>
</dir>
  • Directory Item #1
  • Directory Item #2
  • My Recommendations:
    1. The 'dir' element defines a directory list. It was designed to create multi-column directory lists in old HTML4, but has been deprecated. Do not use the 'dir' element as it has been deprecated in HTML5. Use 'ul', 'ol', and 'dl' instead.
    <div> division, container

    Division

    <div style="padding: 1em;border:1px solid black;">
      <p>This text is inside a "div" container</p>
    </div>

    This text is inside a "div" container

    My Recommendations:
    1. The 'div' element is a block-level container that defines a logical division of content in a web page. The 'div' element was a part of the original HTML specifications in the early 1990's. It has changed very little in over 20 years. It has also been the "work horse" element for most HTML web pages built today and in the past, and often used for holding large sections of content or for layout designs.
    2. The 'div' element is by default a "block-level" element or container in web pages. It holds space, creates a new line, has margins, has dimensions, expands to take up available page width, and is part of the page flow. As such, it is considered one of the chief "flow content" element types. You can use CSS to change the structure and design of the 'div'. This makes this element a good choice for both custom layout designs and empty wrappers for holding content in your web pages.
    3. 'div' Attributes: Other than setting a unique 'id' on 'div' elements you wish to hide or manipulate with scripts, there are no real attributes beyond ARIA "roles" and "aria-labels" you should need on the 'div' element. 'div' is considered to have an ARIA "generic" role by default (not "none"'). Use these attributes when your 'div' element serves a purpose beyond a generic one, or contains content with semantic meaning in the page screen readers need to understand. An example might be "role=alert" added on 'div' that is used as an alert box. There are some unique attributes that add additional value without scripts, including "contenteditable=true" which allows text inside your 'div' to be edited by a user. Of course this change is not permanent, but might be helpful for educational web sites or demonstrations.
    4. The 'div' Element, Structural HTML Powerhouse! Since the birth of HTML in the 1990's, the 'div' element has been used to structure the layouts of millions of websites. We still use the 'div' element to design our page layouts. But in HTML5 that has been replaced by newer more semantic elements like 'main', 'header', 'footer', etc. But if you need a generic container for content or other structures, use our old friend the 'div' element.
    <dl> description list

    Description List


    A Description List can have Multiple Description Terms

    <dl>
      <dt id="dog1">Dog</dt>
      <dt>Puppy</dt>
      <dt>Mutt</dt>
      <dd aria-labelledby="dog1">Man's best friend</dd>

      <dt id="cat1">Cat</dt>
      <dt>Kitty</dt>
      <dd aria-labelledby="cat1">Our feline friends</dd>
    </dl>
    Dog
    Puppy
    Mutt
    Man's best friend
    Cat
    Kitty
    Our feline friends

    A Description List can Include Definition and Abbreviation Tags

    <dl>
      <dt id="html1"><dfn><abbr title="Hypertext Markup Language">HTML</abbr></dfn></dt>
      <dd aria-labelledby="html1">The standard markup language for creating web pages.</dd>
    </dl>
    HTML
    The standard markup language for creating web pages.
    My Recommendations:
    1. The 'dl' element is a block-level container representing a description list. This list contains groups of description terms ('dt') and descriptions details ('dd'). The description list is often used to show a page's glossary, lexicon, or a dictionary of terms in key-value pairs. The 'dl' element has been around since the HTML4 days, and so is a reliable tool, though rarely used. HTML5 now supports it.
    2. The child elements, 'dt' and 'dd', are contained inside the 'dd' tag and used to list "terms" and their matching "descriptions". As such, the 'dd' element is just a list container like 'ul' and 'ol' list parents and has no visual design. Each 'dl' element should wrap around only one associated "term"/"description" set. Note: You can have many terms per description in a set, or many descriptions per term in a set (see my code examples above).
    3. Even though a description list is just that, "descriptions" of terms used in a document, it is NOT the same as a "definition" or formal approved dictionary definition. If your list performs as a dictionary or actual definition list, you can wrap a 'dfn' tag around a term ('dt'). Example: <dt><dfn>HTML</dfn></dt>. When you wrap a 'dfn' tag around a term, you are officially "defining" a term and your list is now acting like a true dictionary or lexicon. See 'dfn'.
    4. You can wrap a 'abbr' tag around a term ('dt') if the term is an abbreviation. Example: <dt><abbr title="Hypertext Markup Language">HTML</abbr></dt>. See 'abbr'.
    5. The 'nowrap' attribute on the 'dd' child element used to be used to determine if the description detail text should not wrap. But this is now deprecated in HTML5 and I do not recommend its use. Use CSS styles instead.
    6. In the above example, I show how definition lists can be grouped in key-value pairs. In the last example, I show how you can wrap description pairs in 'div' elements for styling purposes.
    7. I have also added ARIA accessibility tags in the examples above to enhance screen reader understanding of your description list.
    <dt> description term

    Description Term

    see <dl>
    My Recommendations:
    1. The 'dt' element is a block-level container representing a description term for a matching description detail within a description list. The description list is often used to show a page's glossary, lexicon, or description of terms in key-value pairs. See the 'dl' element.
    <doctype> doctype definition

    Doctype

    see <html>
    My Recommendations:
    1. The 'doctype' element defines the doctype definition of a web page. See the <html> element for a full description.
    <em> emphasis

    Emphasis

    <p>This text has <em>emphasis</em>.</p>

    This text has emphasis.

    My Recommendations:
    1. The 'em' element is used to represent a piece of inline text that is emphasized or carries a shift in tone in a sentence. It is usually represented visually by italic text.
    2. Note: Use 'em', not 'i' in your HTML. The text these two tags wrap around looks the same but does not carry the same meaning. In old HTML4, tags like 'i' were used to only format or style text, not stress its importance. And so the meaning of the text was lost using 'i'. Today in HTML5, importance has shifted to semantic tags that carry meaning as well as style, like 'em', which tells search engines and readers this piece of content has emphasis and should stand out. When you have text in a paragraph that needs emphasis use the 'em' element rather than the 'i' element.
    3. What is the difference between 'em' and 'strong'? Use 'em' for a shift in tone or voice that represents emphasis. Use 'strong' for VERY important text that carries more weight than 'em'. 'strong' might also be seen as "stronger emphasis". (see 'strong' for its sibling type)
    <embed> embed

    Embed

    <embed id="embed1" alt="embed: Electronic Sheep Video" style="width:324px;height:240px;border:1px solid #000;" src="video1.mp4" type="video/mp4" loop="false" title="Electronic Sheep Video" aria-label="Embedded File: Electronic Sheep Video">
      <noembed>Your browser does not support this media object or the embed element.</noembed>
    </embed>
    Your browser does not support this media object or the embed element.

    (Above is an example using the embed tag. Depending on your browser and the plug-in supported, you should see an "MP4" (MPEG4) video file. If you do not it is because this video format or codec is not supported by your browser.)

    My Recommendations:
    1. The 'embed' element is used to display a multimedia file in a web page, including an image, iframe, Adobe Flash, Java Applets, online documents, audio, or video files. This element is supported in HTML5 but slowly being deprecated by other elements when displaying multimedia in the browser. Use the 'img', 'picture', 'iframe', 'video', or 'audio' elements instead for those types, and 'embed' for specialized multimedia types only. Keep in mind 'embed' relies on plug-ins and players to play its media unlike the other HTML5 media types. More details below.
    2. The 'embed' element supports a number of attributes, including 'width', 'height', 'src', and media 'type'. The 'width' and 'height' are used to set the dimensions of your file. The 'src' attribute is a path to your multimedia object. The 'type' should have the generic MIME type of your media object and is a hint to the browser of how to interpret it.
    3. Deprecated Attributes: There are many old attributes used by 'embed' by browsers of the past that may not work. I have listed the ones below I recommend you avoid: bgcolor, hspace, palette, pluginspage, pluginspace, quality, salign, scale, vspace. Note: I have added the "loop=false" attribute to the code above, though it is likely not supported in modern HTML5 browsers today. But it prevents some older browsers from repeating video playback in a loop forever.
    4. As usual, always include an 'id' and a 'title' on these click-able multimedia objects. The 'title' tooltip might not show up on rollover but in some browsers may appear.
    5. The 'alt' attribute in 'embed' elements helps screen readers and the blind identify the meaning of embedded elements, just like images provide. For that reason, always add the "alt" attribute.
    6. In older pages you may see a strange attribute (not used in HTML5) called pluginspage, which is a URL that indicates to the browser where the required plug-in is to be found to play the media if it is not installed in the browser. Plug-in vendors typically made available a URL to download and install such plug-ins. Flash and the Adobe Flash plug-in download was a common use for this attribute. When a user displayed the page and did not have the player a popup would fire up asking them to install it. This is less common today.
    7. Add autoplay="false" to stop videos from automatically playing when the browser loads. Also, some browsers interpret the presence of the 'autoplay' attribute as a boolean 'true' regardless if you set it to 'false'. So remove it completely if that is the case. Never use 'autoplay' without a true/false as it fails in XHTML5/XML parsers.Warning: Videos automatically play in some modern browsers using 'embed' regardless of setting autoplay! I tried changing many attributes to stop this and it still played! It turns out your users will have to go into their browser settings and under "privacy" change the "autoplay" feature to block autoplay for both audio and video. (This must have something to do with kids wanting Youtube videos to autoplay in web pages now.)
    8. Use of the 'noembed' element: Today, in HTML5, the 'embed' element is generally an empty element, meaning it has no start and end tag with no additional content inside it. It just displays a media element. But in the old days of the Internet, 'embed' was often part of a block of elements designed with fallback tags if a browser did not support object, embed, etc. The "noembed" is still supported but rarely used. However, in the example above, you will see how I have added the 'noembed' back in as a nice fall back element if a browser or screen reader does not understand the other 'embed' parent element.
    9. The 'embed' element was never a part of the HTML4 spec's but was built by Netscape as a popular alternative to Microsoft's 'object' element for ActiveX and the 'applet' element for Java players. It has been around since the birth of HTML and the 1990's, so was once a very popular element used to support multimedia objects in web pages (everything but Internet Explorer which did not support 'embed'). Because 'embed' became a universal element for non-IE browsers and players, while 'object' became a Microsoft Internet Explorer ActiveX element, 'embed' was often contained inside 'object' elements and used as a fallback to Microsoft's ActiveX 'object' version. 'embed' is now strangely a part of HTML5. You can still play many types of media using the 'embed' element, including: Images, Video, Audio, Flash, iframes, and more. The browser will interpret the media player required based on the file extension and the 'type' attribute and attempt to load a player to display it. Remember, Internet Explorer 5-10 has limited support of the 'embed' element as it needs the ActiveX 'object' element, instead.) Because of these crazy cross-browser issues, deprecated ActiveX support, and the fact images, video, and audio can now be displayed in newer HTML5-friendly elements, there really is no reason to use 'embed' except to support older browsers or specialized media. Most of the "other" media 'embed' once supported have gone anyway and were driven by deprecated multimedia players that have been discontinued years ago. However, you may find older websites that still use 'embed'. If you are targeting older browsers it might be useful to still use 'embed' in special limited cases so you support those older user agents.
    10. History: Prior to 2010 and the advent of HTML5, the 'applet', 'embed', and 'object' elements were used to display a wide range of multimedia objects in HTML including: Java Applets, Adobe Flash, plug-ins, ActiveX objects (in Internet Explorer only), images, video, audio, Windows documents, and older 3rd party applications in the browser. Nearly all embedded media was played back via a "player" or "plug-in" separate from the browsers. 'embed' and 'object' use this plug-in model, while the newer HTML5 'video' and 'audio' have native playback support built into the browser and element. Keep in mind that for over a decade, web browsers viewed millions of multimedia objects this way using plug-ins and players of many types. Many of these media types are now discontinued, no longer supported, or are security risks in the browser. Smart phones also decided these players and plug-ins were a security risk as well as a CPU hog. For those reasons and more, these multimedia elements are generally not used in HTML5, though they are still supported in various forms. With the newer smart phone technology that came online after 2007, it was decided that most of this new media would not be supported on mobile devices going forward. And so the plug-in model is dying fast. Tags like the 'applet', 'object', and 'embed' elements are dying too, even on desktop. Legacy websites today that still contain unique custom multimedia objects like this must now be removed or replaced with alternative media types as so many of the "players" that once supported rich media like this are no longer around to play them (post-2010). Adobe Flash, for example, was discontinued just a few years ago, though it was once hugely popular as a choice for highly interactive solutions in thousands of desktop websites. (I actually used to write Adobe Flash animations and applications in old Actionscipt.) This change has not stopped video, audio, or other applications from being embedded in web pages, however. HTML5 has simply come up with alternate elements where the players are built into the browsers that parse them. Keep that in mind. So, if you see these old elements, 'object' or 'embed', and are deciding to remove them or update them with HTML5, use the newer HTML5 elements and media types available ('img', 'picture, 'iframe', 'video', and 'audio' using MPEG4, WebM, etc.).
    11. Warning: Most versions of Internet Explorer 1-11 have never supported 'embed' and prefer the 'object' element instead, as it supports ActiveX. IE9-11 have adopted support of HTML5's 'video' and 'audio' elements instead of 'object'. This is another reason to avoid this element and move to the 'video' or 'audio' element instead when supporting newer browsers. If you support video in these older browsers, however, you may find you need all three elements. Note: For a powerful new cross-browser video solution that works in old and new browsers and combines 'video', 'object', and 'embed' elements, see my section in "best practices" below called: "How to Create a Cross-Browser Video in HTML5".
    12. Warning: The sample video above may not play in Internet Explorer using Windows Media Player. If the video above does not play in IE or your browser could be because the media player used by the browser does not support the codec capable of decoding the video information. Your OS may recommend the installation of an additional codec to make up for this deficiency so that you can play the movie in your media player.
    13. Warning: Use CSS to set custom 'width' and 'height' using 'embed' in supporting newer HTML5 browsers, as the attribute version may not honor the dimensions you set. (see my example above)
    14. As mentioned, I recommend you NOT use 'embed' for playing audio and video in web pages, but use the 'img', 'picture', 'video', or 'audio' elements instead. Even though HTML5 still supports 'embed', because it is an element that is more reliant on the older "plug-in" player model, its better to avoid its use going forward. Again, if you must support IE or older browsers with multimedia, you may need to add a scripted fallback to use 'embed' and 'object' along with say the 'video' element when supporting these older browsers with video.
    15. See my article below called "How to Create a Cross-Browser Video in HTML5" for a newer, more modern example of how to combine 'video', 'object', and 'embed' elements together to enable wide video playback support across many old and new browsers.
    <fieldset> fieldset

    Fieldset

    see <legend>

    <form id="fieldsetform" name="fieldsetform" action="#" aria-label="Login" title="Login">
    <fieldset id="fieldset1" name="fieldset1" form="fieldsetform">
    <legend style="background-color: #ccc;color: #fff;">Login</legend>
    <p>
    <label for="fieldsetinput1" title="Username">Username:</label>
    <input type="text" aria-label="Username" id="fieldsetinput1" name="fieldsetinput1" size="20" maxlength="10" value="" title="Username" tabindex="0" autocomplete="username" />
    </p>
    <p>
    <label for="fieldsetinput2" title="Password">Password:</label>
    <input type="password" aria-label="Password" id="fieldsetinput2" name="fieldsetinput2" size="20" maxlength="10" value="" title="Password" tabindex="0" autocomplete="new-password" />
    </p>
    <p><button id="fieldsetsubmit1" aria-label="Submit" aria-pressed="false" title="Login" tabindex="-1" disabled="disabled" aria-disabled="true">Login</button></p>
    </fieldset>
    </form>

    * Note: The box around the form fields is the 'fieldset'. The "login" text is the fieldset's 'legend'.
    Login

    My Recommendations:
    1. The 'fieldset' element is used to group related form elements together, including the input, select, textarea, and button elements. It is often used to wrap a bordered, gray box around elements, simulating a PC dialog box when styled. It is a block-level element prized for its ability to group larger sections of complex forms into subgroups which would otherwise become difficult to manage. Note: It is recommended you use 'fieldset' with 'legends' (see below) if you plan to have multiple 'submit' buttons or subsections inside your forms.
    2. The 'fieldset' element supports a number of attributes, including 'form' to connect the fieldset with its parent form element's 'id'.
    3. Adding the 'id' and 'name' to your 'fieldset' is useful for showing and hiding large blocks of form elements using scripts. The 'title' attribute is optional here as the 'legend' provides a title.
    4. A 'fieldset' usually sits inside a parent form, which wraps about it, or can be located outside the form but with a 'form' attribute associating it with the form elsewhere in the page (not recommended). It is recommended you always insert 'fieldset' directly under and inside every form, if you use it to group controls. Always use 'fieldset' if you plan to have multiple 'submit' buttons or subsections of forms. Also, the 'fieldset' element can be nested inside other fieldsets!
    5. The 'disabled' attribute can be used to quickly disable all child form fields inside a 'fieldset'. But, I do not recommend you use the 'disabled' attribute in 'fieldset' as it might not be reliable in some browsers (Some Edge/IE browsers have issues with this attribute.), enabling buttons and forms to be active and submitted to the server, which you might not want. You should control them individually.
    6. The 'fieldset' originally had a "Windows dialog box" look to it when using the browser's default style. It often came with a nice light gray background, grouping form fields with this neutral color. It then used raised buttons that pushed into the 'fieldset' color, much like old desktop application dialog panels used. This default gray look in older browsers was really nice and easy to use. We often used this look to dissolve the disconnect the modern user had online with web form displays, showing instead the old 1980's data entry forms they were used to. (I recommend you try that look-and-feel in your own web forms!)
    7. CSS Issues With 'fieldset': In older browsers, like IE 4-7 and Netscape 4 series, you may see some design issues with this element. Fieldset originally had a Windows dialog box feel to it with a lite gray background when grouping form fields. This looked really nice with input controls inside it. So many designers tend to apply their own background colors and borders. But some older browsers bleed the gray color over the legend at the top, which looks ugly. To solve this you could just set "background-color: transparent". But then Netscape 4 series set background to black if a border was applied and background was set to transparent. So, to fix all this I created my own style fix below, which sets background to white for Netscape only and everyone else to transparent. I then apply this code below just for IE 1-7 series, and in my modern sheets add new designs for more modern browsers. Note: The "/*/*//*/background-color: white;/*end*/" code is a hack only for Netscape 4.

      Old Browsers Only - Fieldset Design

      
      fieldset {
          display: block;
          width: auto;
          height: auto;
          padding: 8px 16px 16px 16px;
          margin: 8px 0px;
          background-color: transparent;
          /*/*//*/background-color: white;/*end*/
          border: 2px solid #bbbbbb;
      }
      

      Modern Browsers Only - Fieldset Design

      
      fieldset {
      	display: block;
      	width: auto;
      	height: auto;
      	max-width: 100%;
      	padding: .5em 1em 1em 1em;
      	padding: .5rem 1rem 1rem 1rem;
      	margin: .5em 0em;
      	margin: .5rem 0rem;
      	border-radius: .2em;
      	border-radius: .2rem;
      	background-color: #f3f3f3;
      	border: 2px solid #bbb;
      }
      
    8. Browser Support: 'fieldset' has wide support in nearly all browsers, old and new. So, it is fully supported.
    <fig> fig, figures

    Figures

    The <fig> element is a lost relic from old HTML 3.0 (1995). It is no longer supported, but oddly was redesigned back into HTML5's 'figure' element.


    <fig src="cat.jpeg" align="left">
      <caption>My cat's name is 7-Up!</caption>
      <p>My cat loves fish and to roam outside after his meal.</p>
      <credit>Cat Daddy wrote this!</credit>
    </<fig>
    My Recommendations:
    1. The 'fig' element or figures, is now fully deprecated. It represented a "figure caption" element in old HTML 3.0 (1995) which contained text and images around which web page content would flow. The 'fig' element has inspired the current HTML5 'figure' and 'figcaption' elements used in modern web pages today. For that reason, Do not use the 'fig' element as it has been discontinued. Use the 'figure' and 'figcaption' instead.
    <figcaption> figure caption

    Figure Caption

    see <figure>
    My Recommendations:
    1. The 'figcaption' element defines a title or "figure caption" for a visual object. See 'figure' below.
    <figure> figure

    Figure

    <figure style="padding: .5rem;border:1px solid #bbb;background: #f0f0f0;width: auto;height: auto;display: inline-block;" aria-labelledby="myfigureimage">
      <img id="figureimage" src="www.jpg" width="255" height="200" alt="image:World Wide Web" title="World Wide Web Image" onerror="this.onerror=null;" loading="lazy" />
      <figcaption id="myfigureimage" style="text-align:center;display:block;">This is the <cite>World Wide Web!</cite></figcaption>
    </figure>

    * I have created a very simple 'figure' example below using a plain image. But, you can wrap figures around many types of objects to create more complex captions (see my examples in "Best Practices" below).

    image:World Wide Web
    This is the World Wide Web!
    My Recommendations:
    1. The 'figure' element defines a an image or visual element as a "figure" complete with a title or caption under it. The 'figure' element is new in HTML5 and is now used by modern browsers to add textual information to images and other visual objects. The child 'figcaption' tag is part of the parent 'figure' element and allows many visual elements to have descriptive text associated with them. Before 'figure' was invented, captions on images and videos was often problematic in HTML design.
    2. Figures: Most photographs or article images should carry more visual information with the element. The 'figure' element solves that by wrapping a visual element in the web page - 'video, 'img', or 'picture' - and associating them as figures within the larger page context. The "figcaption" resides inside the 'figure' element and often appears under the visual item with a "caption" describing the item. In the sample above, I demonstrate an 'img' element with a 'figure' and 'figcaption' as well as a full suite of attributes that assist visual and non-visual users alike in viewing the complete image as a figure within the page. Note that the 'figure' element has additional formatting that enhances the frame around the image as it might appear in an article. The child 'figcaption' element has placed a nice caption on the image. Notice the image has its native width and height attributes added, a title, alt value, and additional CSS to create the padded border. Adding dimensions on the image allows the "Render tree" in the browser to reserve space for the image in the figure and viewport as it downloads. I have also added an ARIA label (see below) to connect the figure with its caption for screen readers. Note that there are more complex 'figure' structures you can use. This one just demonstrates the most common one, which is an image with a caption.
    3. Figure Tag Structure: The 'figure' element always contains a 'figcaption' element with text that resides directly underneath the video, img, or picture element. You always place description text or the "caption" describing the visual object inside 'figcaption'. Note that you can use 'figure' and 'figcaption' with a wide range of other objects, not just images.
    4. The child 'figcaption' really does not need many attributes beside 'id', which is critical in associating it with its matching 'figure' parent. Its generally a best practice today to use ARIA attributes to assist the blind and screen readers in locating the correct text describing the visual element. The best way to associate the 'figure' with any visual object in your web page is to add an 'id' attribute to the 'figcaption' tag, then in its parent 'figure' element add an 'aria-labelledby' (ARIA accessibility attribute) with the 'figcaptions' id as its value. This tells the viewer that the figure's text label for the object is provided by the 'figcaption' text below. Your parent 'figure' tag's 'aria-labelledby' attribute will then tell screen readers any objects inside 'figure' are associated with the child 'figcaption' element and its text. To do so, use the ARIA attribute like so: aria-labelledby="myfigcaptionid"
    5. Why Use 'figure' at all? Images and videos are often difficult to interpret for the blind. Most developers provide an 'alt' or 'title' attribute on those items to assist screen readers in interpreting their content correctly. The 'title' attribute on the 'img' element offered web page viewers rollover text prior to clicking an object, or for a small set of alternate textual info about the page item beyond its visual information. The 'alt' placeholder text for images was also used as a replacement for information about an image as it downloaded, as a placeholder in the page for slow image downloads, or in case the image was missing. Other attributes assisted images and videos in other ways. In the "old days" we used "longdesc" with a URI link on our images to provide a link to more detailed information about the image. But this attribute was not helpful and cumbersome to use. It is now either experimental or deprecated. But none of these attributes truly added reliable, rich textual information about the visual objects in web pages for screen readers. The 'figcaption' now directly identifies itself as the primary source for textual descriptions of the object to all users, so is directly related to assisting the blind as well as page viewers. It also avoids the confusion associated with various paragraphs of text around objects which might not be directly associated with them. The 'figure' element can give screen readers all the information they need about your images or objects without confusing the object with other parts of the page. Visual viewers can get added info about the objects embedded in the web page using 'figcaption', and use the text as fallback should the image or video be lost. Use the new 'figure' feature to describe all your page's visual objects, as well as display captions and figures that directly relate the item to the web page's larger content.
    6. Browser Support: 'figure' is new in HTML5 and so has moderate browser support across the full range of more recent browsers. However, all Internet Explorer browsers prior to IE9, and a range of older pre-2008 browsers, will not support it as they do not know what 'figure' and 'figcaption' are. To support older browsers (like IE 8 or older) I've added "display:block" to 'figcaption' since its a new unrecognized HTML5 element with no defined structure. Older browsers that do not know these elements will often default them to "display:inline", pushing caption text to the right of the image and messing up the figure and caption design. Adding a small CSS style fixes it in the sample code above. In general, if you want wider support of figures around objects, consider using a 'div' and 'p' tag with 'id' and ARIA values. But, if you use my sample HTML code above, I do support use of 'figure' element, as it will display well enough in older browsers to be useful,
    7. Note: Below in my section called "How to Display Images in HTML" I demonstrate a non-figure design that can be used to display larger captions that become more like descriptions, if your object needs to share more textual information with the viewer than a simple caption.
    <font> font

    Font

    <font size="3" face="courier" color="#0000ff">This text is wrapped by 'font' tags and should be blue "courier" font if your browsers supports older HTML4 'font' attributes.</font>

    This text is wrapped by 'font' tags and should be in a blue "courier" font if your browsers supports older HTML4 'font' attributes.
    My Recommendations:
    1. The 'font' element is deprecated now and was a member of old HTML4. 'font' was used to change the font size, face, and color of text in your page. It is now deprecated. 'font' was fully supported in ALL browsers prior to 2000 at least, as CSS1 was not implemented in browsers until some time after 1996. 'font' is generally not supported in HTML5 browsers today. For that reason, I do not recommend you use it to control visual formatting in your web pages. Older web pages using 'font' will support the tag, but likely not the font style attributes. Use CSS to format font styles.
    2. Note: Old IE 1-2 (1996) and Netscape 1-3 (1997) were the main browsers using 'font' when styling page text, as they did not yet support Cascading Style Sheets.
    <footer> footer

    Footer

    See also <header>, <nav>, <main>, <section>, <article>, and <aside>
    <footer id="footer" role="contentinfo" aria-label="Footer" >Footer</footer>
    Header
    Main
    Footer
    * A typical web page structure is shown above.
    My Recommendations:
    1. The 'footer' element is new in HTML5 and defines an independent, self-contained piece of page content. It is used for defining a larger block-level area of content in a web page. Typically, the 'footer' element holds supplemental information at the bottom of the web page. In HTML5, the 'footer' is part of a set of new structural page elements that define the overall layout of most HTML5 website pages designed today (<header>, <main>, and <footer>, etc.).
    2. The New HTML5 Structural Elements include: header, nav, main, footer, section, article, and aside.
    3. ARIA: The 'footer' element is a top-level, "self-describing" structure recognized by most modern screen readers without additional assistance. In the case of 'footer', it is recommended you add an ARIA "role=contentinfo" and an ARIA "aria-label=Footer".
    4. See the <main> element section for more details about this new HTML5 element.
    <form> form

    Form

    Shown below, is a complete code sample for the <form> element which you can copy-and-paste into your web projects. It has a complete set of attributes (I recommend), plus an example of every HTML form field element possible in a traditional form. Use it as a template for all your web projects, modifying it as needed. The visual design for this form is shown below the code.


    <form id="f1" name="f1" method="post" action="#" title="Form Example" aria-label="Form Example" autocomplete="off" autocapitalize="off" spellcheck="false">
    <fieldset id="f1_fieldset" name="f1_fieldset" form="f1">
    <legend style="background-color:#999;color: #fff;">Form Example</legend>
    <fieldset id="f1_fieldset_1" name="f1_fieldset_1" form="f1">
    <legend style="background-color: #aaa;color: #fff;">Text Example</legend>
    <p>You can add plain text inside a form.</p>
    </fieldset>
    <fieldset id="f1_fieldset_2" name="f1_fieldset_2" form="f1">
    <legend style="background-color: #aaa;color: #fff;">Login with Submit</legend>
    <div>
    <input type="text" id="f1_username" name="f1_username" size="20" value="" autocomplete="username" autocapitalize="off" autocorrect="off" spellcheck="false" tabindex="0" placeholder="Enter username here..." title="Enter Username" aria-label="Username" required="required" aria-required="true" />&nbsp;*&nbsp;
    </div>
    <div>
    <input type="password" id="f1_password" name="f1_password" size="20" minlength="8" maxlength="12" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,12}" value="" autocomplete="new-password" autocapitalize="off" autocorrect="off" spellcheck="false" tabindex="0" placeholder="Enter password here..." title="Enter Password: (8-12) characters, must contain one number, one uppercase and lowercase letter" aria-label="Password" required="required" aria-required="true" />&nbsp;*&nbsp;
    </div>
    <div>
    <button id="f1_login" name="f1_login" value="Login Submit" title="Login" aria-label="Login" aria-pressed="false" tabindex="0" form="f1">Login</button>
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_3" name="f1_fieldset_3" form="f1">
    <legend style="background-color: #aaa;color: #fff;">Checkboxes</legend>
    <p>Which colors do you like?</p>
    <div>
    <input type="checkbox" id="f1_checkboxgreen" name="f1_checkboxgroup" "autocomplete=off" value="green" title="green" aria-label="green" aria-checked="false" tabindex="0" />
    <label for="f1_checkboxgreen" title="Green" style="color:green;">Green</label>
    </div>
    <div>
    <input type="checkbox" id="f1_checkboxred" name="f1_checkboxgroup" "autocomplete=off" value="red" title="red" aria-label="red" aria-checked="true" tabindex="0" checked="checked" />
    <label for="f1_checkboxred" title="Red" style="color:red;">Red</label>
    </div>
    <div>
    <input type="checkbox" id="f1_checkboxblue" name="f1_checkboxgroup" "autocomplete=off" value="blue" title="blue" aria-label="blue" aria-checked="false" tabindex="0" />
    <label for="f1_checkboxblue" title="Blue" style="color:blue;">Blue</label>
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_4" name="f1_fieldset_4" form="f1">
    <legend style="background-color: #aaa;color: #fff;">Radio Buttons</legend>
    <p>Choose A Favorite Pet</p>
    <div>
    <input type="radio" id="f1_dog" name="f1_radiogroup" "autocomplete=off" value="dog" title="dog" aria-label="dog" aria-checked="false" tabindex="0" />
    <label for="f1_dog" title="Dog">Dog</label>
    </div>
    <div>
    <input type="radio" id="f1_cat" name="f1_radiogroup" "autocomplete=off" value="cat" title="cat" aria-label="cat" checked="checked" aria-checked="true" tabindex="0" />
    <label for="f1_cat" title="Cat">Cat</label>
    </div>
    <div>
    <input type="radio" id="f1_bird" name="f1_radiogroup" "autocomplete=off" value="bird" title="bird" aria-label="bird" aria-checked="false" tabindex="0" />
    <label for="f1_bird" title="Bird">Bird</label>
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_5" name="f1_fieldset_5" form="f1">
    <legend style="background-color: #aaa;color: #fff;">Textarea</legend>
    <div>
    <textarea id="f1_textarea" name="f1_textarea" title="Textarea" aria-label="Textarea" tabindex="0" contenteditable="true" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="true" maxlength="200">Enter your text here...</textarea>
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_6" name="f1_fieldset_6" form="f1">
    <legend style="background-color: #aaa;color: #fff;">File Upload</legend>
    <div>
    <input type="file" id="f1_fileupload" name="f1_fileupload" title="Multiple File Upload" aria-label="Multiple File Upload" tabindex="0" enctype="multipart/form-data" accept="image/*" multiple="multiple" aria-multiselectable="true" />
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_7" name="f1_fieldset_7" form="f1">
    <legend style="background-color: #aaa;color: #fff;">Select List</legend>
    <div>
    <select id="f1_select" name="f1_select" title="Select List" aria-label="Select List" multiple="multiple" size="6" aria-multiselectable="true" tabindex="0">
    <option value="" selected="selected">-- select an option --</option> <option value="1">one</option>
    <option value="2">two</option>
    <option value="3">three</option>
    <option value="4">four</option>
    <option value="5">five</option>
    <option value="6">six</option>
    <option value="7">seven</option>
    <option value="8">eight</option>
    <option value="9">nine</option>
    <optgroup label="ten to twenty" role="group">
    <option value="10">ten</option>
    <option value="20">eleven</option>
    </optgroup>
    </select>
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_8" name="f1_fieldset_8" form="f1" >
    <legend style="background-color: #aaa;color: #fff;">Hidden Inputs</legend>
    <div>
    <input type="hidden" id="f1_hidden1" name="f1_hidden1" value="one" aria-hidden="true" tabindex="-1" />
    <input type="hidden" id="f1_hidden2" name="f1_hidden2" value="two" aria-hidden="true" tabindex="-1" />
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_9" name="f1_fieldset_9" form="f1" >
    <legend style="background-color: #aaa;color: #fff;">Image Button</legend>
    <div>
    <input type="image" src="yourimagebutton.gif" id="f1_imagebutton" name="f1_imagebutton" alt="Image Button" title="Image Button" aria-label="Image Button" tabindex="0" form="f1" style="border:2px solid #bbb;" />
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_10" name="f1_fieldset_10" form="f1" >
    <legend style="background-color: #aaa;color: #fff;">Reset, Disabled, and Read-only</legend>
    <div>
    <input type="reset" id="f1_resetinput" name="f1_resetinput" value="Reset Button" title="Reset Button" aria-label="Reset Button" tabindex="0" form="f1" />
    </div>
    <div>
    <input type="submit" id="f1_disabledinput" name="f1_disabledinput" value="Disabled Button" title="Disabled Button" aria-label="Disabled Button" disabled="disabled" aria-disabled="true" tabindex="-1" form="f1" />
    </div>
    <div>
    <input type="text" id="f1_readonlyinput" name="f1_readonlyinput" size="20" maxlength="20" value="This is Read-only Text" readonly="readonly" autocomplete="off" tabindex="-1" title="Read-only Text" aria-label="Read-only Text" />
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_11" name="f1_fieldset_11" form="f1" >
    <legend style="background-color:#aaa;color:#fff;">Plain Buttons</legend>
    <div>
    <input type="button" id="f1_plaininputbutton" name="f1_plaininputbutton" value="Plain 'Input' Button" title="Plain 'Input' Button" aria-label="Plain 'Input' Button" tabindex="0" form="f1" />
    </div>
    <div>
    <button type="button" id="f1_plainbutton" name="f1_plainbutton" value="Plain 'Button' Button" title="Plain 'Button' Button" aria-label="Plain 'Button' Button" tabindex="0" form="f1">Plain 'Button' Button</button>
    </div>
    </fieldset>
    <fieldset id="f1_fieldset_12" name="f1_fieldset_12" form="f1" >
    <legend style="background-color: #aaa;color: #fff;">Submit Buttons</legend>
    <div>
    <input type="submit" id="f1_inputsubmit" name="f1_inputsubmit" value="Input Submit" title="Input Submit" aria-label="Input Submit" tabindex="0" form="f1" />
    </div>
    <div>
    <button type="submit" id="f1_buttonsubmit" name="f1_buttonsubmit" value="Button Submit" title="Button Submit" aria-label="Button Submit" tabindex="0" form="f1">Button Submit</button>
    </div>
    </fieldset>
    </fieldset>
    </form>
    Form Example

    Form Example

    This is an example of a single form. It has multiple sections defined by 'fieldset' elements which contain different types of inputs, buttons, and content. The form contains a master fieldset which holds all its child fieldsets. Each child holds one example of all the main types of form field controls that can be used in a typical web form. Placing your form fields inside fieldset sections like this allows you to control how parts of your form are filled out and submitted. We could have used multiple form elements, each one wrapped around a single fieldset below, with their own submission button. This would allow each form section to submit its control data to the server separate from the others. Instead, I have created one master form below, which contains multiple sections of fields and their controls, which all get submitted as one. This means any submit button below would submit all the fieldsets as one batch when pressed.

    Text Example

    You can add plain text inside a form.

    Login with Submit

    This is a common use for 'form' elements: Logins. Note the clean, simple design below. You can add more features like "forgot password", "register" links, and elaborate JavaScript techniques. Notice that you should always use the <label> element and its 'for' attribute assigned to the 'input' element's 'id' value. This associates the label with its sibling form field. Also add a 'title' attribute to every label with a description of the form element associated with the label. This improves usability. Ive added a general "submit" button which would submit this data and every other form field below (inside the 'form' element) to the server. The inputs have a few extra attributes, like autocomplete, ARIA labels, maxlength, title, and others I will go over in more detail under 'input' in this HTML5 list.

     * 
     * 
    Checkboxes

    Which colors do you like?

    Radio Buttons

    Choose A Favorite Pet

    Textarea

    The Textarea allows users to submit larger volumes of text. Notice I have added "spellcheck" which means in newer browsers, as you type, any bad spelling added to the textarea box will now have a squiggly line under it.

    File Upload

    Note that "File Upload" controls typically need their own 'form' element and a special 'enctype' attribute added. They usually are also sent to the server with a 'form' attribute of "enctype=multipart/form-data". I have added it to the file upload element instead of the form. I have also customized this file upload element to only allow the user to choose common image formats only for the file upload type. And this version supports multiple file uploads. Note that IE9 and many earlier browsers don't support multiple file uploads.

    Select List

    A select list is also called a "dropdown list" to some. You can set a single select or add the "multiple=multiple" attribute to support multiple choices, as I've done below. I am also using "optgroup" in the 'select' element below to show how items can be grouped, and I have set the "size" or number of items to display to "6".

    Hidden Inputs

    You cannot see these "hidden" input controls as they are not visually shown to the user. These are often used to store "user settings", sessions, cookie info, or other alphanumeric data that needs to be pushed between the server and the user, back and forth. You can also set these special inputs to "disabled". (code shown below)

    <input type="hidden" id="f1_hidden1" name="f1_hidden1" value="one" aria-hidden="true" tabindex="-1" />
    <input type="hidden" id="f1_hidden2" name="f1_hidden2" value="two" aria-hidden="true" tabindex="-1" />
    Image Button

    Note that the "image" button is actually just an <input> element with a "type=image" attribute. They act like "submit" type buttons and will submit all form data as a regular "submit" type input button does. Besides the 'input' element, the 'button' element can also use images as a background and act like an 'image' button. It would not have an 'image' type attribute, just wrap an image with its tags, and use "type=submit".

    Reset, Disabled, and Read-only

    Use the "type=reset" attribute on buttons to create a "reset" button that clears out all fields in a form. Add the "disabled="disabled" attribute on buttons to disable a button and prevent it from posting data back to the server. Add the "readonly=readonly" field for text boxes that have values that are submitted to the server, can be read, but cannot be changed by the user.

    Plain Buttons

    Note that these plain buttons do NOT submit data or do anything without the help of JavaScript!

    Submit Buttons

    "Submit" buttons are default button types used by most browsers to submit all form field data values entered by users back to the server for processing. If you add an 'input' element of "type=submit" it will be a submit button. The "type=image" setting is also a "submit" button for inputs. A 'button' element without 'type' is a "submit" type by default, as well. Setting its "type=submit" is usually what most developers use to make sure it is explicit. Both 'input' and 'button' elements work the same as far as being "submit" type buttons, and post all form field data to the server when pressed.

    My Recommendations:
    1. The 'form' element defines an top-level element that wraps around form fields and buttons. It is used to tell the browser that a collection of data inputs is available for a user to fill out and submit. The 'form' element has been around since the birth of the web and has changed very little over the years.
    2. Form Structure: The 'form' element generally is your starting point for creating interactive forms with inputs and buttons. It must wrap around all your form field child elements, and has many attributes that allow you to control how form fields send their data to the server (see below). But the 'form' element acts like a 'div' element in that by default it has no look-and-feel, acts like a block-level element, and serves no visual purpose other than to collect lots of form fields together for data entry and submission to the web server. Keep that in mind. It is both critical as a wrapper around form fields and buttons, yet has no visual design. In terms of structure, always add the <fieldset> and its <fieldset> element inside your 'form' element. Add all your form fields must reside inside the 'fieldset' element. Remember, you can add nested fieldsets inside each other to allow better partitioning of your form fields, but may not ever nest 'form' elements. In addition, the W3C recommends you wrap all your individual form fields in either paragraphs <p> tags or <div> tags. This gives your form fields structural grouping inside your fieldsets. You can also assign your form fields to unordered lists ('ol'), add headings ('h1') at the top of each set, and use other structural HTML elements inside forms. Note: Because some older Netscape browsers destroyed their forms when 'p' tags were wrapped around form fields, I recommend you use 'div' instead for all your inputs and button form fields wrappers, and use 'p' just for text. (see my code examples above).
    3. Multiple Forms in your Pages: The 'form' element can have multiple forms in a page, one aspect many developers fail to recognize. This allows you to have pages that submit data to different web server locations, have separate sections for complex form processing (like file uploads), and associate different submit buttons with specific forms of data.
    4. Attributes: The 'form' element has many attributes, which I have listed below. There are many others, but these are the main ones that work cross-browser reliably and which you will find useful. Note: I have added many of these attributes listed below to the "form example" above. So, you can copy-and-paste that sample code and get a great example of a form with a full set of attributes ready to use in your application:
      1. 'id' and 'name' - Always use 'id' and a matching 'name' with the same value when possible. The 'id' affects the client-side scripts that must have an 'id' value in order to access the form and all its form field children. If there are multiple forms, this is critical. If you have buttons or inputs outside the form, the "form={id}" attribute tells the browser which form they are associated with. I like to match this 'id' value to the 'name' attribute, as I do in all my form field 'input' elements. The 'name' attribute is what is often sent to the server, and helps your server-side processes identify which form you are processing. If the two values match its very easy to locate and sort client-side from server-side form processes when they use the same value for 'id' and 'name'.
      2. method="get" - This attribute is the default value and optional. It controls how data gets posted to the server via HTTP. HTTP works as a request-response protocol between a client and server. Your form must send data using one of these methods (GET, POST, PUT, HEAD, DELETE, PATH, OPTIONS). The two most common methods are GET and POST.
        GET ("method=get") is the default if you leave off this attribute. It sends your form data using the brower's URL. It is sent via a query string in name-value pairs ('name' and value' attributes of each 'input' element). POST ("method=post") is not the default, but more common in forms. So the "method=post" attribute on forms is more common, and represents a "post of data" back to the server in the HTTP protocol list servers are designed to support and receive from clients. It must be manually set to "post" to send the data over HTTP (hidden form the browsers and user). Only use GET if you are using plain text and smaller, simpler text input data. Otherwise, POST is more adaptable to different types of data, especially file upload data. It also allows you to use different "enctypes" (see below) for things like file uploads.
        Note: There are other HTTP methods, like PUT and DELETE. We often use those as well for specific form submission to narrow processing on the server to one way alterations/additions of data (PUT) or when deleting records (DELETE). It's not really necessary to use those optional HTTP protocols unless your server is specifically designed to respond to these methods with special actions your browser forms must support. Note: Do NOT send type="password" form fields using the default "get" value. Use "post" instead so your password is not shipped over the Internet in full view in the URL string sent to the server. Old browsers struggled with how form data was sent to the server. Example, Internet Explorer v5 would add "+" signs to the spaces in the form field URL string on submission. Often "method=post" is a better, more secure way to fix these issues.
      3. action="{url string}" - This attribute is also optional and controls the URL location on the server where your form will send and receive form data. If you leave this attribute off or blank, your form posts to the same URL as the current web page, which is typical. Thats why in old web form pages there often was no action path or value, as they defaulted to the same page. In the example above I set action="#", which posts back to the same page and avoids a call to the server. You would want to set this attribute to a new URL value if your form needs to push data to a URL that is different from the current page or send the user a response that takes them to a new URL (i.e. move them away from the original web page). That is often the case with login pages, though redirects can replace the need for that. It is more common to leave this attribute off, which then defaults to the same url as the form page. Note: Do NOT ever add query strings to your form "action" URL like so: "action=http://mywebsite.com/?name=JohnSmith". Why? When a form is submitted it will ERASE the query string when "GET" (default value) is used for the "method". When using "POST", your query string will pass to the server correctly in parallel with the form fields which POSt using HTTP headers to the server. But it is not reliable and risks being lost in some older browsers. If you need to pass data this way from a form, do not use a URL and a query string, but use "type=hidden" input types instead. Note: In the old days we would send form results to an email using a "mailto:email@example.com".
      4. autocomplete="off" - "autocomplete" is new in HTML5! This is another optional attribute. It allows forms (or specific form fields) to control whether form field text can be auto-populated with a user's previous text entries from other website pages that have form fields with the same "name" attribute as the current form's "name" attribute. The "autocomplete" value can be a range of custom values, like "name", "email", "tel", "photo", "username", "new-password" (new login/registration page setting), "current-password" (Chrome browser login setting), and others. The most common values are "on" and "off", and most widely supported. This then gives you some control over which previous values for certain text boxes you want to display. The problem is browser support varies by each type. The only other values other than "on"/"off" I do recommend are "username", "new-password", and "current-password" as they will have some security value in controlling choices users may enter in login page input fields. The problem is most of the others have only partial browser support. None have support in Internet Explorer. Do NOT use 'autocomplete' in radio or checkbox type input types. Beside, as we will see, I recommend you rarely allow users to use previous entries. It has less and less value and can be a security risk. So I do not recommend their use. Setting this value to "off" seems more important. Note that "autocomplete" is "on" by default due to the parent form's default value, so will set all fields to allow previous entries by default. That is another reason to disable this feature in the 'form' element, first. If yuou allow the default, modern browsers will allow user the ability to fill out fields with text values from a dropdown of choices that a user has already used before, and so avoid having to re-enter them again. The idea is to save users the hassle of retyping common values, like email addresses, into form fields. If you wish to use this feature just do not add the attribute at all, or set it to "autocomplete=on".
        As I said, I recommend you disable all these fields for "autocomplete" starting at the parent form tag. The problem is "autocomplete=off" often lists previous input text entries for a user regardless of your author settings. In addition, Chrome browsers still do not support "off". So, depending on the browser, it can ignore your settings completely and still try and use previous data based on browser settings. In addition, as a user fills out a form that may have used the same 'name' attribute on another website, they might see a large list of unsecured login usernames and passwords. Because the form's default setting is "autocomplete=on", it allows users to use or see previous entries for commonly named form fields from website to website. It's then possible for other users on a laptop to see another user's login info. Often secured passwords or financial info must hidden. You must prevent users from seeing "autocompleted" options cached in the browser for security reasons, as doing so risks sharing private data with other websites. Using an 'input' of "type=password" with "autocomplete=on" (the default) on the 'form' means listed entries for prior passwords could appear in a dropdown beneath a user's username or password can be a security risk. Many browsers now have turned off "autocomplete" for "password" input types for this reason, by default. Older browsers may not. That is why for this one case, try "new-password" for "password types to disable this feature in some browsers. Nut even that may not be enough!
        I often recommend you turn this feature "off", for all the above reasons and more. To do so, first set "autocomplete=off" on the parent form (other than "new-password" for the "password" input type) if you need all your form fields to require users to enter fresh input data. The text they enter in most modern HTML5 browsers should then always be unique in your web page. But that might not be enough. The best way to permanently disable this feature in forms and fields is to simply create a custom "id"/"name" value each time on your 'input' elements using a unique value like a date concatenated to the field ("name=password_{date}"). Doing so, the browsers cannot cache the previous data, and will have no reference of previous passwords for the user in cache using this technique. It will force "autocomplete" to be off, or show a blank list, and will not show any previous passwords ever again! On the server side, you can create these custom input "named" fields and can still identify and extract the right field from the response coming from the user's browser. When the field's "name" value comes in you simply parse for the first part ("password_{date}") and ignore the rest.
        Note that you can also apply this on an individual input field. An input's "autocomplete" value always overrides the 'form' element values. So, only rely on this setting on the field, not form, as a global attempt at controlling autocomplete settings in all your form fields may fail. Just remember, this attribute is good to set as a starting point in controlling your form, but do not rely on it.
      5. novalidate="novalidate" - All forms naturally validate. No special attributes are needed. "novalidate=novalidate" disables validation in the form and in all child form fields that would normally validate. When form fields fail to validate they create an "error", preventing further submission of data until the data is fixed. Developers often use this "novalidate" attribute to turn off any natural validation by the browser and enable custom script or server validation. However, I recommend you NOT use it, and let the browser help you validate forms. In HTML5, newer browsers now return richer validation of form fields with colored boxes and popup bubble messages to alert users. For some fields, like the new "email" input type, there is even built in "pattern matching" validation for email addresses the browser provides when "required" is set on these form fields. When "novalidate" is missing or not added on a form it means your forms will naturally validate all its form field data, by default. Thats a huge bonus when the newer browsers can help you validate like this! (I have decided to leave "novalidate" off in the code above for demonstration purposes and enable validation, the default).
        As mentioned, in more modern HTML5 browsers, adding the "novalidate" attribute disables HTML5 from trying to validate all form fields regardless of other settings. I do not recommend you do that. The exception is the "formnovalidate" added to 'input' elements and submit buttons which does the same, but forces no validation on a field-by-field basis, which is better. When validation is off like this, all kinds of bad data can and would be sent to the server regardless of errors. This could then cause problems on the server, forcing the server to return to the page with a wide list of errors for the user to address. This is another reason to have very powerful data checks on the server-side for all your data, but also on the client-side.
        Often some HTML5 input fields, including newer ones, like "numeric" and "email", require multiple "checks" in order to be valid. Some text field data must first be present (when the "required" attribute is added). The data values must also be valid in terms of format (email or numeric formats, for example). That is two checks. "novalidate" would stop both checks. Example: Using an input element with "type=email" on an input element will ask the user to type a correct email address format into the text box. If the user submits the form and fails to do this, a bubble message appears in most HTML5 browsers alerting them of a validation error (unless you have added "novalidate="novalidate" to your form). Therefore, adding this "novalidate" attribute disables an important new HTML5 alert feature in today's browsers. So again, I do not recommend you add this attribute.
        Like the "autocomplete" attribute, "novalidate" is not very reliable even when added. For starters, JavaScript validation can override validation or no validation settings on the form. Second of all, many browsers have settings that can stop or enforce form validation regardless of form settings. "password" 'input' element "types" are often overridden or controlled by the browsers, regardless of the form or field settings. In addition, some attributes on individual form fields can also affect or override form validation attributes. But it can also work the opposite. Example: You should know that "validation" is not the same as the "required" form field attribute on individual form fields, which determines if a form field can be left blank by the user. However, when "novalidate" is present on a form, "required" attributes on form fields are ignored, or turned off. So, when you do use "novalidate", all fields with any kind of required validation that potentially stop submissions with missing values are now completely ignored. Empty form fields are then allowed to be submitted to the server. Also, know that the natural validation or non-validation of a form and its fields does not stop hidden input fields with missing or bad data from being submitted, or "disabled" fields from posting data at all, regardless of validation.
        For all these reasons and more, do not rely on "novalidate" or the natural validation of forms and fields to control form validation. Always count on checking data manually on the server as a last resort, but use scripting and the HTML5 validation on the client side as a first line of defense against bad data. If you decide to support scripted validation and manage without HTML5 or the server (I do not recommend this) add "novalidate=novalidate" to the form to turn off validation, then use scripts (like JQuery) on the client-side to check each form field for errors and report issues to users as they fill out your forms. But remember, when it comes to form field validation, always rely on server-side validation code first, regardless of form attributes, client-side scripts, or HTML5 validation! If bad data comes in on the server, and it still has errors, it could cause database issues or worse, SQL injection or hacks that compromise the server!
        Note: The individual form field equivalent of "novalidate" is "formnovalidate=formnovalidate", which can be used on any form field, like inputs, to disable the form's natural validation setting. This is often used if a form does not use the "novalidate" attribute, and everything in a form needs to validate except the specific input field. I prefer this type of setting. It can be used on "submit" buttons when you want to remove validation when certain buttons are clicked, then allow specific from fields to control validation on a case-by-case basis. Or, it can be used when bolting on scripts that capture button events and don't want the browser to report form errors and let the script handle them. It acts like an override, removing form validation. It is the same as a form adding the "novalidate=novalidate" attribute.
        Additional: There are some additional modern browser bugs that come with this attribute. While Safari, iOS, and Android browsers do support the "novalidation" attribute, the form in those browsers is often submitted whether the form validates or not, as if the "novalidate" attribute was always present. In other words, those browsers never validate form fields, anyway, and ignore form field errors! So do not rely on HTML5 browser features such as these, as they are not consistent. Add them as extra enhancements, only. And always rely more on your server-side processing!
      6. enctype="application/x-www-form-urlencoded" - The "enctype" controls how data is encoded when submitted to the server. "application/x-www-form-urlencoded" is the default and the same as using no enctype on forms. A change to the enctype only affects form data when the "method" attribute is set to POST, as all url-encoded data for GET is generally encoded the same. There are three types of form encodings, you can use, however:
        1. "application/x-www-form-urlencoded" - (The default) Using this setting, all data is encoded before sending, with certain characters being converted to lower encoded numerical values. In the old ASCII days, most non-alphanumeric characters were replaced with escapes. In HTML5, this enctype generally converts form field characters to ASCII (first 127 characters) numbers first (which match UTF-8 values), then the rest of the non-ASCII characters into UTF-8. Any non-ASCII characters are also encoded with '%' (percent encoded) using hex value pairs taken from ASCII, then sent to the server. In addition, form control names are separated from their values by '=', and names are separated by '&'. This is the most common format used.
        2. "multipart/form-data" - Only use this if you are posting 'input' elements with "type=file" (file upload controls) and the form 'method' attribute is set to "post". When a user uploads a file using this multipart encoding type, a batch of binary data is extracted from the file by the browser, encoded into compressed hex values, then converted to a type of delimited block set. This binary data set is then sent as a large binary stream to the server to be decoded in blocks and extracted into a binary BLOB or other format on the server.
        3. "text/plain" - This sends form data without any encoding as is. It is rarely used as it sends many non-ASCII characters without encoding. I do not recommend this as it risks sending many types of scrambled non-ASCII or UNICODE data to the server, with many upper-level characters being misrepresented or lost in translation when decoded on the server. It is also less secure.
        The lesson to be gleamed here is, do NOT change the "enctype" unless you are planning to use the 'input' element as a "file upload". Wrap a special form around just that element, if you do, and change the encytpe to "multipart/form-data" in that one case. Leave everything else the default, or even better, just leave off "enctype" entirely. It will use the default value, which is best. You can override the form's "enctype" in an individual form field using "formenctype", but it is not recommend.
      7. target="_self" - 'target' allows you to send the results of a form post to a separate window for processing. In the old days we used "frames" and "framesets" to hold multiple forms and process form data in frames. When posting form data this way, it was possible to process that in another frame or window so users would not have to deal with the results. That is rarely done today. But you might find yourself wanting to process form data in a hidden 'iframe' element which you can still do in HTML5. But, I do not recommend it.
      8. ARIA - When designing forms for accessibility in a screen reader, there is very little you need to add to the 'form' element, as like many top-level HTML5 elements, they are self-describing. So the ARIA 'role' attribute is often not needed, unless your form handles specialized data, like "search", "email", "file" uploads, etc. In those cases, you would need to apply a custom role to your forms. If you have multiple 'form' elements in a page with different purposes, then it might be helpful to add an ARIA label. An example of using ARIA form label attributes might be: "aria-label=Website Login Form". Custom "state" ARIA attributes in forms and form fields is optional (example "aria-pressed" or aria-checked="true"). But it should be used as well as updated by JavaScript if you rely on a stateless scripted API in your website, like Google's Angular or Facebook's React. Because the page never refreshes with new updated HTML on events like submissions in these frameworks, screen readers and the blind have no idea if anything changed in the page or its HTML. So you will need to use JavaScript to update the DOM HTML and its attributes using ARIA "live" attributes when data is changed in the page (I do not cover that here as its beyond HTML). The only other 'input' element "types" you might add ARIA "role" attributes to are for the new HTML5 textbox "types", like "email", "password", "number", "search", etc., or for 'button' and 'input' elements that use "reset", "image", or "file". The latter types might not be described as buttons and confuse a reader when engaged.
      9. title="My Form" - As always, I recommend addition of the 'title' attribute on 'form' elements as it helps some people know what a form does on rollover when inside one of multiple form fields. You can add this to the 'fieldset' tag, as well. I would match these values to the value of your fieldset's 'legend' text value.
      10. Additional Attributes - There are other attributes for the 'form' element not covered here that in general, are either not widely supported across old and new browsers, or not consistent in their implementation. Why use them, then? For that reason, I will not cover those here. Just remember, if it does not work cross-browser its probably not a good addition to your HTML toolkit. In addition, many of the form fields listed above in my code sample also have special attributes based on the parent form field settings. Some affect the parent form's settings or override them. I will cover those under each type of field in this HTML5 list. But in general, they do not affect the basic functioning of forms.
    5. JavaScript Form Submission Tricks - Because 'form' elements control the processing of data sent to the server, JavaScript has for many decades been used to manipulate, massage, validate, show/hide, and control the processing of form field data. Just know these are "substandard" ways to use basic HTML forms and not the norm. Try and use HTML forms as is, but add scripts on top to validate and enhance it, not the other way around. Knowing the basic HTML way to submit data first will help you if you get deeply dependent on these JavaScript API's, later.
      Today, many JavaScript API's now create form fields dynamically (often very sloppily), or bypass form processing completely, hijacking the submit button and sending the data via WebAPI's, REST, SOAP, or by other means. This means form data is often not processed at all using a traditional 'form' element. It just is not "submitted" via HTTP. In these JavaScripted systems, the 'form' element is basically disabled so the data can be sent to the server in other non-traditional ways behind the scenes and prevent a "refresh", which is "evil" (for some reason) to JavaScript developers. I personally think this is lazy design. But it is one wave of the future we cannot ignore.
      When you are thrown into a team doing this type of crazy scripted form processing, it gets confusing as to why the form does not work naturally and what is really happening. The first sign of this type of trick in "hijacked form processing" is when a form "button" control has an event capture script with a "preventDefault()" event processor on it, a "void()" on the "onSubmit" event on a button, or "return false" in the script blocks associated with the form submission. When you see these strange scripts on buttons and forms, know the form submission in the web page has been disabled. All these scripts do the same basic thing......they turn off form and stop the button event that submits the form data to the server. These event capture scripts generally stop the data from going to the server so it can be manually validated by the script internally then shipped to the server manually using "XmlHttpRequest" calls or other special HTTP protocols. (We used these "calls" decades ago when early DHTML was developed. We never dreamed script kiddies would adopt this as a chief technology dependency in these API frameworks!) But, now you know how and why thousands of new web applications today send and receive data from servers this way without use of a real 'form' element. Knowing how things work in basic HTML behind the scenes with heavy scripting like this will help you greatly understand the bigger picture of HTML and how it's often subverted by 3rd party vendors in substandard ways. But just know the old ways will outlast these new ways, as HTML and forms have changed little in over 20 years.
    6. CSS Form Styles - In most cases, the 'form' element does not need styling, as it is an empty semantic element. Almost all the "pretty" designs for form elements you see above in my examples were carefully built using my "Universal CSS Framework" style system, which includes a "reset" sheet that redesigns all the elements, including the form-related ones. If you are interested in recreating this look-and-feel in your form fields, simply copy or download my style sheets from your browser. Note: In HTML5 you can now respond to "required" and "valid" fields using CSS with colored form boxes or custom designs you create for these events. As mentioned above, many HTML5 browsers now display popup bubble alerts if fields are required or invalid and fail. But CSS has added new events using ":valid" and ":invalid" CSS pseudo-classes you can also use in CSS, which respond when form elements inside the form are valid or invalid.
    7. The "data-" Attribute in Form Fields: As mentioned below in my "Best Practices" article called "The New 'data-' HTML5 Attribute", you can now safely use the new "data-" attribute in any HTML form element to store extra data values.
    8. Special Form Issues: Avoid giving forms dimensions or styles, when possible. They are considered empty elements and containers for child form controls. The top-level elements that hold forms are a better place to add styles, colors, borders, etc. Also, use the 'fieldset' and 'legend' inside of forms for design. Avoid wrapping "p" element around any input controls as in Netscape they are treated as containers and the form will fail. Always use 'div' elements instead. You can now use the other server HTTP method types, like PUT, DELETE, etc. when sending form data. Many developers ignored these types in the old days, as they often required custom web server settings to respond to them. But with more control over the server's settings and responses using MVC and other modern frameworks, controllers in these server scripts can now listen to and capture these different types of server methods successfully.
    9. Common Elements Inside Forms: There are several new, "experimental" form field elements included under the 'form' element that are also listed in this HTML5 list, but which are not shown here (like 'datalist' and 'output', for example). There are also a large list of new 'input' element "types" in HTML5 which add new features in forms, but which have spotty browser support in 2022. I left these newer HTML5 form field elements off the 'form' examples shown above as they are still not widely supported, buggy, or require too much scripting. You can read about those new elements elsewhere in this tutorial list. Try and stick with the basic ones shown above and below. They have been around for over 20+ years. See the <button>, <fieldset>, <legend>, <input>, <option>, <optgroup>, <select>, and <textarea> sections of this HTML list for more detail on each of the more common child form field elements available for use in forms.
    <frame> frame

    Frame

    see <frameset> and <noframes>
    <frameset cols="50%,50%">
      <frame src="https://www.w3.org/TR/html4/present/frames.html#h-16.2.1"></frame>
      <frame src="https://www.w3.org/TR/html4/present/frames.html#h-16.2.2"></frame>
      <noframes>
      <p>Alert! Frames are not supported in your web browser. This frame should includes two page views of the W3C website.</p>
      </noframes>
    </frameset>

    * If you do not see anything below, then the 'frameset, 'frame', and 'noframes' elements are not supported in your browser.

    <p>Alert! Frames are not supported in your web browser. This frame should includes two page views of the W3C website.</p>
    My Recommendations:
    1. The 'frame' element is deprecated now and was a member of old HTML4. A 'frame' resides within a 'frameset' and represents a document window or URL of a web page within the larger browser viewport. In the past, frames were a common way to combine, manage, and display many different web pages within a single web page. Many pages in frames could be displayed in the browser this way. It was a very cool concept at first, but over time became difficult to manage and unnecessary. In HTML5, 'frames' and its parent 'frameset' are deprecated, though the 'iframe' or floating frame is still supported in a limited way in HTML5 browsers.
    2. Attributes of Frames: If you do see frames, they always reside inside a 'frameset' parent element. The 'frameset' often defined the percentages of each row and/or column each frame used in the total display. All 'frame' elements included a "src" or source URL attribute, which told the frame what web page to display inside its box. In the old days this could be url and any web page online. This later created a big security risk, as some sites used hidden or tiny frames to hide frames that captured logins from other websites. You often gave your frame an 'id' and 'name' so you could access or manipulate the frame. Adding "scrolling=yes" allowed you to make the frame scrollable. "auto" was the default. "frameborder" was used to provide a border. "noresize" prevented users from grabbing frame borders and changing the size, which was an interesting aspect of frames, as users could customize the display. This latter feature I often used in the old days of page design to allow my users to customize my page's header navigation or hide sidebars. In general, frames and framesets were a bad idea for many reasons, the main one being security, as cross-origin web pages inside the browser window could allow other websites to affect domains in other frames. But to me, frames were not all that bad when used properly. The problem is they were abused and used by some to showcase sloppy web design. That is the real reason they fell out of use.
    3. Do not use the 'frame' element now, as it is deprecated and was a member of old HTML4. HTML5 browsers will no longer support frames. You might try the 'iframe' instead (see below):

      <iframe src="https://www.w3.org/"></iframe>
    <frameset> frameset

    Frameset

    see <frame> and <noframes>
    <frameset cols="50%,50%">
      <frame src="https://www.w3.org/TR/html4/present/frames.html#h-16.2.1"></frame>
      <frame src="https://www.w3.org/TR/html4/present/frames.html#h-16.2.2"></frame>
      <noframes>
      <p>Alert! Framesets are not supported in your web browser. This frameset should includes two page views of the W3C website.</p>
      </noframes>
    </frameset>

    * If you do not see anything below, then the 'frameset, 'frame', and 'noframes' elements are not supported in your browser.

    <p>Alert! Framesets are not supported in your web browser. This frameset should includes two page views of the W3C website.</p>
    My Recommendations:
    1. The 'frameset' element is deprecated now and was a member of old HTML4. A 'frameset' held 'frame' elements which were a document window or URL of a web page within the larger browser viewport. In the past, framesets were a common way to combine, manage, and display many different web pages within a single web page. The 'frameset' replaced the 'body' element when it was used and was seen as a complete replacement for 'body' content. Many pages in framesets could be displayed in the browser this way. It was a very cool concept at first, but over time became difficult to manage and unnecessary. In HTML5, 'frameset' are deprecated, though the 'iframe' or floating frame is still supported in a limited way in HTML5 browsers.
    2. Attributes of Framesets: If you do see framesets in older web pages, they always contain both 'frame' and 'noframe' elements. The 'frameset' often defined the percentages of each row and/or column each frame used in the total display. Over time the 'frameset' element and its child 'frame' elements containing URL's to many web pages became a big security risk, as some sites used hidden or tiny frames to hide frames that captured logins from other websites. You often gave your frameset an 'id' and 'name' so you could access or manipulate the frameset. Also, the 'frameset' contained a 'col' and/or a 'row' attribute with dimensions for all the child frames or framesets inside it. You could design very elaborate page layouts this way using multiple columns and rows, which in turn contained more framesets with frames.
      In general, frames and framesets were a bad idea for many reasons, the main one being security, as cross-origin web pages inside the browser window could allow other websites to affect domains in other frames. But to me, framesets were not all that bad when used properly. The problem is they were abused and used by some to showcase sloppy web design. That is the real reason they fell out of use.
    3. Do not use the 'frameset' element now, as it is deprecated and was a member of old HTML4. HTML5 browsers will no longer support framesets. You might try the 'iframe' instead (see below):

      <iframe src="https://www.w3.org/"></iframe>
    <head> head

    Head

    see <html>
    My Recommendations:
    1. The 'head' element defines the non-content head area of a web page. See the <html> element for a full description.
    <header> header

    Header

    See also <nav>, <main>, <footer>, <section>, <article>, and <aside>
    <header id="header" role="banner" aria-label="Header" >Header</header>
    Main
    Footer
    * A typical web page structure is shown above.
    My Recommendations:
    1. The 'header' element is new in HTML5 and defines an independent, self-contained piece of page content. It is used for defining a larger block-level area of content in a web page. Typically, the 'header' element holds a logo, navigation, and other features at the top of the web page. In HTML5, the 'header' is part of a set of new structural page elements that define the overall layout of most HTML5 website pages designed today (<header>, <main>, and <footer>, etc.).
    2. The New HTML5 Structural Elements include: header, nav, main, footer, section, article, and aside.
    3. ARIA: The 'header' element is a top-level, "self-describing" structure recognized by most modern screen readers without additional assistance. In the case of 'header', it is recommended you do add "role=banner" if used as a top-level element and add an ARIA "aria-label=Header".
    4. See the <main> element section for more details about this new HTML5 element.
    <h1>,
    <h2>,
    <h3>,
    <h4>,
    <h5>,
    <h6>
    heading

    Heading

    An example of a typical "heading" page layout is shown below. This HTML would appear inside the <main> element in the 'body' of your web page:


    <section aria-labelledby="heading1">
    <h1 id="heading1" title="Example of an H1 Heading">H1 Heading</h1>
    <div>
    <h2>H2 Heading</h2>
    <p>text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 </p>
    <h2>H2 Heading</h2>
    <p>Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 </p>
    </div>
    </section>

    H1 Heading

    H2 Heading

    text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1 text 1

    H2 Heading

    Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2 Text 2


    My Recommendations:
    1. The 'h1' element and its siblings (h2, h3, h4, h5, h6) are block-level "headings" (text titles) that appear at the top of web pages. They represent the semantic title of a web page or for a body of text, and usually contain keywords that relate to the content below it. Headings have been around since the birth of HTML and the 1990's, and have changed very little. They are still popular today and used by search engines along with other tags to help identify the subject matter and keywords found in a web page.
    2. The only read attributes needed on headings are the 'id' and the 'title' (tooltip) attribute. Add 'id' if you plan to associate your heading with an ARIA labelledby attribute (see below). The 'title' is optional but nice to have if you plan to provide more info about a section of content defined by the title. Note: Many old HTML attributes are deprecated (like 'align'), so do not use them. Rely on CSS for all formatting of headings instead.
    3. Headings Came from Old Books: Heading elements traditionally have been plain text. They were originally designed to match the old chapter headings found in old books. That design concept continues today, and has not changed much in over 20 years.
    4. Heading Structure: Every web page needs headings! You should have at least a 'h1' heading at the very top of the page. The 'h1' title defines the overall meaning and purpose of the page and its content to readers, to search engines, and to screen readers. So, it has a very important role in page-level structure. For that reason, it often is neglected by web developers who choose to ignore the simple book-like design and purpose of web pages on the World Wide Web today. The Web is primarily used by Humans for reading and gathering text-based information. Multimedia and other properties are always secondary to that purpose.
      For this reason, each page should have an 'h1' element at the top with keywords in the title that match the web pages text content, then use 'h2', 'h3', etc. to define subsections of your page that enhance the primary subject matter of the page. The top-level 'h1' heading is the most important one, and can be placed either above the navigation in the heading or inside the "main" element as a title heading. Because many modern web pages do not always use heading elements in their navigation because of design issues, you should use CSS to change its placement, design, and use. However, as a warning, you should not use CSS tricks like "visibility" or hide the "h1" title to make your page look sexier without headings as search engines will punish you in rank for that! One strategy is to place 'h1' element and its text inside the page's default home link or image at the top of the page, and add text that summarizes the subject matter of your complete website. A better strategy is to simply add a 'h1' title above each page in your site, above you text content, as it was originally designed to do. Always add sub "headings" in smaller subsections of your page, as they too enhance your pages and make them more readable by your users.
    5. Search Engines and Headings: The 'h1' element is used by search engines to identify content, its primary subject matter, and to define important content sections in pages it needs to parse. For that reason, headings have a powerful influence over how pages are indexed by search engines (like Google) and what keywords define a page of text. It is always a good idea to match the meta "title" element's values and "description" keywords with the "h1" title in the page so they are in sync. Often search engines will parse metadata first, parse the headings next, then lastly parse the text to gather information about keywords and the purpose of your content. They do this to build better indexed pages online so millions of people can consume valuable data about a particular subject more quickly online. All that is driven primarily by text! Use headings to help users and search engines determine "document structure" as well, the primary content of a page, and its dominant subject matter. If your web page's text then discuss the same keywords and subject matter with rich, valuable, unique content, search engines will love this and reward you generously with high search engine rankings for many years. The "h1" element starts that process by being at the top of every web page, front and center! Search engines will read the heading text first and give it importance in its indexing bots, if not use it for search titles in its own search listing. This also happens in cases where the meta tag title is absent or not sufficient in a web page, or keyword content is not clear. So if you want better search engine ranking and thus more visitors, do not forget the 'h1' element!
    6. What is in a Name? "heading", as defined by the 'h1' tag, is often confused with the term "header" and "head". It even gets confused with the term "header" or "heading" when describing the stop section of web pages. Below is a breakdown to make all these terms clearer:
      • "head" - This is the <head> element of a typical web page. It represents the non-visible metadata section of a web page above the <body>, or area visible to your users.
      • "header" - This term has been used for multiple meanings. First, it represents the new <header> HTML5 element, that now defines the top structural section of a web page. The term "header" has for years also been used to describe the top section of a web page. But now that meaning is semantically applied to the new element, as well.
      • "heading" - Even I get confused, but know that "heading" ONLY represents the "h" elements that contain page title text. But in the past, many of us have called the "header" or top section of web pages "headings", too. I recommend you erase that idea now that we have a real "header" element. So, the top section of pages and elements are always "headers". And "headings" are simply text title.
    7. ARIA: As mentioned elsewhere, you do not need to apply the ARIA "role" to "h" elements, as they are self-describing. But as shown in the example code above, its now a good idea to map a 'section' element with a 'heading' element (or 'h1') using the "aria-labelledby={h1 id}" attribute. The 'section' adds this attribute with a value matching the 'id' attribute of the 'h1' element. This then tells screen readers and search engines that the definition of that section of the page equates to the top-level heading title inside it. This adds more value to the page, associates a section with its top heading, helps screen readers identify the meaning of the page's content, and gives search engines the association of your page with its section, its title, and its text content. This then improves search engine ranking.
    8. Remember to use the 'h1', 'h2', 'h3', 'h4', 'h5', and 'h6', inside smaller and smaller subsections of your pages. Think of your web page as a book that users will read through and navigate, using your carefully placed headers as guideposts along the way.
    <hgroup> heading group

    Heading Group

    <hgroup>
    <h1>Chapter 1</h1>
    <h2>Intro to HTML Fundamentals</h2>
    </hgroup>
    <p>Page text starts here...</p>

    Chapter 1

    Intro to HTML Fundamentals

    Page text starts here...


    My Recommendations:
    1. The 'hgroup' element was new in HTML5, but now partially deprecated. It allowed the primary heading for a document section to be grouped with secondary headings. Doing so, it removed headings from text and grouped them together at the top of a web page for semantic purposes. Because it is now partially supported in HTML5 browsers, but removed from the W3C recommendations, I do not recommend its use in web pages at this time.
    2. The browser support for 'hgroup' is still decent, but not 100% in newer browsers. In IE8 and older browsers it has no support. I do not recommend use of 'hgroup' due to non-support in HTML5 browsers as well as modern screen readers. It would complicate heading-text associations and thus confuse many browsers and screen readers, alike. Its use was also not necessary, and only useful in formal document structures online.
    <hr> horizontal rule

    Horizontal Rule

    <p>text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </p>
    <hr />
    <p>text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </p>

    text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text


    text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text

    My Recommendations:
    1. The 'hr' element is a horizontal rule that divides text content in a web page from other content. It is a block-level element, so often appears between paragraphs ('p' element) in a web page, and forces content below it on a new line. The horizontal rule has been around since the 1990's and widely used for over 20 years to separate text in web pages. Use it to help you break up all your text, media, form fields, and other content in your web pages.
    2. Its Old Book Design Origins: Horizontal rules contribute semantic meaning as well as design functions in your web pages. By separating content, they tell readers and search engines where content begins and ends in your pages. Rules were created as a way to duplicate the tiny separators found in old books, where a narrative often broke away from the larger context. This often confused readers, so a marker was used between text in the page to tell the reader of the shift in narrative, story, or tone. The horizontal rule has gradually moved from a simple literary design concept to separation between larger blocks of text and page content. As such, it is a powerful tool to separate various types of text, media, form fields, and other page structures in websites.
      Many young developers never use horizontal rules, so miss out on a powerful element used in millions of web pages. It is still a powerful structural tool in your HTML toolset. The rule is also friendly with search engines, who will identify separation of content and ideas and use them to partition valuable content from media that may not be as important.
    3. What is the Right HTML5 Structure for the 'hr' Element? As always, the great debate by newbies online demanding we use "void" HTML5 elements as they were designed continues. Their argument says that any element that has no ending element, is a "void" element in HTML5 and should NEVER have an end tag (example: <source>). They then apply this argument to a whole host of HTML elements, like 'img', 'hr', and others. I disagree! The horizontal rule is no different! They argue the <hr> format is the right format now in HTML5, and should not indicate it has ended. But they are WRONG! You should ALWAYS design your HTML5 to avoid this "void" design and add a forward slash at the end of your horizontal rule element like so: <hr />. This is completely acceptable in HTML5, as HTML5 is now a living standard that accepts all types of formats and changes, unlike the W3C recommendations which were more enforced. Using my HTML rule allows your pages to match XHTML/XML standards, allows your HTML to be read faster and cleaner by 3rd party parsers, improves the DOM manipulated by JavaScript, and best of all actually "ends" the horizontal element correctly! The "void" version does not, and spreads inconsistency throughout your websites. As you write thousands of web pages over time, making sure all your HTML is XML-friendly with ending "/" characters means your HTML is now robust, consistent, cross-compatible with multiple standards, fully XML-compatible, and best of all CORRECT!
    4. See my section called "Use Horizontal Rules (hr) when Separating Content" below for additional details.
    <!doctype>,
    <html>,
    <head>,
    <title>,
    <meta>,
    <body >
    doctype, html, head, title, meta, body

    HTML

    I have decided to cover all the major HTML "framework" elements in one section so you can see how they create the modern HTML5 page when combined. They include the following: <!doctype>, <html>, <head>, <title>, <meta>, <body>, plus the "doctype" definition tag <!doctype html> that goes at the top of the page. Combined, these elements are required in all legacy and modern web applications, and define your current web page as HTML5.

    I have created a "bare bones", basic HTML template below with recommended values and meta tags I recommend you use in all your HTML pages. You can cut-and-paste it into any blank page and use it as a solid HTML5 starting web page template. Just change the values in the attributes for your specific requirements. All other elements listed in this tutorial would appear inside either the <head> or the <body> elements shown below. Note: The 'meta' elements used can include many more than is shown here, or far less, if you choose. Most HTML5 parsers in browsers will assume values for most of these meta tags, anyway, so most are optional. See my list of required meta tags in the section below.

    If you want a full featured HTML5 template with all the other HTML "goodies" included, like "external" CSS style sheets or JavaScript links used in this section, visit my section below called, "My Complete HTML5 Template".

    Basic HTML Web Page Template Code

    
    <!doctype html>
    <html xml:lang="en-us" lang="en-us">
        <head>
            <title>Your Website Title</title>
            <meta http-equiv="content-type" content="text/html; charset=utf-8"
            <meta http-equiv="content-style-type" content="text/css; charset=utf-8;">
            <meta http-equiv="content-script-type" content="text/javascript">
            <meta name="viewport" content="width=device-width,initial-scale=1.0,shrink-to-fit=no">
            <meta http-equiv="x-ua-compatible" content="ie=edge"> 
            <meta name="keywords" content="keyword1, keyword2, keyword3">
            <meta name="author" content="Your Name, https://yourwebsite.com/">
            <meta name="description" content="Your Web Page Description, author Your Name 2022">
    
            
            <meta name="copyright" content="© Copyright 2022, Your Name | All Rights Reserved">
            <meta name="classification" content="business">
            <meta name="rating" content="general">
            <meta name="revision" content="1.0">
            <meta name="distribution" content="global">
            <meta name="resource-type" content="document">
            <meta name="doc-class" content="Living Document">
            <meta name="document-type" content="Public">
            <meta name="document-rating" content="General">
            <meta name="robots" content="all">
            <meta http-equiv="pragma" content="no-cache">
            <meta http-equiv="cache-control" content="no-cache">
            <meta http-equiv="expires" content="0">
        </head>
        <body text="black" bgcolor="white">
        ...
        </body>
    </html>
    
    My Recommendations:
    1. The 'html' element represents the "root" of an HTML web page. As such, it defines your web page as a Hypertext Markup Language document. This element has been the root of all HTML websites since the birth of HTML in the 1990's. Very little has changed with this element and its children, beyond the addition of a few added meta tags. There are several other elements besides 'html' that are needed to structure a modern HTML5 web page. I will cover those elements below.
    2. Modern Structure of an HTML Web Page: Over the past two decades we have seen the rise of HTML, XHTML, and now their newest cousin, HTML5. But the overall structure of markup has not changed much. I will not cover the history of the 'html' element or the various recommendations and standards. That is a long story. Rather, I want to just talk about the main structural elements that define the modern HTML5 page, and how best to design your pages using HTML. It is very simple. For more detailed discussions of various meta tags or items in the 'head' or 'body' elements of your web pages, please see my "Best Practices" section below:
      • <!doctype html> - This truncated, "incomplete" DOCTYPE version for HTML is now required in all HTML5 pages and defines your document as a "true" HTML5 document. As a result, you MUST use this code at the top of every web page if you want browsers to define your pages as HTML5. The newer web browsers will generally assume you are always using HTML5 by default. But, older browser will not. Most older browsers will default to an older form of "tag soup" HTML, or "quirksmode" HTML, when they see this unusual doctype at the head of your web page. What is defined at the top of the web page often controls the type of HTML used by the older browsers, like IE6. This was known as "doctype switching" in the old days. Keep in mind that most browsers created after 2010 also still support some form of doctype switching, but will generally know HTML5, which is likely 90-99% of most browsers viewing your website in 2022. Many browsers created before 2010 knew XHTML, however, which relied on doctypes as well to define their XHTML applications as a form of XML. That means many browsers created after, say 2001, may try and use their "switching" abilities to use the HTML5 DOCTYPE and interpret your web page as a form of invalid XHTML. That is generally ok, as we are not worried about validation in HTML5. Remember, its a "sloppy" standard and very forgiving in many older browsers, allowing many forms of HTML to be used that likely are still valid in XHTML and HTML4 browsers. There is an "XHTML5 Polyglot" DOCTYPE you can use instead, if you are truly interested in supporting XHTML in these older agents. I do not cover that here as its a subtype of the same HTML. Because many older XHTML-friendly web browsers use DOCTYPES in general to define whether a page is XHTML/XML friendly or plain HTML, this "partial" HTML5 DOCTYPE format might trigger some older agents to parse the page as XHTML rather than "tag soup" HTML. Because most web servers, however, rarely delivered true XHTML pages as XML, in the strict sense, these pages would likely fall back to HTML. The HTML tags supported between HTML4 and XHTML1.1 are close to the same, anyway. (My "best practices" section in this page covers a way to make sure your HTML5 works in XHTML5 by using XML-friendly code, btw.) So my point is, do not worry about these issues in older browsers and the HTML5 DOCTYPE. By following my recommendations in this tutorial, your code will work GREAT if one of these older XHTML browsers were to try and parse your page as XHTML/XML using this doctype. Because most would not accept an "incomplete" DOCTYPE as HTML5 uses, its likely they would fall back to a form of HTML4.1, in most cases. But, just realize DOCTYPES for decades have factored into how older browsers interpret what flavor of HTML you are using. But, know that the majority of the time, because none of the older browsers will know what HTML5 is, they will just consider your web page "tag soup" HTML, using the server's default HTTP content-type of "text/html" to define the page as generic HTML.
      • <html xml:lang="en-us" lang="en-us"> - 'html' is the root element of every website, HTML5 included! As such it defines your page to user agents and browsers as HTML. This includes all the older versions, like HTML3.2 and HTML4.1. Using the HTML5 DOCTYPE mentioned above in combination with this root element, your pages are recognized as HTML5 by the nearly all user agents online today. In the past, there have been several attributes added to 'html' tags to help browsers define the language the page is using. "lang" was the main one. Because different browsers come with so many encoding types, Unicode layers, legacy encoding sets, and numbering schemes for characters, its important you always assign a language used (lang="en-us" for US English). This then helps browsers and search engines interpret or "decode" your web page and its character sets better. It also helps them determine if they do not support a given language used in your web page. Because HTML5 uses UTF-8 by default, it will support all of Unicode and a million or more text encodings and hundreds of language sets, emoticons, etc. used around the world. These browsers also are good at "sniffing" the language used. You can leave off the language attribute for that reason, but I do not recommend it, especially if your page is in a non-English speaking language. The reason is the characters used might not be supported in countries or browsers for some users. There may be mis-interpretations between closely aligned languages, as well. In XHTML, an "xml" version of the "lang" attribute was added and is also optional. I added it here so your pages are XHTML-friendly.
      • <head> - The 'head' element holds all the meta data for your page and any preprocessing of external files, styles, or scripts required by the page. These include all non-visual design elements in the web page.
      • <title> - The 'title' element appears directly under the parent 'head' element and should come first before all other elements. It is used by browsers to display the title of your web page in tabs, bookmarks, shortcuts, etc. in the browser. You may see your title appear in the browsers tab text, for example. It also is used by search engines in both their search application titles in search listings and also for determining keywords used in the page when they build page rank. If your website's title has text and keywords that also appear prominently in the subject matter of the web page (i.e. headings and text), then the 'title' element can assist in providing better search engine rankings for your page.
      • <meta> - "Meta tags" have been around since the 1990's and have changed over the years in type, variety, volume, function, and affect in websites. Because of these changes, the meta tags I have listed in the code above are all optional. None of them are required for your website to function. Only a few are highly recommended, though not critical. If you avoid using the handful that are required, you might see small, very minor effects in how your website is displayed or function in some devices, search engines, or browsers. But none are critical, in my opinion. I have listed the important ones I recommend you use, below:
        • <meta http-equiv="content-type" content="text/html; charset=utf-8" />
          This is the "version" of "charset" I recommend you use, though HTML5 standards people say to use <meta charset="utf-8">. I disagree, as the first version above supports a wide range of old and new browsers. As mentioned, when you use the HTML5 DOCTYPE mentioned above, the browser will assume your HTML5 page uses UTF-8 Unicode encoding. But older browsers will not. So, adding this value here helps them more than newer browsers. Encoding is how a document is saved in terms of the numbers representing characters and the byte sequence used to store them in memory or in the saved document. Over time, we have moved from ASCII in 8-bit to Unicode which holds ASCII and over a million additional characters. But most software today does not default to saving in Unicode, so much of what is saved in HTML pages is still using older encoding. The good news is ASCII, or all the English numbers and characters, translates perfectly into HTML5's UTF-8 unicode standard without any special requirements. It's when you start using foreign languages or special characters in web pages that you might see problems and might want to check how you encode your web pages. Because older browsers do not know HTML5 and its UTF-8 default encoding platform, they will not know to use Unicode when translating your web page. That is why you need this special required meta tag. When using this "charset" tag, do remember to place it right after the 'title' element at the very top of your 'head' element (in first 1024 or 256 bytes of page byte code), as the earlier browsers see the encoding type, the faster they parse your page. Web Servers send text in blocks, so that explains the memory limit values and why its critical you send this in the first bit of code from the server. UTF-8 is always the standard for HTML5 anyway, but this tag helps enforce that fact to all browsers and user agents that parse your web page. In most cases, as I describe in my "Best Practices" section below, browsers use a wide variety of techniques starting with HTTP headers from the server and BOM marks to "detect" what encoding HTML pages, CSS, and script files are encoded in. So, you should not worry too much about all that, as many inexperienced web developers try and convince you that you should.
        • <meta name="viewport" content="width=device-width, initial-scale=1.0,shrink-to-fit= no" />
          This strange little meta tag is one of the rare cases recently where meta tags have made a small comeback to effect millions of web page layouts. I honestly thing it was a dumb idea to go back to old technology and use this. In most cases you still do not need this meta tag. This new "viewport" feature is used for various mobile device display settings, though most of this is controlled by either CSS or server side detection and reformatting via CSS. The "viewport" is not a new term but means any screen or monitor representing the user's visible web page area. It varies with the device and will be smaller on a mobile phone or tablet than on a computer screen. This meta tag gives the browser, and especially newer smart phones and tablets, instructions on how to control the page's dimensions and scaling relative to your HTML page. This is important, as some devices have settings that start out in a zoom mode, a direction, a width, or some scale that is not typical or the default. You always want to try and tell these devices or browsers to start with the "default" viewport settings. In the "content" settings above, I have chosen values I recommend you always use, as they basically "reset" the device or the browser on the device to start with a default width that matches the max width of the screen, turn off all scaling or zoom, set a 1:1 ratio as far as scale for your web page display, turn off "shrink-to-fit" web page features in iPhone Safari, and set all Internet Explorer browsers starting with IE7 to always use the "Web Standards" browser engine in those browsers, never the older "quirksmode" version, when displaying your site. I know there is a lot of stuff hidden in all these crazy settings and things you want to customize. But just try and trust my code above to help take care of a lot of the potential problems in all these various devices and browsers.
        • <meta name="keywords" content="keyword1, keyword2, keyword3" />
          As mentioned in my meta tag "History" below, this keyword tag really carries very little weight when it comes to search engine ranking today. But adding specific keywords that are found in the body of your page text here (which follow the subject matter of your page and website), will enhance or rather help search engine performance, as indexing bots do read this meta tag.
        • <meta name="description" content="Your Web Page Description, author Your Name 2022" />
          Add a description for your website here. As above, this is primarily used by search engines who may take this text and using the 'title' tag mentioned in this article, use them for the text they display in their search engine listing for your website. In that case, this element does give your tag some power over how its displayed in search engines. So, use it as much as possible in all pages. Make sure your description does have keywords from the keyword meta tag and 'title' sprinkled in.
        • <meta name="author" content="Your Name, https://yourwebsite.com/" />
          This is a little-used meta tag that allows you to tell search bots and other indexing parsers who the author is of the web page and its content. This really does nothing important, but over time it may help identify you online as the source for critical information that over time has value to the world and is shared by millions of people online. Knowing who or what the source is of that information will be important later. This is an example where "meta data" matters and adds value, though this "author" information may not appear visibly in web browsers.
        • A note on the use of "cache control" using meta tags - I have added three types of cache control meta tags in my recommended code above: "pragma", "cache-control", and "expires". The settings above disable all caching, or try to, in the browser using the settings I have added. I will not cover their meaning or purpose here, except to say that different browsers in the past supported the three types shown here. So, I have added all three. This means, using these tags in older browsers should force them to NOT cache your website and its content and always get fresh data on every call to the server. However, this meta tag "cache" code does not work in most modern HTML5 browsers today. So, do not rely on them. I do not recommend their use except for support of older browsers. That is why for them, I set these to no cache above. For over a decade, these "cache" settings in meta tags worked in many web browsers alongside server HTTP headers to tell browsers when to get fresh web page content and HTML from the server. Caching strategies on the server has been and still is a powerful tool to help browsers not only stay up-to-date on the latest content, but control how often they retrieve that content, saving bandwidth and time. The problem is, meta tag control of that has diminished over time. Today, these techniques rarely work or at the very least are not reliable. So, do not use these tags except as fall backs. Instead, rely on your web server settings when instructing browsers on how to cache your content.
        • There are numerous meta tags many developers swear by and which they say you must use in every web page. I may add those here over time. But for now, read my "History" of meta tags below for my "opinion" on why I recommend you never rely on meta tags and meta data in HTML going forward.

        The History of Meta Tags: In the 1990's, i.e. the "old days", some meta data and their tags were critical in search engine rankings or in controlling features used in web browsers. Others were mandatory in helping browsers parse your page or display various features in your website. So, we adopted a large list of meta tags we would use and began exploring better ways to use meta data in enhancing our websites. After the 1990's, we were very careful in how we used meta tags and which ones were left off. The landscape for meta data was constantly changing back then. Hundreds of meta tags evolved after 2000 and grew to such variety and use that many developers abandoned any kind of consistent use of meta tags. As time progressed, the browsers began creating their own custom meta tags which they encouraged developers to use. But over time, browsers and search engines realized meta data would never replace HTML and good page content, so began to back away from requiring so much meta data. Because of this evolution after 2001, we stopped relying on meta tags for things like enhancing web page displays, refreshing, toolbars, image support, and search engine rankings. They just did not have as much influence over website design or function as before. Even search engines themselves stopped relying on meta tags and meta data, as the content and text in the page is what mattered as time went on. Meta tags "types" like "keywords" and "description" were still parsed and used by major search engines. But they no longer had the dramatic effects on search engine ranking and keywords as they once did in the 1990's. Fewer and fewer of the meta tags that controlled browser features kept working. Most were eventually abandoned. By the end of 2001, the promise of meta tags transforming the web had ended, and the "Golden Age of Meta Data" was gone.
        The "wild west" fun days of meta tag use in web pages is now past. Most tags are rarely parsed or used by user agents or search engines. Most of the real utility tags no longer work. Most of the tricks used in meta tags to trigger browsers to do different things have been replaced with JavaScript. Truly helpful features like "meta refresh" tags that once forced browsers to cycle calls to the server for new content have stopped working or are no longer supported in browsers. Even control of page "charset" encoding values and keyword listings are often "sniffed" in other ways by browsers, assumed to be a default value if meta tags are missing, or determined by server HTTP headers or looked for in the 'body' section of web pages now. HTML, CSS, and JavaScript now dominate control of meta data through the use of new attributes like "data-" or microdata. Even "caching" web page schemes using meta tags no longer work reliably in newer browsers, which instead follow server HTTP header cache values, "sniff" URL changes, use cookies, or implement JavaScript API calls to determine caching now. So my point to you is, do not rely on meta tags to do much in 2022, as they once did 20 years ago. Instead, use good meta tag "mixes" of data in your web sites to "enhance" them, knowing most will affect very little in browsers today. Do rely on good, consistent meta tag use to guide search engines. But rely more on good content. Those search engines that do use your meta data can then get a better idea of what to expect in your pages or what you intended.
      • <body text="black" bgcolor="white"> - The 'body' element contains all your visible HTML elements and page content seen by users online. Anything that needs to be viewed or processed goes in the 'body' element, including some scripting blocks at the end, though the 'head' element is a better place to manage scripting. Note that like all the other elements listed in this section, 'body' is required to create an HTML web page.
        Note the addition of some "outdated" attributes I have added in my 'body' element above. In the old days of the Internet, many browsers did not support CSS and even when they did, still did not support many styles of the 'body' element. This allowed and required the use of many proprietary HTML attributes including the following that are no longer used by modern HTML5 browsers: background, bgcolor, text, bgproperties, margin family, and link family of <body> attributes.
        I generally do not encourage you to use these, as they relate to 1998 browsers and old HTML4 and CSS in the 'body' element has now almost universal support. The "text" and "bgcolor" attributes added above are not supported in HTML5 today. Because I like all my pages to work in ALL web browsers, old and new, even old Netscape, I have added these here to support them. In some rare cases of very old Netscape series 4 browsers, they often defaulted to browser viewports with gray backgrounds and off-color text. Often, CSS or HTML would trigger Netscape to default to black backgrounds with black text, destroying usability. In those very rare cases I like to force Netscape to use black text on a white background using these old 'body' attributes. Know that they do no harm and are cascaded over by CSS in modern browsers when you apply style sheets with CSS properties in the 'body' selector.
    3. If you want a full featured HTML5 template with all the other HTML "goodies" included, like "external" CSS style sheets or JavaScript links used in this section, visit my section below called, "My Complete HTML5 Template".
    <ibobject> backstage object

    Backstage Object

    <ibobject name="backstage_object />

    My Recommendations:
    1. The 'ibobject' element is deprecated but was a non-standard HTML element related to a now deprecated "backstage server" server and web page system. 'ibobject' was mainly used by early Web browsers, like Netscape v3 and Internet Explorer v3. Do not use the 'ibobject' element as it is now deprecated.
    <iframe> iframe, inline frame

    Iframe

    also see <frameset>
    <figure aria-labelledby="iframecaption1" style="padding: .5rem;border: 1px solid #bbb;background: #f0f0f0;width: 400px;height: 300px;display: block;text-align: center;">
    <iframe id="myiframename" name="myiframename" title="Internet Archive Movies" loading="lazy" referrerpolicy="no-referrer" style="width:auto;height:auto;min-width:100%;min-height:80%;" src="about:blank" srcdoc="<!doctype html><html xml:lang='en-us' lang='en-us'><head></head><body style='width: auto;height: auto;text-align: center;background: white;'><p>Welcome to My Iframe!</p></body></html>"></iframe>
    <figcaption id="iframecaption1" style="font-size: smaller;"><a href="https://archive.org/details/TheSpiritOf43_56" target="myiframename" title="Donald Duck Movie" rel="noreferrer nofollow noopener">Load Donald Duck Movie</a><br /><a href="https://archive.org/details/CC_1914_08_31_TheGoodforNothing" target="myiframename" title="Charlie Chaplin Movie" rel="noreferrer nofollow noopener">Load Charlie Chaplin Movie</a><br /><a href="about:blank" target="myiframename" rel="noreferrer nofollow noopener">Load Blank Screen</a></figcaption>
    </figure>

    Notes on My Iframes Example: Notice I have wrapped the 'iframe' element with the new HTML5 'figure' element, like I do with 'video' elements. This allows you to use the caption as a tool to add alternate video URL links. I have also added styles that allows the iframe to expand as the figure expands. It is often difficult to control the iframe size. For that reason stick with styles and use the 'figure' element to control 'iframe' sizes. I am also demonstrating use of a "about:blank" starting page with custom HTML for the source. You can also link to a blank HTML page. The added links inside 'figcaption' are optional and show how you can allow users to load other files, pages, or objects into your iframes.
    Remember, iframes are a security risk to many browsers, so you must limit its use unless you want to add the new "sandbox" or other security attributes, which I do not recommend at this time.

    Load Donald Duck Movie
    Load Charlie Chaplin Movie
    Load Blank Screen

    My Recommendations:
    1. The 'iframe' element is an inline frame element that contains an independent window or URL within the current browser window. The 'iframe' creates a floating document window to an outside web page URL within the larger browser viewport, allowing viewers to see additional content inside the existing web page. The 'iframe' was a member of old HTML4 and supported in the first Internet Explorer browser (1997). And so, it has been around for some time and supported in all the browsers. It was removed from XHTML, however, so still not supported in XHTML5. It is the only "frame" element still supported within the current HTML5 recommendation, however. In HTML5, the old 'frameset' is now deprecated, though the 'iframe' is still supported in a limited way (security limitations) in modern HTML5 browsers.
    2. Attributes of Iframes: I will not cover all the iframe attributes, as most are either deprecated or not supported consistently across numerous browsers, old and new. So, I cannot recommend their use. The main attributes I do recommend are listed below:
      • "src" - Add the URL path to your internal or external source here. This can be a URL to a web page, a file, media, etc. But understand the security risks and get permission when possible before using someones online material inside your own.
      • "srcdoc" - This new attribute is not supported by a wide range of browsers, like Internet Explorer 1-11. So I do not recommend it. But it is a safe "add-on" you can try if you need insert some custom HTML you want displayed into the iframe and you need a starter or blank iframe page. You can use "about:blank" or custom HTML for the value and this is what appears when the page loads, saving your page from having to download external pages at first. I use this attribute in the code same above.
      • "name" - Use a "name" with a matching "id" value. The "id" allows scripts to access the 'iframe'. "name" allows links to access the "src" attribute of the 'iframe' and change it to a new location (see my code example above).
      • "width" and "height" - I recommend use of the "width" and "height" attributes only to reserve space in the browser layout while the page loads. Match those to "width" and "height" CSS values using styles, as you want to always control those dimensions using style sheets. Often the dimensional attributes are ignored in HTML5 browsers on multimedia elements like this. So, always rely on style sheets to control dimensions.
      • allow="fullscreen" - Use this attribute and value if you want your iframe to activate fullscreen mode. To me this is pointless. You might as well just link to the iframe page.
      • loading="lazy" - Use this attribute and value if you want to delay download of the 'iframe' source page until the user scrolls down to view it. This is not supported in IE, Firefox, Opera, and other browsers. So use it as a limited add-on to help your page manage downloaded material in a very limited way.
      • referrerpolicy="no-referrer" - Use this attribute and value if you want to block the external source or server of your iframe file from getting your user's referrer or source information. This blocks the origin data sent to their servers, which shows up in their logs every time a visitor of your web page uses one of the video or files imported into the iframe. Note: If this prevents you from accessing the external file, then you might have to remove it.
      • Use CSS - Always use CSS style sheets to control the border, size, background, scroll bars, margins, and position of your 'iframe'. CSS is far superior in controlling the design of HTML than an element's attributes.
      * Avoid these old, deprecated attributes once used in old browsers (pre-2001): align, frameborder, hspace, vspace, marginheight, marginwidth, scrolling
    3. History of Iframes: The 'iframe' has been around since the 1990's, and is still used today to display independent content inside existing web pages. 'iframe' was primarily an old Internet Explorer element and not supported by old Netscape 4 Series (c. 2000). But over time the 'iframe' element has been used less and less due to security concerns and the demands on browsers when displaying outside media and content like this. The unknowns of cross-domain displays and various media, scripts, and players means 'iframes' like 'frames' open up the user to numerous vulnerabilities online. In addition, many content providers block 'iframe' use of their material, or encourage other forms of displaying them. Some clever 'iframe' websites now use small, hidden frames to hide data processes, capture secret content from users, display advertising, or preload large JavaScript libraries behind the scenes. All are bad web design concepts. Browsers now, by default, disallow iframes to do much inside the browser for security reasons. So many of the benefits of iframes for some has diminished. But use of the 'iframe' element is not all that bad when used conservatively, which is what I recommend you do.
    4. Changing Iframes URL's: You can actually change the location of an iframe's URL externally in HTML by simply adding links. You can see this technique used in my code example above. The anchor tags (link) contain a "target" attribute that matches the "name" attribute of the 'iframe'. Clicking the link sends the "href" URL value of the anchor to the 'iframe' "src" attribute and changes its display to the new 'href' URL value of the anchor. Using the 'target' attribute like this means anchor tags and many other elements can now manipulate what appears in iframes!
    5. Iframes and Host Servers: When adding an 'iframe' element to a web page, when the iframe calls a foreign domain for a URL page, it is designed to be accepted or rejected based on a number of special server checks. This is again for security reasons, but also to stop some from illegally planting copyrighted material into a source page that can pretend to claim or use the material as their own. The 'iframe' in a parent page often sends its own special instructions behind the scenes that tell the source server the page is bound inside another domain or web page as an "x-frame". It will send the server "notes" via an HTTP header saying an iframe is being used and the browser will listen for an "X-Frame-Options" value from the source. Servers can then decide if they will authorize such a use if the parent page is not from the same domain or subdomain as theirs with either "sameorigin" (denial) requirement, "allow-from" (is your site on their list), or a "allowall" (accepted). Often companies block 'iframe' use of their material, so you can get a denial response. To try and bypass this security check and enable some sort of foreign page display of their material, most large sites reject 'iframe' use of their pages and include an "embed" option to iframes instead with instructions. Youtube now does this to stop users from linking to their content inside other web pages without tracking their use or paying for its use. One trick you can also do to improve the chances a foreign server accepts your 'iframe' URL use is remove the "https://" from 'iframe' element URL's (src="//www.youtube.com/embed/..."), which will now make several calls to the server to negotiate a more secure call to their material, and lets them decide if your use of their secure material is allowed and if the parent page allows SSL/TLS, etc. Any such conflicts listed above could block the material coming from the host server inside your 'iframe'! Your 'iframe' will then show a warning or white error page. Again, all this increases the issues surrounding 'iframes' and why, like frames, they are not reliable.
    6. Additional Security Concerns with Iframes: Besides sites now blocking 'iframe' use of their material, there is an opposite problem: Security! 'iframes' often display risky outside URL's of content and various media, so naturally runs the risk of having dangerous scripts in foreign code or hijacked web pages secretly run in your page's 'iframe' and access the browser's primary window. The 'iframe' can then force download of dangerous files or scripts, run plugins, or execute dangerous applications on the user's computer from unknown locations. To prevent this, most modern browsers today now lock down or prevent many type of 'iframe' access to the main windows by default, including blocking many devious foreign processes, like secret file downloads, running unknown scripts, manipulation of content outside the iframe, running dangerous players and plugins, manipulation of same-origin-policy, triggered popup advertising, secret form field captures, click-jack attacks in frames, and more. To enable any of these features now requires the web author add a new attribute called "sandbox" and the "allow-{policy name}" value to their 'iframe' element. This allows you to open up what the 'iframe' can do in a user's browser (Google "sandbox", "iframe", and "allow-" to get a full list of the available settings). Without use of "sandbox", the 'iframe' and its URL page has very limited control over the brower's threads, memory, and execution routines. This is a good thing. By default it means nothing much is allowed and secures the browser when 'iframe' is used to host foreign web pages inside their own. Keep in mind older browsers (IE9 or less, for example) have no such protection. It's also very easy to manipulate this attribute to enable more features and weaken security in the browser. The "sandbox" attribute also adds complexity and uncertainty to secure aspects of the 'iframe' that are not necessary, if not dangerous. Because "sandbox" is required to enable more features in your 'iframe', yet risks changing security in your user's browser, I feel its unwise to use this feature at this time and just leave the 'iframe' default security as is.
    7. Do not use the old 'frameset' element now, as it is deprecated and was a member of old HTML4. HTML5 browsers will no longer support framesets. Stick with the 'iframe' instead!
    <ilayer> ilayer, in-line layer

    In-line Layer

    <ilayer>Text Content Here</ilayer>

    Text Content Here
    My Recommendations:
    1. The 'ilayer' element is deprecated but was a non-standard HTML element supported only by old Netscape 4 Series browsers designed to position elements of content within the main web page flow. The 'layer' and 'ilayer' element in Netscape browsers acted like a form of 'div' or 'iframe' alternative. Do not use this element as it is now deprecated.
    <img> image

    Image

    also see <picture>

    Using Plain Images

    Below is the more traditional way to use images in web pages. If you just need an image to appear in a web page, you can drop in the 'img' element anywhere in your page. Note: The sample code below has a full suite of attributes I recommend you use which will allow your image to perform at its best in various scenarios in HTML.

    <img id="imagexample1" style="border: 4px solid #999;" src="www.jpg" width="255" height="200" alt="image: World Wide Web" title="The World Wide Web" aria-label="Image of the World Wide Web" loading="lazy" onerror="this.onerror=null;" referrerpolicy="no-referrer" />

    image: World Wide Web

    Images With Text that Wraps

    Most 'img' elements are "inline", meaning they flow with text horizontally across the page. Text does not wrap around the image by default but with the image horizontally. This allows you to drop images inside of paragraphs or text and they become part of the flow. Many people want text to flow around images, however, and float inside paragraphs. In most cases, text will not scroll around the image like this unless you change its display to "display:block" and add "float:left" in CSS. In the old days you could avoid this and set the "align:left" attribute on the 'img' element and force text to scroll to the right of it with mixed results. But it was not reliable as the image remained an "inline element" like the text beside it and part of the normal flow of text. I recommend you manipulate the image instead to float as described above using CSS rather than the "align" attributes on the 'img' tag.

    <div style="padding: 1em;border: 1px solid #999;background-color: #ccc;">
      <img id="imagexample2" style="width: 255px;height: 200px;display: block;float: left;margin: 0em 1em 1em 0em;border: 4px solid #999;" src="www.jpg" width="255" height="200" alt="image: World Wide Web" title="The World Wide Web" aria-label="Image of the World Wide Web" loading="lazy" onerror="this.onerror=null;" referrerpolicy="no-referrer" />
      <h5>Sample Title</h5>
      <p>text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </p>
      <p>text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </p>
    <div id="clearingdiv" style="clear: both;"><!--empty--></div> </div>


    image: World Wide Web
    Sample Title

    text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text


    Using Images with the New HTML5 <figure> and <picture> Elements

    Below is the more modern HTML5 way to use the 'img' element. Below I have wrapped the 'img' element in a 'figure' element, then a 'picture' element. The 'figure' element provides a 'figcaption' or text caption for the image, assisting non-visual readers. The 'picture' element provides alternative image formats based on browser support, viewport size, or other checks in the <source> tags. The browser first checks these 'source' elements one at a time, and if the image "type" is supported and/or viewport dimensions match, then the alternate "src" image is passed into the 'img' element below. If none are supported, then the default 'img' tag's image "src" is used. Understand that 'picture', like 'figure', is just a hollow "shell" element and does not do anything other than to group images with these other features, as well as give the 'img' tag alternate image choices. It simply injects alternative image formats into the 'img' element, if the user's browser supports them. So keep in mind, the 'img' element remains the PRIMARY container of the image inside all these other elements.

    The 'img' element below also has a set CSS "style" attribute with variable width and height added to support the possible variable dimensions of the alternate image types assigned by the 'source' elements. It does have "width" and "height" attributes whose values are based on its default image, which the browser should only use if it defaults to its first image. But those will be ignored as each source image with different dimensions is applied.

    So, if you see a "flowering tree" image ("webp" type) below, your browser supports one of the new alternate HTML5 image formats that the picture's 'source' element has assigned your 'img' element. If you see the "weather map" image it means your browser does not understand the WebP image type or failed the "media" viewport check in the previous 'source' element. Finally, if you see the default 'img' element's "World Wide Web" globe image ("jpg" type), the previous two image types failed and your browser only supports "jpegs".

    <figure aria-labelledby="imgcaption3" style="padding: .5rem;border: 1px solid #bbb;background: #f0f0f0;width: auto;height: auto;display: inline-block;">
    <picture id="imgpicture3">
    <source srcset="image.webp" type="image/webp" />
    <source srcset="weather.gif" media="(min-width: 800px)" type="image/gif" />
    <img id="imagexample3" style="width: auto;height: auto;max-width: 100%;" src="www.jpg" width="255" height="200" alt="image: World Wide Web" title="The World Wide Web" aria-label="Image of the World Wide Web" loading="lazy" onerror="this.onerror=null;" referrerpolicy="no-referrer" />
    </picture>
    <figcaption id="imgcaption3" style="display:block;">
    "Which Image Appears?"
    </figcaption>
    </figure>


    image: World Wide Web
    "Which Image Appears?"

    * Note: My host provider does not support "WebP" images I found out, so if no "flowering tree" WebP image appears, it is not the code but my host provider. :(

    My Recommendations:
    1. The 'img' element is an inline media element that displays an image in a web page. The 'img' was a member of the original HTML specifications in the 1990's and has not changed in over 20 years, so is fully supported in all the browsers. In HTML5, the 'img' element has now matured a bit more, and can now be contained within a 'figure' and 'picture' parent element to enhance the image with captions and more advanced HTML5 alternative image formats like WebP, Base64 encoded images, etc.
    2. What is an Image? It has been around since the birth of HTML and web pages in 1990. The 'img' element is actually a "replaced" or embedded element in HTML. Such elements are typically managed outside the web page and generated by the browser. The 'img' display is not really connected to HTML and markup, but added as a special "control" in the web page the browser and operating system manages. The pics and graphic display is a separate part of the browser from the textual markup. Like the 'select', 'file', and 'textarea' replacement elements, image layouts and limitations are often controlled by the browser and cannot always be styled or affected or altered by code or scripts like CSS or JavaScript, either. In older browsers, controlling images in the 'img' tag was sometimes difficult. However, 'img' elements have over the years been more "stylable" than most replaced elements. If you want to see all the COOL ways you can use images and the 'img' element in web pages, see my article below called "How to Display Images in HTML". I cover all the basics of using images in HTML.
    3. Image Element Attributes: I will not cover all the 'img' attributes, as many are either deprecated or not supported consistently across numerous browsers, old and new. The main attributes I do recommend for images are listed below:
      • "src" - Add the URL path to your image on your server here. This must be a absolute path ("/") or a relative path ("../") to your image on your web server using one of the many "image" formats types (jpg, gif, png, bmp, webp, etc.) supported by most web browsers.
      • "id" and "name" - Always add a unique "id" value to your image so you can manage it quickly and consistently by scripts on the client. The "name" attribute has been deprecated for 'img' elements in HTML5, so avoid its use.
      • "alt" - The 'alt' attribute is a text "replacement" for the image when it is slow to appear, fails to appear, or not viewable by the blind in a screen reader. 'alt' text should describe the image if the image contains information that is important to a screen reader. If the image is wrapped in an anchor (a hyperlink) the 'alt' text should explain where the link goes if the image is clicked. You can also use an alt="" blank value if the image is only for decoration. This tells screen readers the image is not important and if its missing, no placeholder will create a empty image box. But always add an "alt" attribute with a simple description of the image in as few words as possible. This text is what will appear inside the image box in your web page if the image is missing for some reason. The role of the 'alt' attribute is critical in all the scenarios described above and more, so I like to use this text format in mine: alt="image: World Wide Web". Note: The alt text should not exceeds 150 characters. Use null "alt" text as in alt="" on images that serve only a structural purpose, which is good for hiding spacers or design images that do not need to be identified. These are hidden from screen readers. Don't use suspicious alt text as follows: alt="photo.gif", alt="234 bytes", alt="image", "graphic", "photo", "photograph", "drawing", "painting", "artwork", "here", "click here", "click", or starts with "graphic of" or "image of". "alt" should apply to any HTML element that represents a visual image of some kind. Every image should have at least an empty alt="", if the image is not important. Lastly, old IE 4-6 had issues with "alt" attributes, where if you left off the "title" attribute, suddenly the alt appeared as a rollover tooltip! This was incorrect. So, that is why every image should always have both attributes. When doing so in old IE browsers, the "title" tooltip will suddenly replace the alt tooltip ad prevent it from appearing.
      • ARIA labels and the "title" - Like the "alt" attribute described above, ARIA label and "title" attributes are vital in allowing both visual and non-visual people to understand your image textually. I like to give a full description for the image in my title. The rollover tooltip that appears then allows users to see more information about the image. If the image is inside a link, its vital you tell a visual person what it is they are clicking before they do so. The ARIA "aria-label" works like title, but is ONLY seen by screen readers. So for them, you just want to identify what the image is, not a provide full description in the label, which they can get from the "title" attribute or using the "figcaption" element text. WARNING: Do NOT duplicate the text in the "text" attribute with what is in the "alt" attribute, as each serve different roles and screen readers may repeat both with the "aria-label" text. Remember, 'alt' as "alternative text" for a missing image, "title" or tooltips are descriptive and additive to the image, and ARIA labels provide information only for screen readers that can never view the image or understand its meaning.
      • "width" and "height" - I recommend you ALWAYS add the explicit "width" and "height" attributes with the image's true dimensions on all images only to reserve space in the browser layout while the page loads. Match those to "width" and "height" CSS values using styles, as you want to always control the final dimensions using style sheets. The style values will override the attribute values, so you can scale images using CSS quite easily. Note: In the old days in older browsers we were able to use the "width"/"height" attributes to expand or shrink the actual true size of images. In HTML5 this causes severe problems now as the recommendation tells browser to focus on the images true dimensions which it uses to calculate an aspect ratio in memory for the image. If you try and enter dimensions that are not the image's true values, HTML5 browsers will ignore your values anyway and use the image's true values anyway.
      • DO NOT USE "srcset" and "size" - "srcset" and "size" on 'img' elements are non-standard attributes and will fail in many old and new browsers, anyway, including all versions of Internet Explorer 1-11. However, in some limited cases you might find it helpful. For now, I RECOMMEND YOU DO NOT USE the "srcset" and 'size' attributes! I recommend you use the new HTML5 'picture' element instead of "srcset" and allow its 'source' element with the 'img' element to control source images and media, instead. Why?
        • 'srcset' - This attribute is new in HTML5. But it comes with numerous bugs and counter-intuitive features I do not recommend. With this new attribute you can now apply "alternative images" to your 'img' elements. This is supposed to be another form of responsive design, delivering several images in various sizes inside the "srcset" attribute. With this feature you are supposed to be able to deliver images based on the width of the viewport of the user's browser. You are letting the browser decide what alternate images to use based on some logic related to available screen width in a user's device and browser. Typically, we do this using CSS style sheets and "media queries", which measure the width of a viewport or uses other conditions to set styles that refit layouts and choose images that fit well into the browser. Often you can switch out images this way and have more control. This "srcset" feature works the same, but on an image-by-image basis which to me is tedious. But if you had multiple versions of a very large, high resolution or PPI image, you could use "srcset" provide alternates at smaller sizes in its "srcset" attribute and save bandwidth via smaller downloads. The user's browser will then switch the image out with the new images as the users screen width increases or decreases. That is the hope, at least. But its not reliable. Though the "srcset" attribute allows you to list multiple images to download based on viewport widths, multiple image size choices often fail to change them from using any of the alternatives if all three will fit into a given viewport. So, it is pointless. Often the browser doesn't know which image ideally works best beyond just seeing if its width will fit, which all threes often will. So nothing really changes. You set this like so: "srcset=255.jpg 255w, 200w.jpg 200w, 100w.jpg 100w". The browser should pick the small images as screen width reduces. You can also use "1px, 2px", etc. instead of the width values, that read the "device pixel" values of the device, then choose images with higher resolutions. Many iPhones, for example, use 2 or 3 pixels per CSS pixel, meaning higher resolution images look better on those devices. But again, you are hoping the browser even knows what the "device pixel" is on a given phone or high-resolution device. Its all pretty dicey to me and not reliable. "srcset" on images was also shown to fail, or be partially supported, on many of the newest HTML5 browsers. Example: in Chrome, even though you set three alternative images with various widths, it rarely picked smaller images in any device viewport, anyway. And when it picked an image it still tried to use the "width" and "height" dimensions of the original 'img' dimensions anyway, not the new one's dimensions, which is bizarre. It just dropped the smaller or larger image into the existing medium image's width and height as set on the 'img' attributes, for example. It should resize itself to the chosen image's new dimensions. When I removed those dimensional attributes on 'img' to try and "coax" it to use the new images actual size, it made the default image as large as the parent block instead (same as setting "size=100vw"), not its actual size. It should always default to the actual image's first size even with the "sizes" attribute removed. Who sets images to viewport width anyway? That just creates blurry, distorted images. So "srcset" failed numerous basic tests for me.
        • The "size" attribute they say must always be assigned if you use "srcset". This attribute allows you to physically change the size of an image larger or smaller from its ACTUAL size to a viewport "stretched" size, away from the image's actual property size. Again, why create stretched, blurry images? Note that "sizes" does not interfere with the "srcset" attribute's image choice. It simply resizes the new image, yet again, which to me is confusing. "sizes" simply allows you to resize that chosen image bigger or smaller relative to the viewport. "size" is also problematic as it alters the image's size to a "viewport size" instead of using or starting with its actual size, when making the new calculations. Some additional confusion with "size" is that often images sit inside a parent block that constrains its dimensions, so resizing is redundant. Why not just use "width:100%" in CSS if you want some viewport stretched image, anyway? On smaller images using say "10vw" or one tenth the viewport width for the images new width, it works ok. But on larger image sizes, say "100vw", it cannot set that value to 100% of the device's screen width as most images are constrained by the parent's width. Example: An image in a 'div' element set to 50% of the viewport width will never allow its child 'img' element to be 100% of the screen width, as in "sizes="100vw", as its constrained to the 50% viewport width of its parent. I also saw "bleed over" of the image outside the box when this event occurred. In addition, setting "width" and "height" attributes on the 'img' tag, as mentioned above, messed with these viewport dimensions and often deleted them. I tested this using "width" and "height" attributes, or CSS dimensions, or even with no attribute dimensions, and "sizes" had variable results honoring or ignoring these values. On "sizes" attributes, you can also use "media queries" to further control image viewport image resizing (this doesn't affect the "srcset" image choice though, which is confusing!) Example: "sizes=(max-width: 800px) 50vw" tells the browser, after choosing one of the three images in "srcset", if the browser window is less than 800 pixels, resize that image down yet again to 50% of the viewport. I find this feature a bit sloppy and poorly thought through. For starters, we used to do this resizing of images manually inside parent containers using "width:50%" in style sheets on the parent container. The viewport width then really doesn't matter. The parent's width matters! We also manipulated this by resetting the "width" and "height" attributes (this "stretch feature using attributes is now disabled in HTML5). So "sizes" destroys the main features of good image size control we used to have which was much simpler and always based on an image's actual "width" and "height".
        • "all:revert" when used on the image element, ERASES the previous or even actual image size, which is lost in the browsers render and paint processes on the DOM, so breaks all use of "srcset" and "size" attributes.
        • ONLY use 'picture element, instead of "srcset" anyway. Because the "media" attribute of 'source' elements offer multiple choices for the browser and works the same as the 'image' "srcset" attribute, but in combination with the more advanced image "type" attribute to help control when image alternatives are chosen, you will get more "predictable" results than using "srcset" and "size". The 'picture' element' also fails gracefully in older browsers, while the 'srcset' has no support in browsers like IE, so will not work anyway.
        But if you want to try "srcset" and "size" together, below is an example of an 'img' element code with those attributes added. Just create three images of different sizes and try scaling your browser window in size to see if it works. Notice, you can offer a comma-separated options list for both alternative image types and a media query for when to apply different sizes of images based on size of the viewport. The browser will use one of these images or the default image in src to start. It will then use one of the widths, like the "640w" value for example, to determine if this sized image will fit "better" into the user's display and reserve space for it. Note that without these explicit widths, it cannot know what dimensions to expect for each image. "sizes" allows you change the width again on your image based on the viewport width. (confused yet?).
        Below is an example of three images for a JPEG image where three image widths are offered (320w, etc.). The browser should first use the image widths to decide which one fits best in the users screen size. It should then use the "sizes" attribute to determine if the chosen image should be resized based on some media query condition related to the device's viewport width or other criteria, and if those conditions are met, resize the image to a new value relative to the viewport width (not the image's). "50vw" should mean the image is sized 50% of the device's screen width (if not in a constraining container!). Note: Its important you include your default image in the "srcset" attribute list below:

        <img id="srcset_image" src="medium.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(max-width: 800px) 50vw" />

      • longdesc - This is a link to a separate file with a description for the image. Use of "longdesc" with a URI link was once used alongside 'title' to provide a link to more detailed information about the image. But this attribute is now either experimental or deprecated. We never used these in the past anyway, as it was overkill. The new HTML5 'figure' and 'figcaption' elements really contain more info on an image and should be enough.
      • loading="lazy" - This attribute is not widely supported by browsers. But for those that do, it adds a valuable way to delay image downloads until the user scrolls down to view the image. At that point, the browser actually downloads the image into the 'img' placeholder element (hopefully with its reserved "width" and "height" attributes set). For image heavy websites, this might be valuable too. I have seen this feature wait to load a large image as you scroll a web page, but the delay cause a "flash" of the image. So, with all sketchy features like this, do not rely on it.
      • referrerpolicy="no-referrer" - This attribute is widely supported by most browsers, except Internet Explorer and some overseas browsers. But for those that do want to use it, it adds a valuable way to show/hide referrer data when calling a foreign image from another server. This applies mostly to cases where you link to an external image found on a foreign server. Often, when you paste a URL to an image from an external website into your web page, when your web page and your user's browsers call the foreign server to download the image, they can read your IP, domain of origin, path used, and other information. In the past this was not important. But to hackers and spammers today in 2022, it can be. If they know an image in an email or website was read by you, they could use your origin information to continue to target you. Most web developers now use large amounts of CDN's and foreign URL's to download external files into their user's websites. These come from numerous external sources. They do not realize that these sources can track your usage or your user's usage of their services via images and files your users constantly download to their browsers when viewing your website. For that reason, I recommend you NOT rely on CDN's for files. However, if you do, you can always set the "referrerpolicy=no-referrer" attribute on all such external or foreign images to stop access to your website origin data. This then tells the external server logs access to their image was a simple Google "direct" or plain link, and hides your user's data and your server path from their logs. The default for "referrerpolicy" is "no-referrer-when-downgrade", which means by default the referrer header info will be sent to them as long as you use HTTPS. Thats very bad! Without adding "no-referrer", all your image path data and origin info is sent to their servers when you create a path to their images or files. For you and your web user's sake, I recommend you always set images with the attribute "referrerpolicy=no-referrer" when using external images, so they have no way to know of the source of these calls. Note: This matches the same feature found in 'a' element links where the "rel" and "noreferrer" attribute value is used.
      • onerror="this.onerror=null" - You know me, I do not like scripted dependencies. But this little extra trick might help some browsers handle issues where images are lost. The script then nulls out the "broken" error icon if the image is slow to download or missing on the server. If an image is not found or is missing, you have a choice: Either let the browser show a broken error image and hopefully your 'alt' attribute text replacement, or use JavaScript to degrade gracefully and hide the error completely. You can use this 'img' attribute trick by adding this: "onerror=this.onerror=null;" or "onerror=this.remove();", which will be applied when an image is missing, corrupted, or slow to download and times out. Because this will rarely occur, its an extra but of HTML code that will not hurt your page, but allow the 'alt' text to appear quicker when an image is missing from the page, while removing the error from the reported list of errors created by the browser. Note: You can also assign a universal fallback image instead, like a transparent spacer or custom error image, if any image is missing in your website. In that case it will show a replacement image. Just add the following to your "onerror" event attribute on 'img' with a path to your default image like so: "onerror=this.onerror=null;this.src='default.jpg';". Update (11/2022): Recent browser updates have disabled 'onerror' script. When a bad image path is detected, the error is thrown, cannot be captured using 'onerror', but is logged in devtools anyway. A broken image icon is then returned in the HTML view. So, my recommendation is to abandon this attribute now.
      * The following is a list of deprecated attributes no longer used by modern HTML5 browsers and the 'img' element: align, border, controls, dynsrc, hspace, vspace, ismap, loop, lowsrc, start, vrml.
    4. Image Figures and Captions - In HTML5, the 'figure' and 'figcaption' elements are now used by modern browsers to wrap around images and add captions beneath then in HTML5. The 'figure' element wraps around the image and the "figcaption" usually appears under it with text describing the image. Most photographic websites, online magazines, or article images carry more visual information in the 'img' element than normal, so require a text caption to connect the image with the article text. So, be sure to add captions when using images in HTML5. See my article below called "How to Display Images in HTML" for a great rundown of how to add rich textual content to your images.
    5. Using Background Images: Background images are becoming more popular, simply because some developers want to trick browsers into delaying download of images by using them as tiled backgrounds in CSS instead. In the past, we traditionally only used background images when needing tiny "tiled" web page wallpaper backdrops or to contain logo headers at the top of web page. If used to show visual queues like photographs in pages, background images in CSS do create a semantic problem. The issue with background images is when used this way they are no longer part of the page layout or page flow, so are "semantically" not viable either for search engine indexing or even viewing in some browsers that may fail to download them. Often block-level elements will collapse, hiding the image. Screen readers certainly would not have a way to know about these visual queues like they would traditional images in 'img' tags with 'alt' attributes. I discuss the right way to use background images elsewhere in this tutorial, though I rarely support their use.
    6. Images Inside Links - In the old days, we liked to use images with anchor tags wrapped around them, creating powerful "image links" or buttons from page to page. Weird browser issues occurred, however, like the strange blue borders around images in Netscape 4 which were hard to remove (see my <a> element recommendation above for two ways to fix this using "border:0" and adding "width" and "height"). Over time, use of image links like this have faded as far as use cases. But keep in mind, you can still do this trick. Just make sure you use enough CSS, tooltips, and figure captions on the image to design it properly and to tell users the purpose of the image link before they click on it.
    7. Compressed Images and Faster Page Loads - There is no doubt that in 2022 most developers have lost the knowledge needed to compress JPG, GIF, PNG, or other image formats. I see HUGE uncompressed images and photos all over the Web today. By compressing images and limiting color palettes, you can greatly speed up the download of your web pages just as reducing the megabytes of JavaScript downloaded can speed up pages. We learned how to compress images using limited color palettes (like Netscape's "Web Safe" 216 palette for GIFs, minus 40 colors reserved for the Netscape logos) and LOSSY JPEG photos compressed by image programs like Adobe's "ImageReady" 20 years ago. Developers today have completely forgotten how to do that. So instead, they've created bloated images that are never compressed or ever use reduced image palettes. This can save gigabytes of downloads over years. Remember, bandwidth costs big bucks! But you can shave off megabytes of data per page download alone by reducing your image sizes using compression and limited palettes. So please consider doing that using image software.
    8. Images and CSS - Always use CSS style sheets to control the display, width, height, border, background, padding, margins, visibility, and position of your 'img' elements. CSS is far superior in controlling the design of HTML than an element's attributes.
    9. For more advanced examples using the 'img' element and new 'picture element, see my two articles below: "How to Display Images in HTML" and "The New Picture Element".
    <input> input

    Input

    see <form> for more details using <input> in forms

    Shown below is a complete code sample of the <input> element, which you can copy-and-paste into your web project. It has a complete set of inputs by "type", along with a rich set of attributes I recommend you use for each scenario. The visual design for this form is shown below the code. With these examples you have a complete set of inputs you can use in your web forms.

    <form id="forminput" name="forminput" method="post" action="#" title="Input Example" aria-label="Input Example" autocomplete="off" autocapitalize="off" spellcheck="false">
    <fieldset id="forminput_fieldset1" name="forminput_fieldset1" form="forminput">
    <legend style="background-color:#aaa;color:#fff;">Input Types List</legend>
    <div>
    <input type="text" id="forminput_text" name="forminput_text" size="20" value="" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" placeholder="Enter text here..." title="Enter Text" aria-label="Text" tabindex="0" required="required" aria-required="true" />
    <label for="forminput_text" title="Text">Text</label>
    </div>
    <hr />
    <div>
    <input type="password" id="forminput_password" name="forminput_password" size="20" minlength="8" maxlength="12" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,12}" value="" autocomplete="new-password" autocapitalize="off" autocorrect="off" spellcheck="false" placeholder="Enter password here..." title="Enter Password: (8-12) characters, must contain one number, one uppercase and lowercase letter" aria-label="Password" tabindex="0" required="required" aria-required="true" />
    <label for="forminput_password" title="Password">&nbsp;*&nbsp;Password</label>
    </div>
    <hr />
    <div>
    <input type="button" id="forminput_button" name="forminput_button" value="Button" title="Button" aria-label="Button" tabindex="0" aria-pressed="false" form="forminput" onClick="JavaScript:alert('::: This Button Type only works with Added JavaScript :::');return false;" />
    <label for="forminput_button" title="Button">Button</label>
    </div>
    <hr />
    <div>
    <input type="submit" id="forminput_submit" name="forminput_submit" value="Submit" title="Submit" aria-label="Submit" tabindex="0" aria-pressed="false" form="forminput" />
    <label for="forminput_inputsubmit" title="Submit">Submit</label>
    </div>
    <hr />
    <div>
    <input type="image" src="imagebutton1.gif" id="forminput_imagebutton" name="forminput_imagebutton" alt="Image Button" title="Image Button" aria-label="Image Button" tabindex="0" aria-pressed="false" form="forminput" style="border:2px solid #bbb;" loading="lazy" />
    <label for="forminput_imagebutton" title="Image">Image</label>
    </div>
    <hr />
    <div>
    <input type="reset" id="forminput_reset" name="forminput_reset" value="Reset" title="Reset" aria-label="Reset" tabindex="0" aria-pressed="false" form="forminput" />
    <label for="forminput_resetinput" title="Reset">Reset</label>
    </div>
    <hr />
    <div>
    <input type="file" id="forminput_fileupload" name="forminput_fileupload" tabindex="0" enctype="multipart/form-data" accept="image/*" multiple="multiple" aria-multiselectable="true" title="Multiple File Upload" aria-label="Multiple File Upload" />
    <label for="forminput_fileupload" title="File">File</label>
    </div>
    <hr />
    <p>Checkbox</p>
    <div>
    <input type="checkbox" id="forminput_checkboxgreen" name="forminput_checkboxgroup" "autocomplete=off" value="green" aria-checked="false" tabindex="0" title="green" aria-label="green" />
    <label for="forminput_checkboxgreen" title="Green" style="color:green;">Green</label>
    </div>
    <div>
    <input type="checkbox" id="forminput_checkboxred" name="forminput_checkboxgroup" "autocomplete=off" value="red" aria-checked="true" tabindex="0" checked="checked" title="red" aria-label="red" />
    <label for="forminput_checkboxred" title="Red" style="color:red;">Red</label>
    </div>
    <div>
    <input type="checkbox" id="forminput_checkboxblue" name="forminput_checkboxgroup" "autocomplete=off" value="blue" aria-checked="false" tabindex="0" title="blue" aria-label="blue" />
    <label for="forminput_checkboxblue" title="Blue" style="color:blue;">Blue</label>
    </div>
    <hr />
    <p>Radio</p>
    <div>
    <input type="radio" id="forminput_dog" name="forminput_radiogroup" "autocomplete=off" value="dog" aria-checked="false" tabindex="0" title="dog" aria-label="dog" />
    <label for="forminput_dog" title="Dog">Dog</label>
    </div>
    <div>
    <input type="radio" id="forminput_cat" name="forminput_radiogroup" "autocomplete=off" value="cat" checked="checked" aria-checked="true" tabindex="0" title="cat" aria-label="cat" />
    <label for="forminput_cat" title="Cat">Cat</label>
    </div>
    <div>
    <input type="radio" id="forminput_bird" name="forminput_radiogroup" "autocomplete=off" value="bird" aria-checked="false" tabindex="0" title="bird" aria-label="bird" />
    <label for="forminput_bird" title="Bird">Bird</label>
    </div>
    <hr />
    <p>Hidden</p>
    <div>
    <input type="hidden" id="forminput_hidden1" name="forminput_hidden1" value="one" aria-hidden="true" tabindex="-1" />
    </div>
    <hr />
    <p><strong>Special Input Attributes</strong></p>
    <div>
    <input type="submit" id="forminput_disabledinput" name="forminput_disabledinput" value="Disabled Button" disabled="disabled" aria-disabled="true" tabindex="-1" form="forminput" title="Disabled Button" aria-label="Disabled Button" />
    <label for="forminput_disabledinput" title="Disabled Button">Disabled Button</label>
    </div>
    <div>
    <input type="text" id="forminput_readonly" name="forminput_readonly" size="20" maxlength="20" value="This is Read-only Text" readonly="readonly" autocomplete="off" tabindex="-1" title="Read-only Text" aria-label="Read-only Text" />
    <label for="forminput_readonly" title="Read-Only Text">Read-only Text</label>
    </div>
    <div>
    <input type="text" id="forminput_required" name="forminput_required" size="20" maxlength="20" value="This is Required Text" required="required" aria-required="true" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" tabindex="0" title="Required Text" aria-label="Required Text" />
    <label for="forminput_required" title="Required Text">&nbsp;*&nbsp;Required Text</label>
    </div>
    <div>
    <input type="text" id="forminput_states" name="forminput_states" size="2" minlength="2" maxlength="2" value="" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" tabindex="0" title="Please Enter a US State Code (2)" aria-label="Pattern Attribute Text" pattern="[A-Za-z]{2}" />
    <label for="forminput_states" title="States">Pattern Text</label>
    </div>
    <div>
    <input type="text" id="forminput_hidden" name="forminput_hidden" size="20" maxlength="20" value="This is Hidden Text" hidden="hidden" autocomplete="off" tabindex="-1" title="Hidden Text" aria-label="Hidden Text" />
    </div>
    <hr />
    <p><strong>Non-Recommended Elements that Use 'input'</strong></p>
    <div>
    <input type="text" id="forminput_datalist" name="forminput_datalist" value="" size="20" maxlength="20" tabindex="0" list="forminput_list" placeholder="Double-click to choose..." title="Double-click to Choose" aria-label="Fruit" />
    <datalist id="forminput_list" title="Fruit List" aria-label="Fruit List" role="listbox">
    <option value="apple"></option>
    <option value="orange"></option>
    <option value="pear"></option>
    <option value="grape"></option>
    <option value="banana"></option>
    </datalist>
    </div>
    <div>
    <input type="range" id="forminput_range" name="forminput_range" value="50" min="1" max="100" minlength="1" maxlength="3" tabindex="0" autocomplete="off" title="Slide the Range Indicator" aria-label="Slide the Range Indicator" /> +
    </div>
    <div>
    <input type="number" id="forminput_number1" name="forminput_number1" value="0" min="1" max="100" minlength="1" maxlength="3" tabindex="0" title="Number" aria-label="Number" /> =
    </div>
    <div>
    <output id="forminput_output1" name="forminput_output1" for="forminput_range forminput_number1" tabindex="0" value="0" title="Number Output" aria-label="Number Output"></output>
    </div>
    <hr />
    </fieldset>
    </form>
    <form id="forminput2" name="forminput2" method="post" action="#" autocomplete="off" autocapitalize="off" spellcheck="false" title="New HTML5 Input Types" aria-label="New HTML5 Input Types">
    <fieldset id="forminput2_fieldset" name="forminput2_fieldset" form="forminput2">
    <legend style="background-color:#aaa;color:#fff;">*New HTML5 Input Types</legend>
    <p><strong>Recommended New Types</strong></p>
    <div>
    <input type="search" id="forminput2_search" name="forminput2_search" value="" tabindex="0" autocomplete="on" aria-autocomplete="inline" required="required" aria-required="true" novalidate="novalidate" spellcheck="false" placeholder="Search this site..." title="Search" aria-label="Search" />
    <label for="forminput2_search" title="Search">&nbsp;*&nbsp;Search</label>
    </div>
    <div>
    <input type="email" id="forminput2_email" name="forminput2_email" value="" tabindex="0" autocomplete="on" aria-autocomplete="inline" required="required" aria-required="true" placeholder="Enter an email address..." title="Enter a valid Email Address: x@x.com" aria-label="Email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" multiple="multiple" aria-multiselectable="true" />
    <label for="forminput2_email" title="Email">&nbsp;*&nbsp;Email</label>
    </div>
    <div>
    <input type="tel" id="forminput2_tel" name="forminput2_tel" value="" tabindex="0" autocomplete="on" aria-autocomplete="inline" required="required" aria-required="true" placeholder="XXX-XXX-XXXX" title="Enter a valid US Phone Number: xxx-xxx-xxxx" aria-label="Phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" />
    <label for="forminput2_tel" title="Telephone Number">&nbsp;*&nbsp;Telephone</label>
    </div>
    <div>
    <input type="number" id="forminput2_number" name="forminput2_number" value="0" min="1" max="100" minlength="1" maxlength="3" tabindex="0" autocomplete="off" required="required" aria-required="true" title="Enter a valid Number: 1-99" aria-label="Number" />
    <label for="forminput2_number" title="Number">&nbsp;*&nbsp;Number</label>
    </div>
    <div>
    <input type="submit" id="forminput2_inputsubmit1" name="forminput2_inputsubmit1" value="Test" tabindex="0" form="forminput2" title="Press Submit to Test HTML5 Validation" aria-label="Press Submit to Test HTML5 Validation" />
    </div>
    <p><strong>Non-Recommended New Types</strong></p>
    <div>
    <input type="url" id="forminput2_url" name="forminput2_url" value="" tabindex="0" autocomplete="on" aria-autocomplete="inline" required="required" aria-required="true" spellcheck="false" placeholder="Enter a URL..." pattern="https?://.+" title="Enter a valid URL: http://..." aria-label="URL" />
    <label for="forminput2_url" title="URL">&nbsp;*&nbsp;URL</label>
    </div>
    <div>
    <input type="date" id="forminput2_date" name="forminput2_date" value="" tabindex="0" autocomplete="off" required="required" aria-required="true" spellcheck="false" title="Date" aria-label="Date" min="2020-01-01" />
    <label for="forminput2_date" title="Date">&nbsp;*&nbsp;Date</label>
    </div>
    <div>
    <input type="datetime-local" id="forminput2_datetimelocal" name="forminput2_datetimelocal" value="" tabindex="0" autocomplete="off" required="required" aria-required="true" spellcheck="false" title="Datetime-Local" aria-label="Datetime-Local" />
    <label for="forminput2_datetimelocal" title="DateTimeLocal">&nbsp;*&nbsp;Datetime-Local</label>
    </div>
    <div>
    <input type="time" id="forminput2_time" name="forminput2_time" value="" tabindex="0" autocomplete="off" required="required" aria-required="true" spellcheck="false" title="Time" aria-label="Time" />
    <label for="forminput2_time" title="Time">&nbsp;*&nbsp;Time</label>
    </div>
    <div>
    <input type="week" id="forminput2_week" name="forminput2_week" value="" tabindex="0" autocomplete="off" required="required" aria-required="true" spellcheck="false" title="Week" aria-label="Week" />
    <label for="forminput2_week" title="Week">&nbsp;*&nbsp;Week</label>
    </div>
    <div>
    <input type="month" id="forminput2_month" name="forminput2_month" value="" tabindex="0" autocomplete="off" required="required" aria-required="true" spellcheck="false" title="Month" aria-label="Month" />
    <label for="forminput2_month" title="Month">&nbsp;*&nbsp;Month</label>
    </div>
    <div>
    <input type="color" id="forminput2_color" name="forminput2_color" value="#ffffff" tabindex="0" autocomplete="off" required="required" aria-required="true" title="Color" aria-label="Color" />
    <label for="forminput2_color" title="Color">&nbsp;*&nbsp;Color</label>
    </div>
    <div>
    <input type="range" id="forminput2_range" name="forminput2_range" value="50" min="1" max="100" minlength="1" maxlength="3" tabindex="0" autocomplete="off" required="required" aria-required="true" title="Slide the Range Indicator" aria-label="Slide the Range Indicator" />
    <label for="forminput2_range" title="Range">&nbsp;*&nbsp;Range</label>
    </div>
    <div>
    <input type="submit" id="forminput2_inputsubmit2" name="forminput2_inputsubmit2" value="Test" tabindex="0" form="forminput2" title="Press Submit to Test HTML5 Validation" aria-label="Press Submit to Test HTML5 Validation" />
    </div>
    </fieldset>
    </form>
    Input Types List







    Checkbox


    Radio


    Hidden

    <input type="hidden" id="forminput_hidden1" name="forminput_hidden1" value="one" aria-hidden="true" tabindex="-1" />

    Special Input Attributes

    Below are examples of special attributes used with 'input', and which are either widely supported by browsers or add value.

    • disabled="disabled" - This attribute must be spelled out as such to support XHTML. Disabled text or buttons cannot be changed and will never submit data to the server. It is for viewing only by users. There is universal browser support for this attribute. Notice I set "tabindex=-1" so the user does not tab through disabled form fields. I also added a matched ARIA "aria-disabled=true" attribute for screen readers.
    • readonly="readonly" - This attribute must be spelled out as such to support XHTML. Read-only text cannot be changed but will be submitted to the server. There is universal browser support for this attribute. Notice I set "tabindex=-1" so the user does not tab through readonly form fields.
    • required="required" - This attribute must be spelled out as such to support XHTML. Required text means the form field must be filled out with some data by the user or an error will be generated and the submission will fail. In most HTML5 browsers, adding "required" triggers validation of an empty field or with pattern matching of the data entered. When it fails a "bubble" alert appears instructing the user of the error. Note: In Internet Explorer, the browser also adds whatever text is in the "title" attribute to the end of this bubble message. So, you can essentially customize the error message, where Firefox and Chrome will add their own data type errors based on the type of form field input("email", "url", etc.). This attribute can be overridden by add the "novalidate=novalidate" on the form or form field. It's good to also add a matching ARIA aria-required="true".
    • pattern="[A-Za-z]{2}" - The "pattern" attribute value shown in this last 'input' element includes a "Regular Expression" (REGEX) pattern that entered text must match. It says to enter a alphabetic US state code two characters in length. I have also added "minlength" and "maxlength" attributes to further enforce the text values. These attributes are used to enhance "text" input fields for users and control data. If validation is enabled, most HTML5-supporting browsers will also enforce text to match the REGEX or other text pattern when submitted. These attributes will also work with many 'input' types, including "text", "date", "search", "url", "tel", "email", and "password". Please note that there is still limited browser support for the "pattern" attribute, so do not depend upon it. Note that even without the new "pattern" attribute added, many HTML5 browsers have built in pattern matching for several types, like "email", "number", "url", etc. They will provide a warning if the type of text entered does not match the minimum character string requirements. But it is still a nice additive feature that can fail and not harm the user experience. Just remember to always validate your 'inputs' with scripts and server processes, as well as pattern matching.
    • hidden="hidden" - In modern HTML5 browsers, a form field element with the added "hidden" attribute will not be seen by the viewer but remain an active form field. Note: Remember, if your browser does not supports HTML5 your form control will not be hidden! The new "hidden" attribute is redundant, however, as there is a "hidden" 'input' type you can use instead which is always hidden and always submitted. But, there may be rare cases where you just need to hide it. In those situations I recommend you use CSS "visibility" instead to hide things, as it will work more reliably in older browsers. If you use "display:none" to hide controls, remember the input will not be seen AND will not be sent to the server on submission, unlike the CSS "visibility" property or the "hidden" element attribute. See my section called "How to Hide HTML5 Elements and Content using CSS" for more information on hiding elements in HTML correctly.

    <input type="text" id="forminput_hidden" name="forminput_hidden" size="20" maxlength="20" value="This is Hidden Text" hidden="hidden" autocomplete="off" tabindex="-1" title="Hidden Text" aria-label="Hidden Text" />

    Non-Recommended Elements that Use 'input'

    The 'datalist' does not have wide enough modern HTML5 browser support to be usable with 'input' at this time. The 'output' element below is not supported in Safari, any Internet Explorer browser, or even Edge 12 (only supported in the newest Windows 10 Chrome-based Edge 13 browser.) So, I cannot recommend its user, either.

    The 'output' element (last box below) allows a user to use the "range" and "numeric" input types to combine values and then post the mathematical result to the new 'output' element box. But 'output' does not have wide enough browser support to be usable, and requires custom JavaScript to work when it does.

     +
     =

    *New HTML5 Input Types

    The New HTML5 'input' Element "types" listed below allow you to expand the type of data collection your forms provide your users, adding date/time features, numeric values, a color picker, search, and more. The problem is many browsers (like IE 9 or less, Safari, some phone browsers, and others) do not fully support them. If you use them, you will likely exclude a wide range of users who will fail to send you any data whatsoever. Because so many of the newer, more modern HTML5 browsers (and all the older ones) do not support these new form field types, its dicey implementing them reliably in web forms today, even with "hacks".

    For that reason, I have divided the ones I recommend and that are safe to use into one list, and the rest I do not recommend in another. All fields below have a full suite of custom attributes added, so you can cut-and-paste them into any project (use code listed above).

    I have added "required=required" to each of these new types and a submit button so you can try and submit their data, see if they work or validate, then review any bubble alerts HTML5-supporting browsers will create for you. You can then tab through each one and see if your browser supported these types and of they trigger validation on each new control. Again, these are built in HTML5 features that require no special scripts, CSS, or other tricks to work! Some HTML5 browsers will even validate by checking text formats for you using added "pattern matching" attributes that are built into the browser for those types (like with the "email or "tel" types below), while others will not know pattern matching and how to validate bad formats. Be sure to click the "Test" submit button below to see this HTML5 validation in action. It is one of the increasing number of built-in, value-added features of modern HTML5 browsers that are coming!


    Recommended New Types

    I recommend these new 'input' "types" below, though all have various issues in some browsers, and no support in older ones. Because these all collapse back to plain "text" types in older browsers, they are additive features you can safely use in your web applications which will not harm user interactions when not supported in their browsers. Be sure to add good JavaScript validation as well as server-side validation to all data coming in from these controls.

    Note: The "search" type typically has its own 'form' and 'submit' button separate from the larger web page. Extensive parsing and validation should be used by both scripts and the server to prevent SQL Injection and other security risks, and to extract out important text string combinations created by the user when typing search strings into "search" type text boxes. I recommend you enable "autocomplete" as I have done below to allow users to use previous search terms.

    Note: I have added the "pattern" attribute with a REGEX text matching pattern to the "email" and "tel" types below. In many modern browsers, the "email" type has built in pattern matching validation, anyway. "tel" does not. But I added my own for those that do not support it. This will only enhance these elements in HTML5 browsers, which will require user's text match a valid email or telephone address pattern when submitting data to the server. This feature has very limited cross-browser support, so do not rely on it to validate every time. I have also enabled "autocomplete". The same in the "tel" type. And in "email", it supports multiple emails using a comma separated list. So I have added "multiple=multiple" to add that support.

    Note: The "number" type should use "min" and "max" numeric values, plus "minlength" and maxlength" text values to control user input ranges on the text box. Again, this works well in newer HTML5 browsers, but will collapse back to a plain "text" type in older ones. Most new browsers support "number" except Internet Explorer. Even IE 11 did not show the number increment buttons. So, remember to always validate these fields for numeric values in older browsers that will allow alphabetic text to be inserted, creating form field errors.

    Be "extra" cautious using any of these new HTML5 types. Besides non-support of these features in non-HTML5 browsers, support is sketchy in newer browsers, too, and has been for years. Test in Internet Explorer 10-11, Edge, Safari, mobile browsers, and more. But always try and stick with the old reliable input "types" I have listed above, when possible.


    Non-Recommended New Types

    I do not recommend use of the new HTML5 input "types" below, as they are not only NOT supported in all older browsers but not supported in many of the newest ones, either. Those that do, have spotty support for both the 'input' "type" but also for pattern matching, So, essentially they act like "text" boxes, in most cases. Therefore, why not use the "text" type for most of these, then add JavaScripted validation and custom controls that apply to everyone? Some developers like to use elaborate "hacks" or scripted polyfills to force these "types" to work in certain browser versions. Thats poor design, as it still leaves out most web viewers! Only use these "types" if you are ONLY supporting the newest browsers and ignoring everyone else. An internal company "intranet" web application, where everyone has to use the same browser, would be a reason to support these, but not on the Internet. Personally, if something is "broken" in most modern browsers, like these are, why bother using them? Always rely on solid HTML you can count on in numerous browsers without extra scripting.

    * A typical web form is shown above.
    My Recommendations:
    1. The 'input' element defines a type of form control used for submitting data to the server. There are many types of 'input' element "types", including many forms of the classic text box, various buttons, and newer HTML5 types. I will discuss all those "types" of inputs in the code samples above and in the text descriptions below. The 'input' element has been around since the 1990's and in the earliest of HTML recommendations by the W3C. It has changed very little in the past 20 years, so is a bedrock form field element supported in all browsers and versions. As such, it can be safely used in all your web forms. Only the newest HTML5 "types" are sketchy.
    2. The Major 'input' Element Types: In the code examples above, I have listed all the various "types" of 'input' elements you can use. (The many new HTML5 ones I recommend are listed in the next section). These below have been around for over 20 years and 100% reliable. Because the code samples above showcase all the 'input' types possible, there is no need to list them below. However, below I will list a few factoids about the various "types" and their unique characteristics you might not know about:
      • The Four Button Types - There are four main "button types" you can use in 'input' elements to create buttons: "submit", "reset", "button", and "image". The "submit" and "image" types act like submit buttons, sending form data to the server. Note that the "image" type also allows you to replace a standard button with an image added via a "src" attribute and image path on the server. These types are always "submit" buttons, and when pressed will submit all form data as the normal "submit" type will. The "button" type does nothing until scripted. And "reset" buttons clear the form fields of all data. Note that the "submit" and "image" types have additional power over how, when, and where form field data gets submitted, beyond what the parent 'form' element says. Because of this submission power, they can override the 'form' attribute settings using new attributes, though I do not recommend you do that as it adds more confusion. These optional overrides are: "formaction", "formenctype", "formtarget", "formnovalidate", and formmethod". Note that these are rarely used, and are overrides of the parent form attributes. They only work when using the "submit" button types of 'input' (see the 'form' element for more details).
      • "checkbox" and "radio" - These unique types give you the ability to offer a multiple choice form fields to users. Checkboxes offer multiple selections of many, while radio offers only one selection of many. Both types of controls must all have the same "name" attribute value to group their values together (see my code sample above) when they are submitted to the server, along with their their text 'value' also submitted to the sevrer. So both send a "name=value" for every item checked or chosen. 'radio' types using the same "name" attribute value create a single choice multiple choice selection. 'checkbox' types using the same "name" attribute value allow a multiple choice selection, same as radio but with multiple possible values using the same name. You can also assign unique "name" values to checkboxes, which allow only one choice in each case, but still multiple, making each name-value more unique. Its more common for 'radio' buttons to have multiple inputs assigned to one "name" than the 'checkbox' type, where there are cases you might want to let users toggle a checkbox on or off which sends a unique name along with its value. Note that data submitted will only submit the items selected or checked, sending the "name-value" attribute to the server of those items the user actual chose, ignoring the rest. These are flagged in the browser, and sometimes on the server with an "on" flag. Some Firefox browsers persist a page as checked even on refresh, so always use "autocomplete=off" attribute on your 'input' elements to disable persistence (you will see that in my code samples above).
      • "text" - This is by far the most common and most popular of the 'input' element types. Any type of text entry you can imagine can be done using this simple "text" type. All the new HTML5 types, like "email", "tel", and "url" are variations on the "text" type. You can use various attributes to restrict the physical size of the box and limit its text entry. Use the "size" attribute to limit the physical text box's character size (default is "20"). Know that "size" only resizes the textbox, not how many characters a user can enter. To limit characters, you can use "minlength" and "maxlength" to control actual characters users can type in the textbox. Also use "placeholder" text to fill the box with gray-scale instructions for the user (like sample text), and "title" or a tooltip to help instruct users what should be entered into your text boxes on rollover.
      • "password" - This attribute value, like the text box version, has been around for years and is often used by authors in login screens. It does not come with any special features beyond hiding the password text. But over the years browsers have begun to assign "password" type text boxes special security features to harden them in the browser and to secure user data. You can also add the new "pattern" attribute to these types to try and enforce or validate early text entries by users. I like to add other attributes, like autocomplete="new-password", which is the same as "autocomplete=off", except this new version prevents most occurrences of previous passwords from showing up in Chrome browsers. You can add limiting attributes like "size=12", "minlength=8" "maxlength=12" (limits password to 8-12 characters) to control the allowable limits of characters used in password text boxes. Most add elaborate JavaScript filtering on top of "password" boxes to control stricter validation. But the extra HTML attributes really help. NEVER submit a form with a password using default form method of "get" for security reasons! Change it to "post". Otherwise, the password will be seen in plain text when submitted via the URL to the sever.
      • "file" - This is a very special type of 'input' that is also widely supported in browsers old and new. The "file" type allows uploads of files to the server and usually resides in its own personal 'form' element with "method=POST" and "enctype=multipart/form-data" attributes set in the 'form'. You must also add a "submit" button to your file upload form, which when clicked, allows users to choose files on their device and upload them to the server from a popup the browser provides. The server must have the ability to process the binary block data stream it will receive from these controls (see <form> for more details on "multipart/form-data"). The "file" input type also has a special attribute calls "accept", which allows you to control what types of files are uploaded by a user. In the code example above you can see how I have added "accept=image/*". This says to only allow images, but of any subtype or extension. The wildcard "*" attribute creates this "any" feature. There are many other arrangements of file types you can add to the "accept" attribute. I have listed a few below:
        • accept="image/jpg" - This input would only accept JPEG images which could have extensions ".jpg" or ".jpeg".
        • accept="image/*" - This input would only accept images, but of many types, including JPEG, PNG, GIF, etc.
        • accept="video/mp4" - This input would only accept MPEG-4 video files, which could have a variety of extensions and codecs.
        • accept="video/*" - This input would only accept video files, but of many types.
        • accept="audio/*" - This input would only accept audio files, but of many types.
        • accept=".pdf,.docx" - This example shows how you can enforce files by file extension rather than file type. Only Adobe Acrobat files with the .pdf extension, or newer formats of Microsoft Word Docs (2007+) would be allowed to be uploaded.
        • accept="image/*,.pdf" - This example shows how you can mix and match file types with extensions.
        • accept=".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" - This example would allow a wide range of Microsoft word types and extensions, and shows how you can try and maximize coverage and upload of a given type of file (Microsoft Word documents) by adding all its older variations of extensions and types into the "accept" list.
        In HTML5, you can also set the "file" type to submit multiple files using the "multiple=multiple" attribute on the 'input' "file" type element. Note that some older browsers have buggy support for multiple file support, including IE version 1-9. As an added feature, my CSS style sheet used for this tutorial contains a very fancy style sheet, which redesigns the "file" type so it looks close to the same in numerous browsers, old and new.
      • "hidden" - (Note: This is not the same as the "hidden=hidden" attribute!) The "hidden" input type ("type="hidden") is not seen by the user (though they can easily see it under a page's "view source") and is often something many developers forget to use, or grossly abuse. It's often misused by new developers today and JavaScripted API's as a vehicle for passing values around because their server is stateless, they don't understand sessions, or they think they need to track each user exchange while ignoring the natural ability of servers to manage sessions. That means they use these "hidden" controls to pass large amounts of data back and forth between the client and server, including huge piles of sensitive and unnecessary information. Often this data is passed anyway by servers in HTTP variables or via cookies. I personally think all this is a mistake and a waste of time. If your server must track the user, but must not use the server to track users, yet must force all this data back on the client, what is to stop hackers from exploiting this data even with SSL/TLS? Adding huge data layers in the client then sending more and more hidden insecure data just increases the risk, as well as slows down page rendering. A BETTER use of 'input' in forms is to simply see it as stateless and letting web servers either not use session state, or manage all the state without use of the client. Try and use "hidden" inputs to pass tiny pieces of data your server cannot store in session but which aids identification of data or the user only, like a product or small user id. Your application is then free of cookies, user sessions, even TLS encryption, as the identification of a web page id does not depend upon sessions, encrypted values, or login data in most cases. One example would be passing a simple user ID or product ID so when data is passed back in say a form, the server knows what record is effected. Besides, using state should be as simple as a single session value anyway, not piles of hidden or encrypted data in a user's browser. But if you choose to use the "hidden" input type for your own purposes, know it is there. Just remember, "hidden" input types are really great places to pass back information that aids processing of a large form or a single record of data on the server, but not so good at storing multiple data records or sensitive data on the client.
      • Required, Disabled, Read-only, and Hidden - For any form field that must be filled out or selected, you must use the "required=required" attribute. Be sure to set any buttons or fields you do not want pressed or sent to the server as "disabled=disabled" in your inputs. Also, data you do want sent to the server, but not changed by the user should be set using the "readonly=readonly" attribute. For rare times you do not need to use the "type=hidden" input type, but simply want to hide an active 'input' control from the user, use the "hidden=hidden" attribute. Note: Always use the "XML-friendly" version of these attributes so your tags are always cross-compatible with both XHTML and XML. Do not use "readonly", but type "readonly=readonly".
    3. New HTML5 Input Element Types: There are many new HTML5 'input' element types and elements, as shown in the code above. Like the 'video' element, these new types remove the need for fancy CSS, JavaScript, plugins, or players to display these interactive components. The browser is now responsible for creating them internally, rather than using 3rd party products, DHTML, or JavaScript polyfills. For example: An 'input' with "type=color" would show a "color picker" popup created by the browser when clicked. No scripting needed! Try recreating that in JavaScript.
      However, even in 2022, support for these new input types is not complete in a number of browsers, including Internet Explorer, Firefox, and Safari. Generally, only Chrome or Webkit browsers offer close to complete support. Even Chrome has issues with some of the new types, however. For that reason and more, use caution when adding these to web projects.
      In the list below (and code above)I have created a list of the major new 'input' types available to you to use in your web forms. I have then placed a "(yes)" next to the ones I fully recommend you use, and nothing next to the others I do not recommend. Most of the "yes" ones are not supported in IE 9 or less and most older browsers, but are supported by everyone else. These "yes" types do have enough built in "fallback" control design to be functional. In all cases, these new types default to "text" type 'input' controls when not supported, so users can at least enter plain text if they are not supported. Some browsers support the new "pattern" attribute to enforce text and numeric data entry in the 'input' elements. But many of these still leave users in many browsers, old and new, lost not knowing what "format" the data must be in. That is why I recommend above, if you use the new 'input' types, that you follow up with carefully coded client-side and server-side validation.
      Most of the new HTML input types I do not support, as they have either no Internet Explorer, Safari, or Firefox browser support, their designs are broken, or they are missing control features necessary to function. There are many people posting solutions to those "broken" controls, which again, add cross-browser complexity way beyond the normal functioning of HTML. Most of these also, as mentioned, do fall back to plain "text" boxes. In many cases this might be enough. But if you want to use non-recommended types and are targeting older user agents, you would need to provide alternative designs and solutions for non-supported ones using very elaborate CSS and scripted solutions. You also would need to add validation and instructions on what data to enter. Because that adds very complicated CSS, HTML, and JavaScript to your projects, I recommend you stick with plain "text" type input controls, or just the handful of new 'input' types below I do recommend. Note: The HTML code for the 'input' types I do recommend are listed above in my examples. However, I have added the non-supported ones, too, so you at least can see how they might function in supporting browsers and can copy some code to help you get started.

      New HTML5 'input' element "types"

      • color
      • date
      • datetime-local
      • email (yes)
      • month
      • number (yes)
      • range
      • search (yes)
      • tel (yes)
      • time
      • url
      • week
    4. Always Wrap a <form>: Element Around Your 'input' Elements: When you wrap a form tag around a submit button 'input' control, it tells the browser your submit button is associated with a specific form "id" value and will only submit the field elements associated with that control. If you have multiple forms of forms and form fields to submit in a web page, it is crucial you know what input button submits which forms. You can still place the 'input' submit button element outside a form, if you give it a 'form' attribute with value associated with a specific form "id". In that case, it will still submit all input fields inside that specific form when pressed. However, I do not recommend you move any form controls or buttons outside of a parent form, as some older browsers may fail to submit the right data when submitted.
    5. Always Use the <label> Element with Your 'input' Element: Try and use the 'label' element before or after your 'input' tag, then add the "for" attribute with a value that matches the input's 'id' value to associate the two together. This links the label to the 'input' or form field and allows the browser, search engines, and screen readers to connect the two, adding semantic meaning. Always add a 'title' attribute to labels with a description of the field in order to associate the label with it. This is just good usability. Often, the browsers will float the label text beside the form control, with minimal CSS design changes needed to position it (see my code samples above for examples of labels and inputs). Additionally, in most browsers "clicking" on the label's text auto-selects the 'input' text box, giving it focus for fast data entry!
    6. Collecting Form Field Data Using Inputs: The process of using 'input' and other form fields to collect and process data is way beyond the scope of this tutorial. Know that 'input' controls manage maybe 95-99% of your data collection in typical web forms today. As such, the single most important aspect of good form field design (beyond HTML) is validation. That is discussed in-depth in the 'form' element section. The main thing to understand about forms and form fields is that data collection is the single most complicated aspect of web design, simply because it requires so many levels of exchange, validation, processing, analysis, and storage. Data collection and processing of 'input' elements data is way beyond the scope of this tutorial. Just know, I have built dozens and dozens of large data collection applications in my life-time, and I can tell you good data collection always begins with solid HTML design, not fancy JavaScript, not fast REST API's, not secure server processes, not relational databases, and not fancy business applications. HTML is always King simply because HTML is the gateway between your users, your server, and your database.
    7. Always use the 'id' and 'name' Attributes: Always use 'id' and a matching 'name' attribute with the same value when possible on all 'input' elements. The one exception is the "checkbox" and "radio" types which must all share the same name so they are grouped. The 'id' affects client-side scripts that must access a unique 'id' on the form field in order to access the control and its data. But 'id' is never sent to the server, unlike 'name'. If there are multiple inputs, it is critical each have a unique 'id'. This value must be unique for each element in the current web page. As mentioned, I like to always match the 'id' value to the 'name' attribute (except for checkboxes and radio types), as I do in all my other form fields. Why? The 'name' attribute is what is always sent to the server, along with the input's "value" attribute. Assigning both 'id' and 'name' to the same value helps your server-side processes identify which 'input' you are processing and align the 'input' with any client-side scripted validation or pre-processing that uses the 'id'. If the two attribute values match, it's very easy to locate and sort client-side from server-side processes if all the values are the same. Also, in form fields the 'name' attribute is often parsed first as it is used when building name-value form field key-value pair data system sent to the server on submit. So, be sure to give each 'name' a unique value, match the unique name to the 'id' element, and be sure to put both first in the element!
    8. Always Use the 'value' Attribute: The 'value' attribute is what is sent to the server as data, and part of the "name-value" attribute pair sent to the server from your input control when a "submit" button is pressed. Always add "value" as an attribute on all your 'input' elements, even if empty, as it controls what data is sent to the server for that control. In some cases, "submit" button types and "hidden" types will have a static, predefined string for 'value', while "text" 'input' types will have a user-entered one for "value". In some cases its important to add a "dummy" value to help define a form field control when say a "submit" button is pressed by the user and sent to the server as a "name-value" pair along with the other form fields. You may want to know what button was pressed and the "value" would be sent along with the name to help identify it on the server when it receives all the name-value pairs for the form. In the case of the "checkbox" type, each box checked will always send the same "name" for all the fields in the group, but with a different values. So make sure each value is unique, as you have to loop through the same array of names to get each value selected. The data for checkboxes with multiple boxes checked will appear like this: mycheckbox=red&mycheckbox=green&mycheckbox=blue.
    9. Always Assign a 'tabindex' Attribute Number: Almost all browsers, old and new, add 'input' elements to a "tabindex" list. This means that all interactive elements are available for tabbing through by a user in the browser as they fill out larger forms. You really do not have to add this extra attribute to your 'input' elements or worry about this feature as it's built into all modern browsers. Most of the old ones, as well new ones will logically add all your form fields and buttons to a tab list. Nearly all form fields, links, and buttons are added to the tabindex, by default. However, you can manipulate this to change the tab order of your 'inputs', remove a input control from the tabindex, or add one that was missed by using the "tabindex" attribute. I always add the "tabindex=0" attribute to all my form fields to enforce addition of each control to browser's tabindex, which also lets the browser reorder everything, naturally. I add "tabindex=-1" to remove fields from the tabindex I do not want included. "hidden" types fields are never added to the tab index anyway, but I add the "-1" value to all other interactive form controls I don't want users stumbling across (including disabled fields, read-only fields, etc.). You can also granularly control tabindex by setting each of your controls to a specific number in an order, like "tabindex=2", and set the specific order you want your users to use. You can also set "autofocus=autofocus" to force focus immediately to a specific 'input' button, button, or other field. This overrides the natural tabindex, however. Remember, the browsers also automatically assign the ENTER/RETURN key to the first available "submit" button type in the web page. So, again you don't have to override these features in browsers unless you want to change tab indexing. "tabindex" and "autofocus" can help enrich your 'input' controls and add more control over how you intend users to use your web forms. (See my code samples above which use "tabindex", and read my section in this page called "TabIndex and Autofocus in HTML" for more details on "tabindex".)
    10. 'image' Type Attributes: The "image" type of input allows you to create a submit button which uses an image for the button. To enable this feature you will need to add three additional attributes: "src" for the image URL on the server, then "width" and "height" for the image dimensions. Be sure to also add the same dimensions in your CSS and other styles for more control over the final image button design. This works like the 'img' element, and allows the image button to reserve space in the rendered page for the image while it downloads. Important: You must add "alt" attribute to "image" types, like 'img' elements use. Of course, add a tooltip or "title" attribute and ARIA, as well.
    11. Optional 'placeholder' Attribute Text: The "placeholder" attribute is a nice place to add special grayscale text inside text boxes which assists users with the type of data they must enter. Use this with the 'title' or tooltip attribute to assist users with data entry formats.
    12. Optional 'autocomplete' and 'novalidate': I discuss these two attributes in more details under the 'form' section (see <form> for more details), as the form really controls this setting over all its child 'input' fields. But often you will have a 'form' with default settings and want to override them in each form field. The two most difficult ones to manage are "autocomplete" and "novalidate". In general, to summarize, the code samples above showcase my "best practices" and recommendations for how each field should use these two attributes.
      I do not like "autocomplete", but sadly the default in form fields and in browsers is the "on" setting. This means when a user sees a form field in another website with a similar "name" attribute value as yours, it tries to pull a dropdown list of previous text choices for the user to choose from, which they entered in previous websites. I find this helpful, sometimes, but in the case of "logins" it is a terrible feature and a HUGE security risk! For that reason I ALWAYS recommend you manually add this attribute ("autocomplete=off") to EVERY form field and 'input' you have to make sure you turn autocomplete OFF and force users to ignore past text entries. For "password" you always want your users to enter fresh data into your forms fields, and NEVER reuse saved ones, so use "new-password" to disable this feature on password field. I like to remove this feature on most other inputs, setting the attribute "autocomplete=off" on each one. WARNING: Even after adding this "autocomplete=off" attribute, the browser often overrides this feature anyway, and gives users the previous options in a dropdown beside your form fields. But there are more tricks you can do as a page author to stop "autocomplete", as mentioned in the 'form' section of this page.
      As for 'novalidate', good news is it is "off" by default, meaning validation is always enabled by default, which in my opinion is a good thing as HTML5 browsers now come with a new array of validation checks and features. Again, see my 'form' section for more details on how these work and some additional tricks to force them to do what you expect. But if you want to turn off validation on a field and override the 'form' element's default value, you can add the "novalidate=novalidate" attribute to your 'input' element.
    13. Optional "autocorrect", "autocapitalize", "spellcheck": These attributes are really not widely supported. "autocorrect" only works in Safari browsers on Macs. "autocapitalize" is not supported in IE 1-11, Firefox browsers, Safari desktop, and possibly many android browsers. "spellcheck" I cover in the 'textarea' element, and does have wider browser support. But, rarely do you want to force users to correct typos. I have added most of these attributes anyway to many of the code examples for inputs in this page to DISABLE or turn "off" these features in browsers that support them. It is always best to disable any spell-checking, correcting, completing, capitalizing, or other "auto" features on form fields. This just gives the user the power and freedom they need to decide what data they are entering without interruption. But, if you find you need to channel your data entry users into highly filtered and customized data choices, try enabling these and see how they perform by browser and version.
    14. Do Not Use "accesskey": I do not recommend use of this attribute. Long ago, it was designed to allow keyboard presses to access form fields. But it is not reliable and requires various additional combinations of keys to work that are specific per device or just not accessible. It also conflicts with operating system shortcuts and could trigger other features on a laptop or phone by accident.
    15. Do Not Use "step": I do not recommend use of this attribute. The "step" attribute works with the following numeric input types: number, range, date, datetime-local, month, time and week. It allows you to try and control intervals of numbers entered, but is poorly supported and unreliable in browsers as is the new 'input' types it supports. Use JavaScript to control this, instead.
    16. Do Not Use New "inputmode": This new attribute is gaining in popularity, but still poorly supported in browsers. "inputmode" is now used as a "hint" to tell browsers the type of data to expect, like "email", "search", "url", etc. Because its not supported in IE, Safari, or Firefox browsers prior to version 24, it is not helpful or reliable.
    17. The Optional "data-" Attribute: As mentioned below in my "Best Practices" article called "The New 'data-' HTML5 Attribute", you can now safely use the new "data-" attribute in any HTML form element to store extra data values. Know that this is an extra attribute, and that "data-" values are not submitted to the web server anyway, so pretty useless. Its mainly an add-on for JavaScripted frameworks on the client-side.
    18. ARIA Attributes: The 'input' element is another "self-describing" structure recognized by most modern screen readers, and by its various "types" that help define its use. Most screen readers can read each form fields quite well, and understand an 'input' type's value. They can identify its semantic purpose that way. However, it is recommended you add an ARIA "aria-label={Name of Item}" on each 'input' element to give screen readers more details about your input's purpose and meaning within a form. You should also use the "aria-multiselectable=true" on "file" or "email" types that allow multiple file uploads or comma-separated emails, "aria-checked=true" for "radio" and "checkbox" types that are pre-selected, aria-pressed="false" for buttons that are not active yet, aria-autocomplete="inline" when "autocomplete="on" is used, and "aria-hidden=true" for the "hidden" input type. I would avoid "roles" attributes for most or all your 'inputs' as they are understood based on their "types". However, when delivering a "search form", "email", "file", or other specialized form submission, its advisable to wrap a specific form around these selective form inputs then add "role=search", for example, to the parent 'form' element. This "landmark role" tells screen readers the function of the input group and the overall form submission.
      You do not need the ARIA "live" attributes telling screen readers the "state" of your controls or buttons as they change unless you are manipulating the DOM using JavaScript. For example, "aria-pressed" and "aria-checked" do not need to be updated, unless you do.
      Use my code samples above to see "best practice" uses of ARIA attributes in 'inputs' when designing form fields that assist screen readers.
    19. Additional Input Attributes Supported: The list of attributes for inputs is extensive. Instead of listing all the combinations, I have added the attributes I recommend for each subtype of 'input' in the code above, including the new HTML5 ones. Just copy the code and you will have a great start using form 'input' controls with 99% of what you need as far as attributes, settings, and what is widely supported. In addition, below in "best practices", I have listed numerous examples of code using various attributes for input form fields and button types. Use those examples to help you understand what attributes work best in custom HTML situations beyond the norm.
      * Many deprecated attributes from the past still exist for 'input'. Avoid the following which either no longer work or which can be controlled with CSS now: align, height, width.
    20. The Optional Pattern Attribute: "pattern" is a new HTML5 attribute that allows you to assign a REGEX pattern to an 'input' element. When validated by the browser, it will check the user's entries to see if it fits within the pattern's constraints. The 'pattern' attribute only works when using the default validation setting on 'form' elements (no attribute), removing or overriding the "novalidate=novalidate" added to form fields, or when adding "required=required" to each form field. Note that the "novalidate" attribute added to forms overrides the "required" attribute on fields when added, so your forms will still not validate. When a "submit" button is pressed and "novalidate" is not applied, most modern HTML5 browsers will validate each form field and show bubble validation messages for any field either missing data when set to "required", or validate the text data that does not pass pattern matching attribute values. It will start with the first invalid field and show a bubble alert for each field that fails validation in this way. These checks include one bubble alert for empty required fields and then one for data entered but which is invalid, as defined by the pattern matching attribute. (Keep in mind some browsers come with their own built in pattern checking for certain 'input' types formats, like "email" or "url"). Note that Internet Explorer will add the "title" attribute text to the end of these bubble messages, so you can customize the error alert. The other browsers are better at showing additional data-specific error information, like whether the text is supposed to be in a "number", "email", "url", etc. format and is not. In this way, the HTML5 browsers often assist with validation using the "pattern" attribute or built in pattern matching using special regular expressions for each type of input added to your form. "pattern" is a new attribute in HTML5, so not very reliable or supported across browsers. I have found that "email" had the widest support for both browser native pattern matching and for support of the custom "pattern" attribute on the 'input' element. When supported, the "pattern" attribute works great in forcing allowing the browser to look at user data and make sure it fits a given text string format before data will be submitted or passed to JQuery or scripted validation. Because its non-intrusive and additive, if browsers do not support it, it does no harm. It adds value as no scripting is needed. Because of variable support in browsers today for patterns means there is one more reason not to rely on these new HTML5 additions and design solid validation on the client and server, instead.
    21. Form Field Validation: As mentioned above and in the <form> section, it is not enough to drop form fields like 'input' onto web pages and then hope the data coming into the server works. I have found too many cases where poor data processing ends up destroying a website! Even with fancy JavaScript, you cannot ignore the HTML design and server processing. That also includes heavy database scrubbing and processing. You need to always validate your form fields, no matter what the type, in ALL layers of your application. Do it not just to improve data collection, but for security reasons as well! Data validation is not part of the scope of this tutorial but is native to the specific language, framework, network, and database architecture you are using. Don't rely on a single product like JQuery (JavaScript) either. Rely on good server-side validation, always, but good HTML design, too. It will help the user get the data right on their end without waiting on elaborate scripts to warn them later. Getting the HTML design right helps them navigate your forms faster, and makes it much easier for them to enter good data. Good HTML means it's one less layer you have to wrestle with. And it frees up control of data entry to your users, not your script libraries or your server.
    22. See the <form> element section for more details about this element within a form.
    <ins> insert

    Insert

    see also <del>

    <p>Did you know my favorite pet is a <del>dog</del> <ins>cat</ins>.</p>

    Did you know my favorite pet is a dog cat?

    My Recommendations:
    1. The 'ins' element represents a piece of inline text that has been recently inserted. The 'ins' tag will draw a line under any text it wraps around.
    2. The 'ins' element is often used to tell a reader of changes to text that are critical in representing the history of an edited document. An inserted text (<ins>) will often follow the deleted one (<del>) to indicate a replacement of new text for the deleted one and to emphasize the change.
    <isindex> isindex

    Isindex

    <isindex prompt= "cats" action="http://google.com/" />
    My Recommendations:
    1. The 'isindex' element is a deprecated, non-standard HTML element once used to display search strings in a web page. It would be placed in the 'head' section of a page and used as a search prompt in querying the contents of the web page. It was rarely used and not used today. Do not use the 'isindex' element.
    <i> italics

    Italic

    This is some <i>italic</i> text.
    This is some italic text.
    My Recommendations:
    1. The 'i' element defines a piece of "italic" text.
    2. Do not use the 'i' element, but use 'em' instead! Because 'i' is a purely visual element, use of its semantically important brother, <em>, is recommended instead of 'i'. You can also use CSS styling and 'font-style: italic' on spans of text segments if you just want a design change, but its not as search engine friendly as 'em'.
    <kbd> keyboard input

    Keyboard Input

    <p>Press <kbd>ctrl</kbd> + <kbd>v</kbd> to paste text in Windows.</p>

    Press ctrl + v to paste text in Windows.

    My Recommendations:
    1. The 'kbd' element represents a inline piece of text representing keyboard input or keyboard combinations. It often wraps around text that displays a key combination for a user to type. Often these were used in online teaching manuals, or computer instruction in web pages for keyboard triggered features (in the example above, I have applied CSS styles to add the "bubble" effect for 'kbd' text). This element is similar to <code>, <var>, and <samp> in that 'kdb' formats text to represent abstract computer programs, keys, equations, or ideas.
    2. 'kbd' and Screen Readers: This element has been around for some time, though rarely used. One reason is the fact there are few cases where instruction online in browsers uses or requires keyboard inputs. In that sense, 'kbd' only adds a little semantic meaning beyond its visual "monospace" display of keys in the text. The one exception is with screen readers, where such keyboard displays do have meaning beyond the visual. If you have a website where certain HTML is assigned "accesskey" attribute values (that are supported) with keyboard combinations, for example, and you intend to enable instruction for visitors and screen readers to use such combinations, then you might have a case for using 'kbd' elements. Often you can achieve much better design for "keyboard text" using CSS on say a "span" element. But again, that would not provide the same semantic meaning needed for non-visual readers as the 'kbd' element would. So, use 'kbd' on a case-by-case basis, as needed.
    <keygen> keygen, key generator

    Keygen

    <keygen id="securekey1" name="securekey1" challenge="abc123" keytype="DSA" keyparams="somekeygenstring" />
    My Recommendations:
    1. The 'keygen' element represents a new HTML5 "hidden" form field designed to hold a public encrypted key. When this was sent with a form, it was designed to provide a client page a secure way to connect to a private key on a server and to communicate with its web-based certificate system, creating a secure connection for data transfer. This element is now deprecated, no longer supported by most browsers, and no longer used in HTML5.
    2. The 'keygen' element is no longer used, so I will not discuss its attributes and features. I do not recommend its use at this time.
    <label> label

    Label

    <form id="formlabel" name="formlabel" method="post" action="#" title="Label Example" aria-label="Label Example" autocomplete="off" autocapitalize="off" spellcheck="false">
    <fieldset id="formlabel_fieldset1" name="formlabel_fieldset1" form="formlabel" style="background-color:#fff;">
    <legend style="background-color:#aaa;color:#fff;">Label Example</legend>
    <div>
    <label for="formlabel_text" title="My Text Field">My Text Field</label>
    <input type="text" id="formlabel_text" name="formlabel_text" size="20" value="" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" placeholder="Enter text here..." title="Enter Text" aria-label="Text" tabindex="0" />
    </div>
    </fieldset>
    </form>
    Label Example
    My Recommendations:
    1. The 'label' element represents an inline text element that displays text next to a form field or other element. The 'label' element is designed to not just label a form field but associate textual meaning to it.
    2. The 'label' element is associated with a form field using its "for" attribute. The value of the "for" attribute is associated with the "id" value of the form field, connecting the two together. Always add a 'title' attribute to your label with a description of the field associated with the label. This is just good usability. As such, the 'label' element really does not need any additional attributes.
    3. Special Features of Labels: 'labels' have been around since the 1990's and were part of the first W3C recommendations. They are a powerful way to associate a span of text with a given form field element, giving it a label. For starters, labels can be associated with many types of form fields (input, textarea, select, progress, meter, etc.). Second of all, screen readers will often read out the label text when the form field is given focus. The connection between a form field and its text label also means you can "click" the label and it will automatically move your cursor into the form field (i.e. text box), giving it focus. Traditionally, its best to add the label BEFORE a form field. In the case of the "checkbox" and radio" 'input "types", its always better to add the label AFTER the element. Most browsers will align the label text perfectly centered, right, or left of the form field. You can also add a break and have the label text sit ABOVE the form field (good in 'select' controls).
      Some developers wrap the label AROUND the form field element, and so avoid using the "for" attribute. This was how we used to associate labels with text boxes, then struggle with CSS to center the label text. Today it is a BAD IDEA as it not only makes aligning label text difficult, but breaks the connection between the two. Also, many times form fields are block-level elements that should not be inside the an inline label element. Note: I often change my 'label' element selectors in my CSS "reset" style sheets to use "display:block-inline" so they sit next to form fields but act like block-level elements and have dimensions and positioning I can manipulate.
    4. I highly recommend you get in the habit of adding a label for EVERY form field you create, even it is not needed, as it adds important semantic and descriptive meaning to your forms. For more example of labels with different for fields see the <input>, <select>, and <textarea> examples in this HTML5 list.
    <layer> layer

    Layer

    <layer id="mylayer">Some text content</layer>
    Some text content
    My Recommendations:
    1. The 'layer' element is a deprecated, non-standard HTML element once supported in Netscape 4 Series browsers and used to position and content separate from the main web page content flow. The 'layer' and 'ilayer' element in Netscape browsers acted like a form of 'div' or 'iframe' alternative. It was rarely used then and is not used today. Do not use the 'layer' element.
    <legend> legend

    Legend

    see <fieldset>

    <form id="legendform" name="legendform" action="#" method="post" aria-label="Login">
    <fieldset id="legendfieldset" name="legendfieldset" form="legendform">
    <legend style="background-color:#ccc;color:#fff;">Login</legend>
    <p>
    <label for="legendinput1" title="Username">Username: </label>
    <input type="text" aria-label="Username" id="legendinput1" name="legendinput1" size="20" maxlength="10" value="" title="Username" tabindex="0" autocomplete="username" />
    </p>
    <p>
    <label for="legendinput2" title="Password">Password:  </label>
    <input type="password" aria-label="Password" id="legendinput2" name="legendinput2" size="20" maxlength="10" value="" title="Password" tabindex="0" autocomplete="new-password" />
    </p>
    <p><button id="legendsubmit1" aria-label="Submit" aria-pressed="false" title="Login" tabindex="-1" disabled="disabled" aria-disabled="true">Login</button></p>
    </fieldset>
    </form>

    * Note: The box around the form fields is the 'fieldset'. The "login" text is the fieldset's 'legend'.
    Login

    My Recommendations:
    1. The 'legend' element is a title that appears inside a fieldset in a web form. It is often used to present a text title inside a box that labels a group of form fields, and appears in the upper left corner of a forms's fieldset box. Note: It is recommended you use multiple 'fieldsets' with 'legends' if you plan to have multiple 'submit' buttons or subsections inside your forms.
    2. Every 'fieldset' should have a 'legend'. The legend always appears just inside the parent 'fieldset' element and is used to add a title or caption at the top of the fieldset block. As such, it is helpful when identifying sections of your form. The 'legend' text title is placed on top of the fieldset box/border line, though you can style it to appear anywhere or any way you like. (In the example above, I have added a gray background to my 'legend' and left it at the top left). The 'legend' allows you to give each section of your form a title explaining what that form section represents. In giant data entry pages online, this is extremely helpful as it breaks up a form for users. Users can then fill out data in sections and submit partial or complete parts of larger online forms as they finish them.
    3. Visual Problems with Legend: There are some minor visual issues with 'legend', 'fieldset', and its design layout in some older browsers. Typically, the 'legend' text sat on top of the 'fieldset' box border. This border often had a background color with the 'legend' box text floating on top of the border removing its lines from the fieldset box, but not affecting the background color. Some browsers added a gray background for the fieldset which then bled the background color of the 'fieldset' box under the 'legend' text, creating an ugly display. Other browsers allowed text to jump in or outside of the 'fieldset' box itself, pushing the text on top of the fieldset line. To prevent this, either leave the default CSS and background of the 'fieldset' as set by the browser (often white like the page), set the 'legend' background to a color that sits over 'fieldset' background color completely (as my examples do), or just set the 'fieldset' background to "transparent". All these solutions will allow the 'legend' text to float between the fieldset lines and ignore the background color underneath.
    4. Browser Support: 'legend' has wide support in nearly all browsers, old and new. So, it is fully supported.
    <li>,
    <ol>,
    <ul>
    list, ordered list, unordered list

    List

    also see <dl> and <nav>

    I have combined the three main elements that control lists below: <ul>, <ol>, and <li>.

    There are three main "types" of lists: Unordered <ul>, Ordered <ol>, and Description <dl>. We will demonstrate the first two here. Description lists <dl> are shown elsewhere as they have unique sub-elements and perform a slightly different role in HTML. You may also see how to style unordered lists to build a "menu" in the <nav> section of this page.

    Shown below are examples of "unordered" and "ordered" lists. Both types use the 'li' child element to hold "list items". Unordered lists can be in any order, so their bullets or icons are generic types. Their list items can be arranged in any order. Ordered lists are numbered in an ordered sequence. I have also included "nested" lists below so you can see how nested lists work, and how the bullets change in style using the browsers default bullet styles.


    Unordered List

    
    <ul id="unorderedlist1">
        <li>List item 1 : Level 1</li>
        <li>List item 2 : Level 1</li>
        <li>List item 3 : Level 1
            <ul>
                <li>List item 1 : Level 2</li>
                <li>List item 2 : Level 2</li>
                <li>List item 3 : Level 2
                    <ul>
                        <li>List item 1 : Level 3</li>
                        <li>List item 2 : Level 3</li>
                        <li>List item 3 : Level 3</li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
    
    • List item 1 : Level 1
    • List item 2 : Level 1
    • List item 3 : Level 1
      • List item 1 : Level 2
      • List item 2 : Level 2
      • List item 3 : Level 2
        • List item 1 : Level 3
        • List item 2 : Level 3
        • List item 3 : Level 3

    Ordered List

    
    <ol id="orderedlist1">
        <li>List item 1 : Level 1</li>
        <li>List item 2 : Level 1</li>
        <li>List item 3 : Level 1
            <ol>
                <li>List item 1 : Level 2</li>
                <li>List item 2 : Level 2</li>
                <li>List item 3 : Level 2
                    <ol>
                        <li>List item 1 : Level 3</li>
                        <li>List item 2 : Level 3</li>
                        <li>List item 3 : Level 3</li>
                    </ol>
                </li>
            </ol>
        </li>
    </ol>
    
    1. List item 1 : Level 1
    2. List item 2 : Level 1
    3. List item 3 : Level 1
      1. List item 1 : Level 2
      2. List item 2 : Level 2
      3. List item 3 : Level 2
        1. List item 1 : Level 3
        2. List item 2 : Level 3
        3. List item 3 : Level 3
    My Recommendations:
    1. The 'li', 'ul', and 'ol' elements are block-level elements representing a list. The unordered list ('ul') and ordered list ('ol') elements hold child list items ('li') elements. These elements are used to show generic lists of items in HTML. You can also use the description list ('dl') for defining the meaning of list items, like in a dictionary. These more generic unordered and ordered list elements have been around since the early HTML days, and so are a reliable tool for sharing lists. HTML5 now supports them, as well.
    2. The Structure of a List: The child element, 'li', is contained inside the 'ul' and 'li' tags and is used to hold the list item text. The unordered list is for lists whose bullets and list items should not be numbered. The ordered list type is for lists that should be in a specific numbered order. You can have as many list items under each list type as you want, mix and match them, have any elements you like inside each list item (block or inline elements), any nested combination inside these lists, and can design lists in any way you prefer using CSS. Just remember to place all your 'li' elements under a parent list element and wrap 'li' elements around all content.
    3. The Semantic Power of Unordered Lists: Often, child list items in unordered lists can be used to do things beyond displaying simple text lists. They can hold lists of links as menu items, for example, or other non-typical elements and content that must be grouped. Lists can even be used for structural layout sections of a web page. Because the list is a powerful semantic "grouping" element, it allows you to go beyond its generic use as a simple text list and hold groups of similar HTML elements or content together. This assists end-users but also search engines and screen readers in associating list items with larger context and meaning. So, use unordered lists as often as possible in your web pages where you have groups of items that must be associated together.
    4. The Design of Lists: Lists often come with a style supplied by default in every web browser that shows numbers or bullets in a block-level indented design made to hold text. This style has not changed in over 20 years! So, I encourage you to use it as is. I often repeat the exact same bulleted list style in all my "reset" CSS style sheets when styling 'ul', ol', and 'li' elements. This allows me to force all browsers to use the exact same styles, bullets, margins, and padding for list designs across all browsers, old and new.
      You also need to know two features of lists. The first is, they are "block-level" elements, like 'div', meaning that they always have dimensions unlike paragraphs or spans, always have padding and margins, and always drop down to a new line. As such, consider lists as structural elements, which implies you can use them to create things like menus, navigation blocks, even page-level structures or sections of web pages. Just remember, lists are always grouping mechanisms, though the children under them are still part of the larger list structure. This means screen readers will create a permanent association semantically between all list items and the blocks of content inside them.
      Finally, understand that beyond the default bullets that decorate the 'li' items and the margins and padding most browsers apply, lists and their list item children have no real "design function". They are empty elements. In other words, their semantic "list powers" are more important than how they look on a web page. You can always strip away their bullets and padding using CSS. But their semantic powers remains. So, do not go designing elaborate styles on these elements, except when needed. But think of their real powers as residing in their semantic meaning.
    5. Supported List Attributes: The "id" attribute with a unique value is the only real attribute I would add to 'ul' and 'ol' list elements. This allows you to at least control the list using scripts, if you need to. The 'li' should have no attributes beyond CSS class styling.
    6. Non-Supported List Attributes: The 'li' element has one older attribute called "value" which allows you to set the current number of your bullet in ordered list items. However, I do not recommend its use and prefer you let the browser build the numbers for you. You can set a "type" attribute on 'ul' and 'ol' elements to control the bullet style. But, I do not recommend its use as CSS allows you to do the exact same thing using the "list-style-type" property. Do not use the "compact" attribute, either. In old HTML 4 you could use the "type" attribute to set bullets on ordered lists ("ol"). For example, "type=A" created a list with bullets that used uppercase letters (A, B, C, etc.). "type=i" created a list with bullets that used lowercase Roman numerals (i, ii, iii, etc.). But this has been deprecated. Use the "list-style-type" CSS property on ordered lists, instead. Most of these attributes are part of old HTML4 and are also no longer supported in HTML5. They can also easily be created in CSS.
    7. What Bullets Should you Use?: The 'ol' and 'ul' elements as mentioned historically have supported a limited number of bullets (pre-2001). However, over time many bullets have been added. But for maximum cross-browser support I recommend you start with the basics in your CSS that have support of bullet types from the 1990's then add your own. My Universal CSS Framework uses this basic list. older browsers also supported the following subtypes:

      Ordered Lists:
      1. decimal (primary)
      2. lower-alpha (primary)
      3. lower-roman (primary)
      4. upper-alpha
      5. upper-roman
      6. upper-latin
      7. lower-latin

      Unordered Lists:
      1. disc (primary)
      2. circle (primary)
      3. square (primary)
    8. ARIA Attributes: I do not recommend use of any ARIA attributes on HTML lists, as like with most HTML elements, they are self-describing and do not need to provide additional information to screen readers. You should only use the "role=list" and role="listitem" on non-traditional list items, like 'div' tags, if you use them as lists. In that one case, screen readers may not readily identify these elements are lists and need the "role=list" and "role=listitem" assigned. The one exception for adding ARIA on true list elements is if you use unordered lists for "menus" links inside 'nav' elements (see my <nav> for an example of using ARIA when lists are used as menus). These designs allow you to use unordered lists to display a styled set of navigation buttons in your web pages. In this case, you may use CSS to have their bullets removed, their margins and padding reset, and their block-level design altered to fit into custom menu designs or buttons at the top of your web page. In this case, the list item role has changed and you are using lists for a new "menu" and "menuitem" role in the web page. When you use lists for menus, you need to tell screen readers their semantic purpose has changed using ARIA. So visit the 'nav' element area mentioned above in this page for an example of how best to do that.
    9. Additional List Goodies: You can always customize the default "bullets" which come with 'ul' and 'ol' list elements by using the CSS property "list-style-type" property. My style sheet associated with this web page attempts to use the same generic list styles used by browsers for over 20 years (see the nested list example above to see the default bullets for a 3-nested list). These bullet designs generally change for each level of each nested list. But you can change those bullet designs any way you like, add custom image bullets, or remove bullets easily using CSS. No scripting required!
    <link> link

    Link

    also see <style>


    A 'link' element is a non-visual (invisible) element that resides inside the <head> element of a typical web page. Below I have listed a rich set of <link> code examples and the many ways you can use this element to enhance your website. Note that I have added the right mix of attributes to the code examples below, so you can cut-and-paste my code and get up and running fast knowing that my 'link' examples will work well in most browsers. You just need to replace the "href" URL values and other element attributes with your own values, in most cases.


    Link with Favicons

    Always include a "favicon.ico" link your website!

    <link rel="shortcut icon" href="favicon.ico" />

    Link with External Cascading Style Sheet

    This example below demonstrates the two most important use cases for the 'link' element in websites today: External CSS style sheets. Always include links to external style sheets in your website! Why? External style sheets are cached for days, weeks, or months by the browser and control the look-and-feel of thousands of pages in your websites, unlike their less efficient cousins, "embedded" styles using the <style> tags and "inline" styles in elements.

    <link media="print" rel="stylesheet" type="text/css" href="print.css?v=1.0.0.1 />
    <link media="screen" rel="stylesheet" type="text/css" href="style.css?v=1.0.0.1" />

    Link with External RSS File

    If you deliver news feeds of your articles or blog, you can link to your RSS XML file using the 'link' element below.

    <link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml" />

    Link with "Prefetch"

    Add resource prefetch call below to preload assets in other pages you hope users will access when they visit a new web page. These files will be cached, but implementation of the call is optional for the browser as these are flagged as low-priority. Note: Browser support of this feature is limited. See my recommendations below for more details.

    <link rel="prefetch" href="someresource.jpg" />

    Link with "Prerender"

    Add resource prerender call below to preload complete web pages and all their associated resources you hope users will access after the viewing the current web page. These files will be cached, but implementation of the call is optional for the browser as these are flagged as low-priority. If this feature is enabled, the browser will "switch" the page to the new page already rendered. Note: Browser support of this feature is limited. See my recommendations below for more details.

    <link rel="prerender" href="somewebpage.html" />

    Link with "Preload"

    The new "rel=preload" attribute works much like the "prefetch" and "prerender" types, except "preload" forces download of individual files (often style sheets) into the cache the minute the browser is available to do so. (i.e. its not optional, unlike with the other two types). I discuss how and why these preload features are used in more detail in my recommendations below.

    Use this version to add resource preload calls below to files you hope users will access after viewing the current web page. Unlike "prefetch" and "prerender", "preload" types must be downloaded and cached. An optional JavaScript "hack" below allows you to preload files in the current page and use them, as well, using a "media=print" to "screen" trick. Note: Browser support of this feature is limited and relies on JavaScript to work.

    <link rel="stylesheet" href="style.css" media="print" type="text/css" onload="this.media='screen';this.onload=null;" />

    Use this version to add resource preload calls below to files you hope users will access after the viewing the current web page. Unlike "prefetch" and "prerender", "preload" types must be downloaded and cached. An optional JavaScript "hack" below allows you to preload files in the current page and use them, as well, using a "rel=preload" to "stylesheet" trick. Note: Browser support of this feature is limited and relies on JavaScript to work. There is a fallback "noscript" for older browsers added.

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

    Use this version to add resource preload call below to files you hope users will access after the viewing the current web page. Unlike "prefetch" and "prerender", "preload" types must be downloaded and cached. This version only caches the file, but does not trick the browser into viewing it in the current web page. Note: Browser support of this feature is very limited.

    <link rel="preload" as="style" href="style.css" />

    Link with "Content Delivery Networks" (CDN)

    If you prefer to use CDN's (Content Delivery Networks) to deliver your CSS files (Bootstrap), you can use this version of the 'link ' element below that is designed to do just that. This version also demonstrates the use of the new "integrity" attribute that some CDN's require and which prevents "cross-origin" rejection by some browsers. Without this encrypted key value, some CDN servers or browsers might not allow you to access their server or files.

    <link rel="stylesheet" href="https://cdn.com/cssfile.css" onerror="this.onerror=null;this.href='local.css';" referrerpolicy="no-referrer" crossorigin="anonymous" integrity="sha384-..." />

    Link with "Canonical" URL's

    You can help search engines know the "preferred" URL design to use for all your web pages, using the "canonical" version of the 'link' element, as shown below. Notice in the example below, I am telling the search engines I want all links into my website to use the "https://" version or secure URL version, and without the "www" subdomain added.

    <link rel="canonical" href="https://mitchellstokely.com/" />

    Link with "DNS Prefetched" URL's

    Like "canonical" links, this "DNS prefetch" link version is also a new feature and optional. There is no guarantee it will help improve anything in your website. If it does work, it just attempts to establish connections faster with external URL's and resources online and solve DNS resolutions quicker. Note the use of the "missing prefix" URL (href="//..."). This tells the external web resource to pick either "http" or "https" for the correct prefix. Also, remember to add an ending "/" slash to the end of URL's as it often means one less call to the server!

    <link rel="dns-prefetch" href="//mitchellstokely.com/" />

    Link with "Preconnect" URL's

    Like "prefetched" links, this "preconnect" version is also a new feature and optional. There is no guarantee it will help improve anything in your website. It attempts to locate available browser connections early with foreign servers and connect with those external resources before they are needed. This can make for a slightly faster web page display when you use lots of external dependencies.

    <link rel="preconnect" href="//maxcdn.bootstrapcdn.com/" crossorigin="anonymous" />
    My Recommendations:
    1. The 'link' element appears in the head of a web page and is used to connect to an external file resource. It typically is used to download external CSS style sheets, link to extra web resources, or download external material a website might need in rendering its web page in the browser. 'link' elements have been around since the 1990's and have changed very little in the past 20 years. 'link' elements really began when CSS (Cascading Style Sheets) was adopted by the first web browsers. The first CSS-supporting browsers were Internet Explorer 3 in 1996 and Netscape 4 in 1997. So the 'link' element was supported in web browsers around that time. It is a reliable element you should definitely use.
    2. Types of 'link' Elements: Below is a list of 'link' examples and how you might use linked files and URL's in your website. These again would all appear inside the 'head' element of your web page, and are not visible to users. This list is not exhaustive, but does include examples of the most important ones you should use in your website. Coded examples of these links are listed above:
      • Favicons - Always include a "favicon.ico" (icon) link in your website! The "favicon" is a special ".ico" or other graphics file that appears next to any web page or URL shortcut in the browser. Its tiny image is just a few dozen pixels across and used to represent your website when listed as a bookmark or shortcut in web browsers. To help browsers download this icon file, a special 'link' element with a "rel" value or "shortcut icon" must be added. The browser will then download the icon image file from the server using the URL in the link and assign it as a shortcut image whenever one of your pages appears in a browser listing. Note: Most modern browsers by default search in the web root of your web site for this icon now without needing the icon link. So, this element is optional. However, I like to move all my images out of the web root of my websites and into my "images" folder in order to better manage them and switch them out as needed. So, using the link above is a better way to have to make sure the "favicon" gets installed in the browser for all my websites.
      • Cascading Style Sheets (CSS) - Always use 'link' elements with external CSS style sheets! Use of external CSS files to manage the design and layout of your website is a better option than most other style conventions. Why? External CSS is far superior to "embedded" (<style>) and "inline" element styles (<span style="color:blue;">my text</span>) simply because external styles downloaded to the browser are cached for every page in your website and affect all web pages, not just one. Often inexperienced developers use inline or embedded styles and forget about externally linked CSS sheets. They assume they are slower, inferior, antiquated, or difficult to manage when the opposite is true. They then lose out on valuable, reliable, proven technology that is far superior to anything built today. Links to multiple external CSS files also download in parallel to each other in a very quick fashion in most browsers, so there are few delays. Browsers have been doing this for over 20 years. Unlike large libraries of scripts, linked CSS often has a very tiny footprint and so has very little affect on page rendering or paint delays, simply because modern browsers manage these downloads very effectively and have been for decades. Once your CSS files are downloaded, they are cached and indexed in browser folders, allowing future page views of your site to be rendered and painted in the browser very quickly.
        When using 'link' with style sheets, always add an explicit "media" type as an attribute (see code example above). "media=screen" is the best value, which is used for desktop/mobile display. If you have developed a "print" sheet for your pages, add a separate "media=print" attribute and link for those, as well. Never combine "screen" and "print" CSS rules and selectors into a single sheet, by the way. That just confuses browsers. Besides, the various @media rules are not widely supported in older browsers, so will fail. As a side fact, "media=print" sheets are always asynchronously downloaded by the browsers, so are purposely delayed. They are not needed until a user prints a web page, so browsers do not stop rendering pages waiting for these "print" pages to download (see further discussions of this in my "preloading" information below).
        There are other media types, like "all", "handheld", "projector", "braille", "speech", etc. But I do not recommend you use any of these, as again, they all have poor browser support. Do not use "media=all" in particular. Why? "all" is dangerous to use for many historical reasons. "all" did not work in some older browsers like Netscape 4 Series and some very early Internet Explorer browsers. The "all" media type caused errors in those browsers when determining screen or browser style sheets, so most developers resorted to "screen" which today is universally supported in nearly all web browsers, old and new, as the default media type for web browser style sheets. The "all" media type also caused errors in many early versions of Mozilla browsers, for example, when combined with "title" use, triggering "alternate" styles (optional style sheets by the browser). Not good, so avoid "media=all"!
        By default, all linked style sheets are a "persistent" types of sheets, meaning, they are always applied to your web page's HTML until you offer alternative sheets for users to pick inside their browser. Your basic linked CSS sheets are by default always persistent as long as you do not add a "title" attribute in the 'link' element and leave off "rel=alternate", which you should always do (see my code sample above). You can provide one of the other two style sheet 'link' types for a user to choose from. These types are called "preferred" and "alternate". But I do not recommend you use any of them, as browser support is still poor. Most users do not ever "choose" alternate style sheets anyway. Almost all web users accept the "persistent CSS" files you provide them.
        Note that you can force removal of an external CSS sheet previously called from your server by the browser and cached by changing the URL in the "href" attribute to end with a unique or random query string value ("style?v=abc"). This will force the URL to have change in the browser and enforce a new CSS file download from the server. I recommend you control caching of your 'link' CSS files this way, and ask the browsers to remove their cache of your CSS files after every website update that occurs. You can easily do this by changing the query string "v" value inside the "href" attribute and adding a version number, random number, or changed text string to the end of its URL like so: "?v=1.0.0.1" (website version number) or "?v=20210605" (date or number value). These are not "magical codes". They just alter the "href" URL to the style sheet enough that the browser does not recognize the path associated with the file any more. This trick will force the browser to then clear its cache of styles for your web domain, renew the link, and re-download a fresh copy of your CSS style sheet, refreshing the look-and-feel of your website instantly.
      • RSS News Feed - Delivering a news feed to users via RSS (XML) is not as important as it used to be online, simply because news has increased in scope and speed online, using many other sources. In addition, mobile news via phone apps has replaced a large volume of the news feeds delivered online. However, if your site delivers such feeds, in the code above is an example of how RSS links are set up using the 'link' element.
      • Prefetching, Prerendering, and Preloading Style Files: In 2022, some in the web community have "suddenly" become concerned with how CSS loads in the browser. We have never had this issue the past 20 years......so what is the concern now? I will explain. With faster and faster fiber optic lines going to houses, and super fast 5G mobile bandwidth nearly implemented in all the towers, there is little proof of a few kilobytes of extra CSS causing web page rendering delays, blocking file downloads, or rendering DOM slowdowns. But some search engines and developers persist with their concern over "blocking CSS", despite the facts to the contrary that this is not a major issue. The real concern for slower web pages today is the fact many developers are downloading HUGE JavaScript API libraries to browsers to simply render a few lines of text! Yet, some new developers have become worried that 'links' of external CSS files may be blocking their megabytes of scripting files from downloading fast enough. This is simply not the case! (You can read more about my analysis of this point in "Why Do my Web Pages Take So Long To Download?" below.) The fact is, you should rarely if ever "preload" CSS or attempt to "hijack" the browser's natural ability to download linked CSS files. For starters, most modern browsers only allow 2-6 max parallel open connections from the browser to the server. Slow web host providers and networks is another bottleneck you cannot control that could affect your external downloads. Third of all, the 1-5 megabytes in a typical JavaScript API library download in web pages today is a waste of bandwidth. Downloading dozens of script files is much more of a problem than one or two tiny 10-50 kilobyte files of CSS. CSS files downloaded over 'link' elements has never been a big problem the past 30 years or it would have come up years ago in browser groups. In addition, CSS blocking capabilities are very fleeting compared to the wait time required for shared connections to open up in the browser. With fast optic cable upload and download speeds now, establishing a connection is more of a delay than the actual download speeds for most browsers. So, you should rarely worry about links and CSS slowing down your homepage's "first paint", as they love to call it. But if you are concerned about this issue, I will discuss use of these new attributes below.
        One way authors have started to cope with this issue is to use the new HTML5 "rel" and "media" attributes on 'link' elements to trick browsers into downloading files faster and in parallel with other processing running in the browser. They sometimes have minor performance gains in terms of browser speed in rendering web page CSS and HTML. The "prefetch", "prerender", and "preload" settings can be used in 'link' elements to force the browser into loading some style sheets asynchronously (delaying download) as secondary style sheets that might not be needed until later. The "rel" attribute specifies the relationship between the current document and the linked document. The "media" attribute defines the media "type" of the file being downloaded, which helps the browser prioritize and parse certain file types. Using the new "pre" features listed above allows you to now load resources, like CSS files, in the background when the browser connections are available, and without affecting synchronously loaded resources like CSS files that often download before the HTML does.
        When browsers load CSS synchronously, they temporarily halt all page downloads, scripts, and rendering while the CSS is downloaded and parsed. When this process is done, the HTML resumes its download, parse, and rendering phase like the CSS file. The browser then applies these downloaded and parsed style rules to the "render" stage, and with the HTML and builds the final painted DOM in the browser. Most of the time you want this feature to work as is, naturally, as you don't want unstyled HTML to flash waiting for a "preloaded" or delayed CSS file. But CSS in a 'link' element is placed in the head of the document before the 'body' element and its content HTML for a reason. Page order was designed this way on purpose. That is why browsers synchronously start downloading CSS first. Delaying HTML is to be expected in this model. Without the style sheets, page rendering would be delayed, anyway. However, in rare cases, certain large unused resources or style sheets can add additional wait time to HTML rendering. Using these preloading tricks to delay certain files can mean your HTML arrives slightly faster. It thus removes a slight delay in the page rendering by the browser. This is based on the fact some CSS is just not needed in your homepage, only in later web pages a user might visit. Or maybe its CSS that renders other parts of the page that are not critical. That then gave birth to the "preloading" concept. However, I don't recommend you use these features or ever async CSS this way due to limited browser support for "prefetch", "prerender", and "preload". In fact, most older browsers do not support these new attribute values, anyway. So, these features will fail. In many modern browsers support of these features are not implemented correctly, ignored, or not yet complete. I discuss this problem below.
        Prefetch: You can download files, styles, web pages, or other resources before a browser or user needs them in another page or location in your website using this feature. This is helpful when you might want to pre-load a large batch of images or styles in your web site before a user clicks a link to visit the a web page that contains them. The browser will call such resources down and store them in cache until needed. However, its not reliable. Some browsers may wait till the browser is completely "idle" or simply ignore these calls (Firefox). By then, a user could have clicked a link to your page needing this cache and instead find an unstyled page. But, when this works it can speed up external pages a user might visit. Just realize some browser could ignore or fail to download such files. Note: No Safari desktop or iPhone, IE 10 or less, or Opera mini browser supports this feature. So use sparingly.
        Prerender: You can also choose to prerender or download a whole web page and have it rendered and ready to view before a user chooses to click a link. This has the effect of caching everything on other pages a user might access from the current page. This feature, when supported, creates the DOM, styles the page, and executes any javascript in the page, as well. When a user clicks a link, the new page is supposed to be "swapped out" for the current page. At least, that is how it is supposed to work. Be careful as this can affect the current page's connections to the server, the browsers CPU usage, and resource access should data on the other pages be very large and take up too many processes in the user's current web page. You also have to be sure a user will visit one of these prerendered links before deciding to so. How do you know? Note: No Firefox browser, Safari desktop or iPhone, or IE 10 or less browser supports this feature. Only Chrome, Opera, and the latest IE11/Edge support this. So use sparingly.
        Preload: This attribute value for "rel" is very much like its cousins, "prefetch" and "prerender", except the "preload" version cannot be ignored by web browsers, is not a low-priority call as the others, and the browser MUST download the resources called into the browser cache as soon as the opportunity becomes available. This makes this attribute a little more reliable as it forces the browser to load style sheets, images, and other files behind the scenes until needed. As with the other types, this has the effect of placing everything downloaded this way into the browser's cache (unless of course, this feature is not supported in the browser).
        Developers in 2022 have started to use "preload" to solve two main problems: The first is to force cache of resources needed in other web pages before a user visits them (traditional use for external pages only) with a much higher guarantee they will be there. But they have also started to use this technique as a "hack" to force some of their secondary style sheets in the current page to download asynchronously in the background while the HTML downloads, preventing additional "blocks" of the page render process. The web page is thus available much quicker for the rendering of the DOM in the current page. This first strategy forces the browser to cache resources for other web pages, while the second type applies them to the current one. Both types only works if "rel=preload" is supported in the browser. But I offer an alternative "media=print" strategy for the second type that works much better without "preload". In my code example below, the first type of external resource download and caching strategy is shown using a traditional "preload" call to a file:

        <link rel="preload" as="style" href="style.css" />

        Note: No pre-2018 Firefox/Safari, Internet Explorer 1-11, or Opera Mini supports this "rel=preload" feature, including a range of Android browsers. So use sparingly.
        The second type of "preload" use is now being used to affect the processes in the current page of a typical site to hide secondary media or files that might be needed but which block the main CSS style sheets and HTML from being rendered. In these next two examples, you must implement a series of JavaScript "hacks" to "trick" the web browser into preloading your style sheets in the background (a form of asynchronous download) then switching it back to its normal synchronous state so its available by the browser for rendering HTML in the current web page and all others a user might visit. When the files are complete, they are accessed immediately by the browser and available for use. They are just queued up for download or delayed. In this latter use of "preload", if you are concerned one or more of your style sheets may be "blocking" page rendering in the current page, and you do not need the style sheet immediately, you can delay the file's download by using one of these two tricks below. The first one avoids the "preload" feature (since its has poor browser support) and uses a very old "print" media trick to delay the file download much as a print sheet would do. When the file is downloaded, JavaScript switches the style sheet link back to a normal type. the second example tries to use a normal "preload" but also uses JavaScript to switch the file back to a normal style sheet accessible by the browser when its complete. This second version has less support in browsers:

        <link rel="stylesheet" href="style.css" media="print" type="text/css" onload="this.media='screen';this.onload=null;" />

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


        These bits of code trick the browser into loading the CSS files quietly in the background when the browser has an available connection. This then removes one more delay caused by these secondary CSS files that are not immediately needed in rendering the web page. The primary CSS in normal links now download slightly faster into the browser in parallel with the HTML, without these other sheets "blocking" or delaying them in some way. But this only benefits you if these secondary CSS files are so large they delay downloading before HTML downloads and renders. In most cases CSS still load in parallel with HTML just fine, even if its delivery begins before HTML starts. Unless it uses up all available connections, this should rarely occur. In the first example above, the "print" preload version asks the style sheet to perform as a delayed "secondary" print style sheet. All browser delay print sheets by placing them into a queue where they download last and only as connections become available, which is often AFTER the web page has been rendered in CSS and HTML. So, this trick would would be used more often for delivering styles not needed in the primary page render. For that reason, people often move style rules that are not critical to the rendering of the homepage out of the primary "screen" sheets and into these secondary "tricked" ones so they are not part of the DOM render and paint delay. The main idea here is to speed up viewing of your homepage web page for new visitors coming to the homepage by just delivering enough styles to display it quickly, while delaying the ones not needed right away in the main synchronous style sheets. The problem is style sheets are so tiny in size, that this trick has almost no real positive effect. In the second example above we use the true "preload" setting, but switch the "rel" to "stylesheet" after the file downloads. Like the "print" version, this secondary file now performs like a normal style sheet and is available to all web pages including the current one, after the JavaScript switch. The disadvantage here is that "rel=preload" does not have the same reliable support in browsers as "media=print" does, so is likely less effective.
        The idea in preloading all these files, then switching to using them in the current page, is to not make the browser wait for these files before rendering the HTML tree in the DOM. But that is rare. All these tricks force all such style sheets in your homepage that do not affect initial rendering and paint of the home page to download quietly in the background, asynchronously. That would have some minor advantage if you had a large number of very large style sheets loaded in your homepage. But often loading external style sheets does not delay rendering site-wide as other pages will now access these cached external sheets for the rest of the user's experience with your web site. That could be thousands of web pages that use that one set of CSS files you asked your user to wait a few milliseconds on your homepage. The trade off is more that fair!
        Again, ask yourself if preloading resources like this is worth the risks? Eventually, simply downloading the asset normally without preload overpowers the risk of this failing in non-supporting browsers or running more elaborate scripts so you can shave off a few fractions of a second of download time. Some people today try and speed parsing of linked CSS files which always must load synchronously before HTML, anyway. Using "preload" to trick the browser into loading the styles later then switching it back to synchronous status to prevent a small amount of extra CSS text seems like a convoluted way to gain minimal advantage. I don't recommend you load CSS using "preload" for that reason, and due to limited browser support in 2022 for "preload", and the fact these tricks could fail in some browsers. Again, failure is older browsers is the main point of contention, here. If you are inside a network and choose to use these tricks, you will have much better success. If you really look at what these developers claim is an issue in modern web pages using external linked CSS, it really becomes an attempt to help a narrow subclass of "special" users who get frustrated waiting on their new phones a few hundred milliseconds for anything to appear (which are generally people that have attention problems or who are adrenaline junkies). It is another reason to avoid this "preload trick" as it has zero affect on both page rendering and the majority of normal web users today. Worst of all, it runs the risk of failing and screwing up your style sheets and web pages. You might end up with NO style sheets in some older browsers! All this is just more "bloated JavaScript" shoved down the throat of the browser, anyway. If this was ever a problem long ago when we had very slow 14.4 (kbit/s) baud rate modems over crackly phone lines we would have caught this "blocking" issue, as would have numerous web browser vendors. So, trust me, its not a problem! Your linked CSS files work fine as is. Always rely on solid HTML5 first before relying in these "hacks".
        One other point must be made on this "preloading" of linked CSS files. It appears that Google's new Lightspeed page ranking system up until now encouraged web developers to fix web pages for faster download speeds in the browser to reduce wait times to milliseconds. But recently they flip-flopped from page ranking based on speed to a form of content-based ranking (the old search engine model). The fact they now have flipped back and forth from page rendering speed concerns to a more content-oriented ranking shows they are struggling to manage heavily JavaScripted websites without a solution other than to demand web site owners ignore the JavaScript download disaster and try and squeeze blood from a turnip and force us to check every little external file and image download for speed improvements, while ignoring the 1-5 Megabytes of scripts being pushing over the wire and into the browser. This is their attempt at trying to rationalize page rank away from the actual website content rewards in order to cope with the ever-increasing layers of Angular JavaScript now clogging up the search engine bots, which directly delay most of the search engine performance, anyway. So, the problem is not your tiny Cascading Style Sheet files, my friend. Demanding authors squeeze every millisecond from tiny CSS file downloads through minimization and other preprocessing, while rationalizing use of these gigantic multi-megabyte scripted frameworks, shows these corporations know they have helped "gum up" the World Wide Web with more bad web application technology, instead of making it better with simpler, faster browsers and search engines.
      • "Content Delivery Networks" (CDN) - Many new developers love to throw around the idea of using a "CDN" or external service on the Internet for all their CSS and script files rather than hosting a handful of tiny CSS text files on their own hosting platforms. If style sheets and scripts are not sitting on their own servers and are free elsewhere, the thought is, this is a great idea, right? The idea that you don't have to host anything when its free on someone else's server seems genius at first, but its not.
        The problem is this solution divides up your website's external files and creates huge dependencies that can fail, destroying the display of your website. CDN's can also be slow, hacked, down, insecure, or simply block your IP at any time, preventing your site from getting critical CSS files it needs to render properly. You might say that's never happened. But it has! And as security increases online, it will. So, I do not recommend using CDN's.
        If you can host your own giant JavaScript files and HTML, why cant you host your own CSS, I wonder? Some say CDN's are faster, but it seems pointless and lazy if you do not trust the speed and reliability of your own host provider. But if you want to try this CDN "trick" and rely on externally hosted CSS files, simply use the CDN code sample above, then replace it with links to your favorite online CSS library. I have added an extra BONUS script in the 'link' element above that maps back to your personal backup copy of the script if the "Content Delivery Service" URL fails. Also, this code sample version uses the new "integrity" attribute that some CDN's require (private encrypted key) and which prevents "cross-origin" rejection by some browsers and servers. Without this encrypted values some browsers might not allow you to use these unknown and unverified cross-domain, externally hosted files (some of which could contains viruses, by the way).
      • CDN and referrerpolicy="no-referrer" - Use this attribute and value if you want to block the external CDN sources from getting your user's referrer or source information. This blocks the origin data sent to their servers, which shows up in their logs every time a visitor of your web page uses one of the video or files imported into the iframe. Note: If this prevents you from accessing the external file, then you might have to remove it.
      • "Canonical" URL's - You can help search engines know the "preferred" URL path to use for all your web pages, using the "canonical" URL version set in a 'link' element. Some people are concerned about duplicate web pages and search engines seeing different versions of the same web pages accessed with different URL's. Search engines will punish you or lower your ranking in search engine listings if they see too many duplicate links to the same page content with different URL's. To help prevent that, you can tell search engines and the browser what the "preferred" or base URL all pages in your site should use via a special "canonical" link. This does not affect your page's actual URL or links, and is optional. Its just tells search engines the base link to use for all your pages so they do not duplicate the same content and punish you in search rankings if you use various URL formats. This is especially important if there are secure and non-secure URL's in your website links, like "http://" and "https://". In most cases, search engines figure this out naturally, so this 'link' format is not required.
      • "Prefetched" URL's - Like "canonical" links, this "prefetch" version of the 'link' element is also a new feature and optional. There is no guarantee it will help improve anything in your website. The first thing most modern browsers do as they load your HTML page is determine if there are any outside domains associated with external URL's or page resources added in your website. If so, to access each resource, the user's browser often must do several request-response calls, including a separate DNS lookup and connection for each resource before calling its actual file. An example of this problem is the CDN link and URL above. These domain lookups can delay requests of content (very slightly) as they must often resolve via foreign DNS servers first. If your site has lots of these calls, you can add these special links and list multiple domains at the top of your page in the 'head' element. Consider adding multiples of these new DNS lookup links, one for each foreign domain used, to force a preload of DNS resolutions early, which can speed up your page as it requests resources later. If your pages are chocked full of advertisers or other foreign URL's, adding these prefetch links may really help. Just remember most browsers today only have a half dozen open connections max, so you are limited anyway. Also, HTML5 support for this type is still sketchy.
      • "Preconnect" URL's - You can "preconnect" to website servers as well to set up early handshakes and connections with servers before an HTTP request is actually sent. Often these external connections to unknown servers are slow, are stalled, blocked, or broken. Adding this feature, you hope to grab any available connections in the browser that are not downloading giant scripting libraries and try and make early "preconnections" to these foreign servers. You can even add "crossorigin=anonymous" or "crossorigin=use-credentials" and send your own credentials to help connect to these domains outside your own while avoiding the blocking cross-domain CORS issues that might occur later in a user's browser. HTML5 support for this is still sketchy, however.
    3. The Importance of Links and CSS: I cannot emphasize this enough: ALWAYS USE EXTERNAL STYLE SHEETS! I always use linked style sheets in all my web pages so they get downloaded one time and cached for all the pages in my website. Linked CSS sheets are fast, download in parallel with the rest of the websites connections, and help you manage styles better using large cached sheets. My own CSS framework of files includes a rich "reset" style sheet that overrides all browser UA default style sheets and reformats all browser elements and types to a common set of base element styles before applying my main classes on top of those element styles. It allows your pages to look clean and consistent across many old versions of browsers going back 20 years with no extra styling needed for older agents. So, I rely heavily on linked sheets and always avoid embedded/internal and inline styles.
      Old Browser Bug: IE3 used to remove all linked sheets but the last one listed in the head or your web page. So, I re-order my linked style sheets so my main CSS link is the last one listed, just to cover this issue or any browser that erases linked style sheets like this from my web pages.
    4. More on the "media" type Attribute: When downloading CSS files using the 'link' element, the browser is often quite sensitive to the "media" type attribute value you provide. The "media" attribute tells browsers the type of media or device your style sheet should be applied to and how your style sheet should be used for your device and parser. Most of the time this is the browser. The default is no "media" attribute, meaning your styles affect any and all devices (this is the same as "all", which means it works for all devices). In old HTML 4.1 the default was supposed to be "screen", but it seems many older browsers ignored this and set it to "all" implicitly. For HTML5 browsers today, the default is now "all", meaning your style sheet will be read by all types of devices. However, this is not the same as explicitly setting "media=all". It is almost always best to set it to "screen", which means your styles only apply to most computer or phone browsers. In the old days most browsers supported "handheld" which was for mobile only. But since PDA's and handheld Palm devices went out of style after 2008, this type is no longer used. Explicit use of "media=all" was supposed to be supported across browsers. But its use now excludes CSS files from being used in some older browsers like Netscape 4, IE 5-6, and some older browsers who do not understand what "all" means or fail to support "screen" when used. When using "all" in "@import" style sheet CSS calls, IE 4-7 will fail to load the style sheet. Netscape 4 series only supports no media type or "media=screen", and will fail to load the sheet if "media=all" is used. Note that Netscape saw "media=screen" as used for all devices, anyway. Support of "all" in "@media" media queries was also partially supported compared to "screen". "all" could mess up "print" sheets added later ,as some browsers fail to import styles when printing using "all". Because the "all" media type causes so many errors in so many older browsers, I recommend you always use "screen" or "print", which is universally supported in nearly all web browsers, old and new, and never design style sheets for all devices. That is why I am against "all" in the "media" attribute. I am for setting an explicit media type, only. But if you want to use a linked style sheet that can be seen by all devices, I recommend you simply leave off the "media" attribute from your 'link' tag, simulating a style sheet used by "all" devices.
      In the past, 'link' tags without a "media" and "title" attribute not only defaulted to "all" media types in some older browsers (not really "all" the string value, but just that the style sheet should apply to all devices), but meant your linked style sheet were seen by all media devices as optional or themed "preferred" sheets. So, if you did not want to limit your styles to just browsers ("media=screen"), but wanted to make sure a sheet is used by all media, you would leave off the "media" attribute and your sheets would affect all devices (both "screen" and "print", for example). If you instead tried to use "media=all" explicitly, because some older browsers did not know "all", it would fail and the browser would ignore the style sheet completely. Your pages then appeared without a style! If you wanted the "all devices" effect, your only trick was to not use "media" but suffer the fact your style sheet is not "persistent" as described above, but an optional "preferred" or themed sheet a user could change in their browser now. Another bad idea.
      Never add "title" attributes, either, as their presence changes your "persistent" sheet to one of the alternative or optional types that is often removed from your pages until a user chooses it. So again in summary, make sure your linked sheets never have a "title" attribute, always use a "media" type attribute, never use "all", and set it to "media=screen" or "media=print" to avoid problems.
    5. "Persistent" versus "Alternative" Style Sheets: Again, do not get confused by this information describing types of style sheets below, as it does not really matter as you should never use alternate style sheet systems, anyway. (You can skip this section if you like). But I thought I would explain some gotcha's when using 'link' element attributes, which you want to avoid.
      There's three different types of stylesheets that may be included on a page: "Persistent stylesheets" are the default and applied no matter which theme a user might choose for styles. "Preferred" stylesheets are themes stylesheets optionally applied. And "alternate" stylesheets are not applied by default unless explicitly chosen by the user. The latter two are user choices, so do not use them. Just use the default. You always want to use "persistent" (the default) and ignore the rest as support is spotty for anything other than the default. The only reason to use the others is if you decide to use an internal company website and offer users a rich set of CSS interface themes they can switch out to improve performance and usability in your web application. In that case I would use CSS "skins", not alternative browser style sheets you deliver, though. Users rarely if ever change style sheets in web pages, anyway.
      Use of the 'title' attribute on 'link' elements and "persistent" style sheets is what triggers your sheets to use the other two types as a "preferred" style sheet in many older browsers (not persistent, as normal sheets). So avoid it! Sheets with the "title" attribute added plus the "rel=alternate stylesheet" attribute triggers the "alternate" style sheet setting for your sheet that users can optionally choose when wanting to replace the "preferred" sheets. That is just one more reason to avoid those two attribute settings. To support this idea, older Mozilla browsers in the past always saw styles with just "title" as "alternate" styles, confusing things a bit more. So, my recommendation is always remove "title" attributes for all link tags and avoid the "rel=alternate stylesheet" setting. Removing "title" will make sure your links styles are always flagged as "persistent" types (default) in older browsers. Just use "rel=stylesheet" to make sure browsers identify your style sheet correctly.
    6. Cascade Order and Linked CSS: Does the order of linked style sheets in the <head> of your web page affect the cascade order of similar style rules on elements? It is an important question. It turns out it DOES in modern HTML5 browsers, but did NOT in many older browsers (pre-2010)! Why? Older browsers used to have a very good rule the W3C used to require they follow. It basically said that no matter where external <link> styles appear in the <head> of your web page, "embedded" or <style> CSS was always last in the order set inside the browsers cascade memory, not in your web page. In other words, embedded styles always cascaded over linked styles using the same selectors, even if you placed external linked CSS AFTER embedded CSS in your web pages. Linked external CSS elements always came before embedded CSS in the memory of the browser, no matter what physical order your code used. This is NOT the case in newer HTML5 browsers, I found out. This might be a subtle issue to you, but if you stack lots of "element" style rules in your external and internal style sections of your web page 'head' element, rules that use the exact same selectors, if you do not order your linked external CSS elements correctly then you might see some cascade over others, unexpectedly in newer HTML5 browsers! Order of styles now matters in your pages, where in the past it did not. The reason newer HTML5 browsers now strictly honor specific style sheet "source order" in the "head" of your page, regardless of linked vs embedded types, is because HTML5 has gotten lazier and looser in defining such things. In other words, be careful in the order you place linked and embedded styles, as they do matter today. Embedded sheets no longer have higher source order over linked sheets, as they did in the past. To match old and new browsers so they both work the same using external and embedded sheets, ALWAYS add your linked sheets (<link>) above your embedded ones (<style>) in the head of your page.
      Unfortunately, newer browsers today using HTML5 decided to ignore W3C and Web Standards, so now order matters. This is counter-intuitive, so I recommend you follow the rule above and you will have no issues with CSS cascade order going forward in any of the browsers you support.
    7. Avoid All Internet Explorer "Conditional Statements": In the long and troubled history of Internet Explorer and its support/non-support of HTML and CSS, many developers over the past few decades solved those cross-browser issues by hiding specific style sheets from all browsers but IE using special "Conditional Statements". In the past, many authors tried to address the numerous CSS bugs in Internet Explorer by using special code that hid certain linked style sheets from other browsers, but which were only specific to a version of Internet Explorer. Without going into the long history of this type of trick, I can say today this technique no longer works for newer IE browsers (version 10, 11, or the new Edge browsers). So, it is time to retire them completely. An example of such code is shown below so you know to avoid this code trick when trying to design CSS for older IE versions. This code below hides two linked CSS files that have special CSS hidden from all browsers but two older, specific Internet Explorer browser versions):

      <!--[if IE 8 ]>
      <link media="screen" rel="stylesheet" type="text/css" href="/styles/ie8only.css" />
      <![endif]-->

      <!--[if IE 9 ]>
      <link media="screen" rel="stylesheet" type="text/css" href="/styles/ie9only.css" />
      <![endif]-->

      * DO NOT USE THIS CODE! Because IE is nearly dead, plus IE 10-11 no longer supports these conditional statements. I do not recommend you use these IE coding tricks going forward, but instead cope with older IE versions using other techniques (I use a new CSS framework I built which uses "@import" rules IE 1-7 cannot understand and which hides my CSS style sheets from all IE 1-7 versions, giving these older browsers plain white HTML pages). Avoiding these custom page-by-page IE hacks means one less customization you now have to worry about in your web pages when dealing with the complexity of styling for older browsers using 'link' elements. (The ONE EXCEPTION to this rule is in my "Best Practices" section below called "How to Force New HTML5 Elements to Work in Old Browsers" where I encourage the use of IE Conditional Comments for forcefully adding missing HTML5 elements to non-HTML5 IE versions 1-8 browsers using a script.)
    8. The Myth of CSS @Import Render Blocking: The CSS rule "@Import" is often used to make additional calls to external CSS inside linked CSS files. A 'link' with @import calls to other external files is a very common practice and fully supported by all CSS recommendations today and 20 years ago. But sadly, some developers have started to demonize the practice unfairly, as a technique that causes "blocking" delays of other linked CSS style sheets. The fact is, this is completely false.
      When using the CSS rule "@import", the idea is to break up reusable CSS into files that can be delivered in pieces as needed. Often these CSS styles are placed into a single, parent linked CSS file so all the import calls are managed in one file. Once this parent CSS file downloads, any import style sheet calls inside are then made from the parent file. Some claim these calls then add additional download time as they are "render-blockers", meaning they cause some CSS to no longer download in parallel with the other synchronous sheets, like other linked sheets are designed to do. It turns out all that is completely false!
      In fact, multiple imported style sheets inside a linked style sheet all download in parallel relative to each other, with no blocking issues ever, and use shared connections for added speed in most browsers. The "@import" style rule only adds one extra call when combined with CSS styles inside the same parent sheet as the importing of other sheets must make one call in addition to the parent sheet call that holds them. Any delay here is on that one extra connection, not the import call. Thats it! The parent sheet that holds imports starts the new required connection then downloads all internal import sheets together as long as there is no other delays in receiving its own CSS. My sheets never have any additional CSS, only more imports. Only old Internet Explorer browsers had some inability to download imported files in parallel with other linked sheets. The main way to reduce render blocking is NOT avoiding use of "@import" CSS rules, but by using fewer external files and smaller files, like smaller images and less JavaScript. Most modern browsers have a default connection limit of 6 connections anyway, as I have mentioned, so parallel downloads of numerous imported CSS files does not speed up CSS if scripts or images are being downloaded in parallel via those few connections. "@import" isn't affecting parallel downloads of files as long as you avoid combining them with other raw CSS in the same file. I never do this, so using @import is a viable CSS strategy to use in connecting to multiple CSS files in your web page and to hide cutting-edge CSS3 from older browsers. The "myth" of these "blocking" claims has been exposed and should now be ignored. It is 100% safe to use @import in CSS linked files to download more CSS you might need without any worry of page render delays or blocking of other linked CSS files.
    9. Browser Support: 'link' elements have wide support in nearly all browsers, old and new. So, they are fully supported.
    <listing> listing

    Listing

    <listing>This element shows content that used to act like preformatted text.</listing>

    This element showed content that used to act like preformatted text.
    My Recommendations:
    1. The 'listing' element is a deprecated element once suppported in old HTML2. Because 'listing' is no longer supported in HTML5, do not use 'listing' but use the <pre> element instead.
    <main> main

    Main

    See also <header>, <nav>, <footer>, <section>, <article>, and <aside>
    <main id="main" aria-label="Main Content" >Main</main>
    Header
    Main
    Footer
    * A typical web page structure is shown above.
    My Recommendations:
    1. The 'main' element is new in HTML5 and defines an independent, self-contained piece of page content. It is used for defining a larger block-level area of content in a web page. Typically, the 'main' element contains the text or primary content area of a web page. In HTML5, 'main' is part of a set of new structural page elements that define the overall layout of most HTML5 website pages designed today (<header>, <main>, and <footer>, etc.).
    2. The New HTML5 Structural Elements include: header, nav, main, footer, section, article, and aside.
    3. The New HTML5 Page Structural Elements: In the old days of the Web, the 'div' element was typically used in HTML to wrap around larger web page structures that defined major content sections in millions of web pages. To assist that feature, we often gave these 'divs' an 'id' attribute value of "main" or "content". These new 'header', 'main', 'footer', and other HTML5 layout elements have now replaced 'div' as the top level containers of your web content and structure. The 'main' element has no special attributes or design other than this new structural or layout semantic, and should perform like a 'div' or any block-level container element. However, like 'div', it can also be styled.
      Always use the 'main' element to hold all your main page content. Use 'header' for top-of-the-page logos and page navigation. Use 'footer' for secondary navigation, copyright, privacy statements, and other supplemental content listed at the bottom of your page. You no longer need to use the 'div' element for these layout sections, as before. Because 'main' and the others are universal structural elements in modern HTML5 pages now, you will see them appear in grids, flex boxes, and other CSS design and formatting structures. So, understanding their purpose and using them across all these different page frameworks is crucial to using HTML5's newest layout elements and thus fulfilling HTML5 "best practices".
    4. I like to always use a unique 'id' attribute with a value of "main" on my 'main' element so they can be recognized and manipulated by other designers using JavaScript. In the old days we used a 'div' with "id=main" to help us identify this these 'div' section from others sections quickly in a layout. So, this idea is simply a carry-over from that design concept.
    5. ARIA: The 'main' element is a top-level, "self-describing" structure recognized by most modern screen readers without additional assistance. In the case of 'main', it is recommended you add an ARIA label of "aria-label=Main Content".
    6. Cross-Browser Support: Older, non-HTML5 supporting web browsers (pre-2010) will not know what these structural HTML5 elements represent or how it should look. They have no design format by default, other than performing as a simple block-level 'div'. However, in older browsers, this element usually needs a CSS style so it does not float to the left or right of your other content blocks in non-HTML5 compliant browsers. Remember, most browsers that find an unknown element will set their CSS 'display' property to "inline", thus destroying the design of these new HTML5 layout elements. For this reason, in my "reset" style sheets, I always assign it a style of "display:block" and "float:none" to make sure these elements perform as a traditional 'div' in older browsers that do not support HTML5. But, I fully support the use of these new HTML5 elements in your web pages, despite their larger non-support in older browsers.
    <map> map, image map

    Map

    see <area> <p>(rollover the image map below)</p>

    <img src="images/www.jpg" width="255" height="200" usemap="#mymap" loading="lazy" alt="World Wide Web Image" title="World Wide Web Image" />

    <map id="mymap" name="mymap" title="World Wide Web Image Map">
        <area shape="circle" coords="80,130,40" alt="What is the World Wide Web?" title="What is the World Wide Web?" href="https://en.wikipedia.org/wiki/World_Wide_Web" target="_blank" rel="noreferrer nofollow noopener">
    </map>

    <ol>
        <li><a href="https://en.wikipedia.org/wiki/World_Wide_Web" title="What is the World Wide Web?" target="_blank" rel="noreferrer nofollow noopener">What is the World Wide Web?</a></li>
    </ol>

    (rollover the image map below)

    World Wide Web Image What is the World Wide Web?
    1. What is the World Wide Web?
    My Recommendations:
    1. The 'map' element defines an image map. It consists of 3 major pieces: An image, a map which defines click-able coordinates in the image, and a list of alternative hyperlinks for users that cannot interact with the image map.
    2. A matching 'img' element is associated with a 'map' element to create a click-able "image map" that allows users to click visual points in the image that link to other web pages with more detailed information. It is essentially a non-textual, visualized menu concept.
    3. In the 'map' element you can define specific "click-able shapes" as invisible rectangles and circles connected to visual elements in an image using the 'area' element inside 'map'. The 'map' element may contain a number of different area tags with shapes that defines different click-able areas in the image map.
    4. The 'usemap' attribute value of the 'img' element connects the image to the 'name' attribute value of the 'map' element. This creates a relationship between the image and the map.
    5. The 'id' is optional. But as with forms, 'id' and 'name' should both be defined here and with the same value in case one or the other is not supported in the browser.
    6. The 'coords' element defines boundaries in the 'area' element that control click-able dimensions in image map. Rectangular values use a pair of (x,y) coordinates for the top-left begin and bottom-right end points of a rectangular inside the image boundary. For a circle, the (x,y) coordinate defines the location of the center of the circle in the image boundary, with the 'y' being the radius of the click-able circle defined.
    7. Other attributes that are useful include the 'href' attribute which defines the URL location to visit when an area defined by coordinates is clicked. The 'target=_blank' attribute in 'area' forces a new browser window when clicked. I like to add informational text descriptions on rollover events using 'title' and 'alt' attributes on the 'img', 'map', and 'area' elements, as well.
    8. I have added an additional accessibility text link list under the map which can be hidden with CSS 'visibility:hidden' or 'display:none'. It is recommended by the w3c accessibility guidelines to add these links in some form as alternative hyperlinks for non-visual people or screen readers.
    <mark> mark, highlight

    Mark

    <p>Make sure you <mark>highlight every important topic</mark> listed in the document.</p>

    Make sure you highlight every important topic listed in the document.

    My Recommendations:
    1. The 'mark' element defines a piece of inline text that must be "highlighted" for importance, special interest, or reference. This element is new in HTML5 and represents text that is significant enough to the page or paragraph that it must have a colored background and stand out. This is often text taken from an original document where the author did not indicate the text was important, but the user did. This is different from 'big', 'strong', or 'emphasized' text which affect manuscripts where the original author has indicated text that is important. The highlighted color is often yellow, like a typical highlight marker would have.
    2. Most HTML5-supporting browsers will highlight the background of "marked" text with a bright yellow background color. You can modify this value in CSS as needed. Remember, all non-HTML5 browsers will not understand this element nor color it. That is one more reason to apply your own CSS custom rules to these elements to make sure the marked text has semantic as well as visual meaning in all browsers, old and new. A CSS example you can use to style the 'mark' element for old and new browsers is shown below. This is what most HTML5 browsers use, anyway:
      
      mark {
          display: inline;
          background-color: yellow;
          color: black;
      }
      
      
    <marquee> marquee

    Marquee

    <marquee behavior="scroll" direction="right" scrolldelay="85" style="color:red;">This is some text that should scroll across the page</marquee>
    This is some text that should scroll across the page
    My Recommendations:
    1. The 'marquee' element is deprecated now and was a non-standard member of old HTML4. 'marquee' used to create a section of inline text which scrolled across the page, slowly. 'marquee' could still work in modern browsers, but I do not recommend you use the 'marquee' element.
    <menu> menu

    Menu

    <button type="menu" menu="contextmenu" title="Click to Show a Context Menu">Show Context Menu</button>
    <br /><br />
    <menu type="context" id="contextmenu">
      <menuitem>Menu Item 1</menuitem>
      <menuitem>Menu Item 1</menuitem>
      <menuitem>Menu Item 1</menuitem>
    </menu>

    Below is a button that when "clicked" would normally trigger a context menu to appear. Instead, in most browsers, nothing will happen. You may just see a "box of text" which my style sheet system has tried to style on the 'menu' element so it looks presentable. But its not the toggled "context menu" you expect, as 'menu' elements are not currently supported in most browsers.



    Menu Item 1 Menu Item 1 Menu Item 1
    My Recommendations:
    1. The 'menu' element is a new HTML5 element representing a list of navigation elements a user can click or activate. It usually describes a collection of menus items grouped together, an unordered list of links or buttons, or a context menu that might appear on focus of button-click. Avoid use of this element as it is not supported in most browsers.
    2. Menu Features: Because the 'menu' element (and its child elements) are not supported by most browsers, I will not go over its features and attributes. Just know that the 'menu' element as designed today would support multiple 'menuitem' child elements inside it, as well as other HTML elements like unordered lists, etc. When fully implemented, it should also have attributes for controlling button-activated items, context menu displays, and other features.
      Most developers avoid this HTML5 element and use a 'nav' element to group HTML items together that look like menus when styled. They often use unordered lists ('ul') combined with anchors and CSS styling to create visually appealing "menu" tabs or buttons in their web pages. These types of menus now carry semantic meaning in screen readers, simply because they use HTML lists rather than just plain anchor links to order menu items. Additional JavaScript would then be added, or CSS pseudo-class events, to trigger dropdown "menu-like" effects. The 'menu' element had promise, as I think the original idea was to enable the browser to create menus for you that would replace all of the technologies listed above. But sadly, the 'menu' element has not matured enough to be usable.
    3. Do not use the 'menu' element, as it is experimental and was only supported in a small group of Firefox browsers in 2022. I think it has been fully deprecated in all browsers now. Use the <nav> element with lists, anchor links, and CSS styling, instead.
    <meta> meta

    Meta

    see <html>
    My Recommendations:
    1. The 'meta' element defines the various meta data found in the head area of a web page. See the <html> element for a full description.
    <meter> meter

    Meter

    also see <progress> <p>
      <meter id="meter1" min="0" max="10" value="2" title="Car Fuel Left as a Number" aria-label="Car Fuel">2 out of 10</meter>
      <label for="meter1" title="Car Fuel Meter">Car Fuel Left (number)</label>
    </p>
    <p>
      <meter id="meter2" value="0.8" title="Truck Fuel Left as a Percent" aria-label="Truck Fuel">80%</meter>
      <label for="meter2" title="Truck Fuel Meter">Truck Fuel Left (percentage)</label>
    </p>

    2 out of 10

    80%

    My Recommendations:
    1. The 'meter' element is new in HTML5 and defines a range of fractional values represented visually as a colored image bar. Note: Each browser displays this "bar" differently. Some may change the color of the bar based on low or high values. This element was designed as a simple way to graphically represent numeric data without complex scripting or 3rd party plugins.
    2. Because this new HTML5 element is not supported in any older browsers, Internet Explorer, or even Trident Edge, I cannot recommend it nor go into detail on its attributes. It does fall back nicely to text inside the 'meter' tags (as shown in the code examples above) when the visual element collapses. But many older browsers, IE, and Edge users will not benefit from that text without the supporting graphic display, which is its hallmark. When supported, the color changes by value vary by browser, or simply do not change at all. So, I would avoid use of this element as it's not widely supported. And when it is, it's implemented inconsistently. Therefore, it doesn't add much value.
    <multicol> multicol

    Multicol

    <multicol col="3">
      <p>Text column one</p>
      <p>Text column two</p>
      <p>Text column three</p>
    </multicol>

    Text column one

    Text column two

    Text column three

    My Recommendations:
    1. The 'multicol' element is deprecated but was a non-standard element used by Netscape browsers to create a multi-column, newspaper-styled text page. 'multicol' is no longer supported by HTML5 and is replaced with flex boxes and grids in CSS. So, do not use the 'multicol' element.
    <nav> navigation

    Navigation

    See also <header>, <main>, <footer>, <section>, <article>, and <aside>

    I have included a styled menu using an "unordered" list to demonstrate how you might use the 'nav' element in your website. 'nav' elements do not create menus or any sort of navigation. They are just placeholders for those things. Keep in mind its best to place the 'nav' inside the 'header' element (as shown below) so everything is managed in a clean, manageable, semantic HTML structure.

    <style>
    /* Here is a very basic menu style I created to show you what is possible inside a "nav" element. */
    .nav_menu {
    display: block;
    width: auto;
    height: auto;
    padding: .5em 1em;
    border: 1px solid #ccc;
    margin: .1em;
    text-align: center;
    min-width: 20em;
    color: #000;
    background:#fff;
    }
    .nav_ul {
    display: block;
    width: 100%;
    height: auto;
    margin: 0;
    padding: 0;
    border: none;
    background-color: #bbb !important;
    text-align: left;
    list-style: none;
    }
    .nav_li {
    display: inline-block;
    width: 8em;
    height: auto;
    margin: 0 2px 0 0;
    padding: 0;
    border: none;
    background: none !important;
    list-style: none;
    text-align: center;
    vertical-align: middle;
    }
    .nav_a,
    .nav_a:link,
    .nav_a:visited {
    display: inline-block;
    width: 100%;
    height: auto;
    margin: 0;
    padding: .25em 0em;
    background-color: #999 !important;
    border: none;
    text-decoration: none;
    text-align: center;
    vertical-align: middle;
    color: white;
    }
    .nav_a:hover,
    .nav_a:focus,
    .nav_a:active {
    background-color: #666 !important;
    }
    .nav_div {
    display:block;
    width:auto;
    height:auto;
    padding:.5em 1em;
    border:1px solid #ccc;
    margin:.1em;
    text-align:center;
    min-width:20em;
    color:#999;
    background:#eee;
    }
    </style>
    <div class="nav_div">
    Header
    <nav id="nav" aria-label="Navigation" class="nav_menu">
    Nav
    <ul id="menu" role="menu" aria-label="Main Menu" class="nav_ul"><!--removes space between inline-block elements
    --><li role="menuitem" class="nav_li"><a href="#" aria-selected="true" class="nav_a">Home</a></li><!--
    --><li role="menuitem" class="nav_li"><a href="#" class="nav_a">Page 1</a></li><!--
    --><li role="menuitem" class="nav_li"><a href="#" class="nav_a">Page 2</a></li><!--
    --><li role="menuitem" class="nav_li"><a href="#" class="nav_a">Page 2</a></li><!--
    --></ul>
    </nav>
    </div>
    <div class="nav_div">Main</div>
    <div class="nav_div">Footer</div>
    * A typical web page structure is shown above.
    My Recommendations:
    1. The 'nav' element is new in HTML5 and defines a navigational region of content, most often within the <header> element. Typically, the 'nav' element contains "navigational" elements or menu items that define the main links to other web pages located within a typical web application. Note: The 'nav' element does NOT create actual navigation or menus, it just holds such elements you create. In HTML5, the 'nav' element is part of a set of new structural page elements that define the overall layout of most HTML5 website pages designed today (<header>, <main>, and <footer>, etc.).
    2. The New HTML5 Structural Elements include: header, nav, main, footer, section, article, and aside.
    3. The New HTML5 Navigational Element: In the old days of the Web, the 'div' element was typically used in HTML to wrap around larger web page structures that defined major content sections, like navigation or menus. To assist that feature, we often gave these 'divs' an 'id' attribute value of "navigation" or "menu" in areas where we had buttons and links to areas inside our websites. The new top-level structural elements, like 'header', 'main', 'footer', and other HTML5 layout elements, have now replaced 'div' as the top level containers of your web content and structure. The 'nav' element is no different. It has no special attributes or design other than its structural semantic, and should perform like a 'div' or any other block-level container element. However, like 'div', it can also be styled.
      Always use the 'nav' element to hold all your menus, links, buttons, or other navigational elements in your page. It is best to place the 'nav' element inside a 'header' element at the top of the page, however, where most major navigational structures often appear. Note that the 'nav' element does not create navigational links, tabs, buttons, or menus. It is simply an "empty container" for those features you must create using other elements, styles, and scripts.
    4. I like to always use a unique 'id' attribute with a value of "nav" or "navigation" on my 'nav' element so it can be recognized and manipulated by other designers using JavaScript. It may seem redundant but it is quite helpful when you are accessing these elements using unique id's. In the old days, we used a 'div' with "id=navigation" to help us identify this 'div' section from other sections quickly in a layout, and describe its purpose in the code. So, this idea is simply a carry-over from that design concept.
    5. ARIA: When used the 'nav' element is a "self-describing" structure recognized by most modern screen readers without additional assistance. In the case of 'nav', it is recommended you only add an ARIA label of "aria-label=Navigation" to spell out clearly to screen readers this element holds the website's navigational elements.
    6. Good Navigation Practices: The 'nav' element is not a top-level element and so is optional. "nav" is a new HTML5 element and using it to contain and control your menus in the page layout is "good HTML practice". But when used, most designers typically add it to the 'header' element so it is contained inside the header at the top of most web pages. However, you can have multiple "nav" elements with different navigational functions in each. Because screen reader may get overwhelmed or confused by this, I do not recommend it. You should stick with one "nav" element.
      When designing navigation inside the header, most designers add "unordered" lists inside the "nav" element for their menus, then use CSS and pseudo-classes in CSS to control their design and any rollover dropdown menu effects, sub-menu displays, etc. These lists combined with the 'nav' element creates good semantic HTML. Search engines will index these unordered lists with anchor elements quite well. Besides providing a central location for users and search bots to access web pages, the 'nav' element also has structural meaning. All users and browsers will read and parse your parent 'nav' and its structured hyperlinks, creating meaningful connections between the navigation element and links to the interior of your website. Creating this navigational structure will thus enrich your HTML and its meaning.
    7. Cross-Browser Support: Older, non-HTML5 supporting web browsers (pre-2010) will not know what these structural HTML5 elements represent or how it should look. They have no design format by default, other than performing as a simple block-level 'div'. However, in older browsers, this element usually needs a CSS style so it does not float to the left or right of your other content blocks in non-HTML5 compliant browsers. Remember, most browsers that find an unknown element will set their CSS 'display' property to "inline", thus destroying the design of these new HTML5 layout elements. For this reason, in my "reset" style sheets, I always assign it a style of "display:block" and "float:none" to make sure these elements perform as a traditional 'div' in older browsers that do not support HTML5. But, I fully support the use of these new HTML5 elements in your web pages, despite their larger non-support in older browsers.
    <nobr> nobr, no break

    No Break

    <nobr>This text should not wrap</nobr>
    This text should not wrap
    My Recommendations:
    1. The 'nobr' element is deprecated but was a non-standard HTML element invented by older browsers like Netscape 1.1 to create text that does not create a line break like normal text. This tag is redundant as you can now control non-breaking text using CSS ("white-space: nowrap") and was also never a part of HTML5. So, do not use the 'nobr' element.
    <noembed> noembed

    No Embed

    see <embed>
    My Recommendations:
    1. The 'noembed' element defines a non-standard HTML element that offers a text message alternative to the <embed> element. This tag was mainly supported by old Netscape 4 Series browsers and was used to display a text alert message if a Netscape user's browser did not support the multimedia displayed in the 'embed' element. It is not supported by HTML5. See the <embed> element for a full description.
    <noframes> noframes

    Noframes

    see <frameset> and <frame>
    <frameset cols="50%,50%">
      <frame src="https://www.w3.org/TR/html4/present/frames.html#h-16.2.1" />
      <frame src="https://www.w3.org/TR/html4/present/frames.html#h-16.2.2" />
      <noframes>
        <p>This frameset includes two page views of the W3C websites on frames.</p>
      </noframes>
    </frameset>

    * If you do not see anything below, then the 'frameset, 'frame', and 'noframes' elements are not supported in your browser.

    <p>This frameset includes two page views of the W3C websites on frames.</p>
    My Recommendations:
    1. The 'noframes' element is deprecated now and was a member of old HTML4. A 'noframes' element was often used inside a 'frameset' parent element and would be displayed if frames were not supported in the browser, which may appear above. A simple text description of each 'frame' was often listed in an unordered list. In the past, framesets were a common way to combine, manage, and display many different web pages within a single web page. Many pages in framesets could be displayed in the browser this way. It was a very cool concept at first, but over time became difficult to manage and unnecessary.
    2. Do not use the 'noframes' element now, as it is deprecated and was a member of old HTML4. HTML5 browsers will no longer support noframes much less framesets and frames. You might try the 'iframe' instead (see below):

      <iframe src="https://www.w3.org/"></iframe>
    <noscript> noscript

    Noscript

    Many people use 'noscript' to provide alternative content when JavaScript is turned off or unavailable in a web browser. But I like to use it as an "alert box" with a message for users to turn on JavaScript or upgrade their browsers. I like to use these message box at the top of every web page I build. Again, the 'noscript' element and its content is completely hidden in most JavaScript-supporting browsers but shown when they do not support scripting. As a BONUS, I also like to use a matching hidden 'div' alert box for browsers that do not support CSS style sheets, as well. Below is an example of both alert boxes. The style sheet version doesn't have a special element like 'noscript', but uses a simple style with "display:none" on it. Any old browser, like Internet Explorer 1-2 or Netscape 1-3, that does not support style sheets ignores the "display:none" that hides the 'div' content box and shows the full message, alerting them to get a new web browser. For testing purposes, I'm revealing the messages below without the 'noscript' element so you can see what it looks like. But the code snippet below has all the right code. You can cut-and-paste it into your project. Both boxes will be hidden permanently from all other browsers, until triggered and viewable in the non-supporting ones.

    Alert Box : No JavaScript Support

    
    <noscript>
        <div style="border:1px solid red;margin:.5em;padding:1em;background:white;" role="alert" aria-label="Alert Message: No JavaScript Support">
            <strong>Alert! You may have turned off JavaScript in your web browser, or it does not support scripting.</strong> As a result, some features in this website may not function correctly. Our website works best using one of the following modern web browsers: <strong><a href='https://www.google.com/chrome/' title="Download Google's Chrome Web Browser" target="_blank" rel="noreferrer nofollow noopener">Chrome</a>, <a href='https://www.mozilla.org/en-US/firefox/new/' title="Download Mozilla's Firefox Web Browser" target="_blank" rel="noreferrer nofollow noopener">Firefox</a>, <a href='https://www.microsoft.com/en-us/edge' title="Download Microsoft's Edge Web Browser" target="_blank" rel="noreferrer nofollow noopener">Edge</a>.</strong>
        </div>
    </noscript>
    
    Alert! You may have turned off JavaScript in your web browser, or it does not support scripting. As a result, some features in this website may not function correctly. Our website works best using using one of the following modern web browsers: Chrome, Firefox, Edge.

    Alert Box : No CSS Support

    
    <div style="border:1px solid red;margin:.5em;padding:1em;background:white;" role="alert" aria-label="Alert Message: No CSS Support">
    <strong>Alert! Your web browser does not fully support Cascading Style Sheets!</strong> Our website works best using one of the following modern web browsers: <strong><a href='https://www.google.com/chrome/' title="Download Google's Chrome Web Browser" target="_blank" rel="noreferrer nofollow noopener">Chrome</a>, <a href='https://www.mozilla.org/en-US/firefox/new/' title="Download Mozilla's Firefox Web Browser" target="_blank" rel="noreferrer nofollow noopener">Firefox</a>, <a href='https://www.microsoft.com/en-us/edge' title="Download Microsoft's Edge Web Browser" target="_blank" rel="noreferrer nofollow noopener">Edge</a>.</strong>
    </div>
    
    Alert! Your web browser does not fully support Cascading Style Sheets! Our website works best using using one of the following modern web browsers: Chrome, Firefox, Edge.
    My Recommendations:
    1. The 'noscript' element represents an alternative block of content or alert message when JavaScript or other scripting is unavailable in the browser. A user agent or browser might have JavaScript disabled, turned off, or might not support scripting at all. In all those cases this HTML black would appear. Support for this element has been around since HTML and the birth of JavaScript in 1996. However, it was rarely used by most developers until the recent trend in using heavy client-side JavaScript API's.
    2. How to Use the 'noscript' Element: As mentioned, since the late 1990's, 'noscript' has been a powerful way to offer many browsers and user agents an alternative to JavaScript. The original idea was to allow browsers that chose to turn "off" JavaScript the ability to see alternative content or media inside the 'noscript' element. That was its original function. Back in the 1990's that was how I started using it. After 2001, we started noticing that on average 10-12% of visitors globally actually has JavaScript turning OFF in their browsers! That is a lot of people! So, that is when I started using 'noscript' for alert boxes. These 'noscript' alert boxes would be activated at the top of the home page of websites that had some level of JavaScript dependency. Visitors with JavaScript turned off would then see a white or red alert box telling them of this potential issue. They could then proceed into the website if they chose, or simply turn JavaScript on. It was a very nice feature to assist another subset of users that might struggle in your website without JavaScript enabled.
      Today, in 2022, we have an even worse problem! With the heavy, heavy use of JavaScript in websites today, there has been an up-tick in interest in the 'noscript' element. As a result, HTML5 has again implemented this very old element. Note that its assumed today everyone supports JavaScript but regular statistics posted online show a range of global percentages (most under 10%) showing a significant number of users regularly turn off JavaScript. If you are building web applications solely from JavaScript today, you must think again about that strategy if 5-10% of users globally cannot use your web product because JavaScript has been disabled in their web browsers. At least you have the powerful 'noscript' element to help you!
      In HTML5, you can now add the 'noscript' element in either the 'head' or the 'body' of your web page, allowing you to reveal large blocks of alternative styles or content for browsers that do not support JavaScript, hiding them from browsers that do. In the 'head' version, you can reveal custom styles that hide and show content for non-supporting browsers. In the 'body' version, you can reveal custom content or use it as an alert box with a message to users that your web page requires a JavaScript-enabled browser. I like to use the latter. An example of that is shown above. Note that all browsers, even very old ones, will support 'noscript' and HIDE the 'noscript' element and its content from browsers as long as ANY JavaScript is enabled in the browser. Remember to always add either a 'p' or 'div' tag around all content inside the 'noscript' element, as it has no style as is and is a hollow element.
    3. Some additional facts include: XHTML and XHTML5 polyglot does not support the 'noscript' tag, but HTML4 and HTML5, do support its use. So, be aware of that fact. Also, the 'noscript' element can be used in both the 'head' and 'body' elements. When used inside the 'head' element 'script' must contain only link, style, and meta elements. You can then use it to completely load new web page features or styles when JavaScript is not supported. In that way, if JavaScript disabled, one can style the page to show or hide all elements and reveal hidden messaging or information that do not require scripting.
    <object> object

    Object

    also see <param>

    <object id="object1" alt="object: Psychedelic Video" data="video1.mp4" type="video/mp4" style="width: 320px;height: 240px;outline: none;border:1px solid #bbb;" loop="false" title="Psychedelic Video" aria-label="Object File: Psychedelic Video">
    <!-- "params" are optional but supported by some older browsers -->
      <param name="movie" value="video1.mp4" />
      <param name="type" value="video/mp4" />
      <param name="play" value="false" />
      <param name="loop" value="false" />
      <param name="quality" value="high" />
      <param name="autoplay" value="false" />
      Sorry, your browser does not support this video.
    </object>

    Below is an example using the 'object' tag to play a movie file. Depending on your browser and the plug-in or player supported, you should see a "MPEG-4" file play. If you do not, it is because this video format or codec is not supported by your browser or its player. Note: Internet Explorer browser may not play this specific video codec, or may have ActiveX disabled.

    Sorry, your browser does not support this video.
    My Recommendations:
    1. The 'object' element is used to display a multimedia file in a web page, including an image, iframe, Adobe Flash, Java Applet, online document, audio, or video file. This element is supported in HTML5 but slowly being deprecated by other elements when displaying multimedia in the browser. Use the 'img', 'picture', 'iframe', 'video', or 'audio' elements instead for those types, and 'object' for specialized multimedia types only. Keep in mind 'object' relies on plug-ins and players to play its media unlike the other HTML5 media types. More details below.
    2. The History of the 'object Element: In the "good old days" of the World Wide Web (pre-2010), in order to display multimedia in web pages, play video games in browsers, run complex applications, play animations, show documents, and display other features online, you had to rely on 3rd party "players" in the browser: Java Applets, Adobe Flash, plug-ins, ActiveX objects (in Internet Explorer only), images, video, audio, Windows documents, and older 3rd party applications. Nearly all embedded media was played back via a "player" or "plug-in" separate from the browsers. 'embed' and 'object' use this plug-in model. The browser would download these special applications then play or display these application files for you in a user's web page. JavaScript was unable to provide these features, nor the browser. Relying on 3rd party applications to deliver multimedia in the browsers was a great idea at the time, as HTML was never designed to do that. And security was yet a problem in most browsers. For over a decade, web browsers viewed millions of multimedia objects this way using plug-ins and players of many types. The problem was it later became a special channel for hackers, malware, viruses, and advertising to sneak in and infect a user's browser, or worse, the user's computer. That is one reason 'object' tags are decreasing in use and replaced by newer elements in HTML5 and scripted features. Security has simply become too big of a concern. Many of these media types are now discontinued, no longer supported, or are security risks in the browser. Smart phones also decided these players and plug-ins were a security risk as well as a CPU hog. For those reasons and more, these multimedia elements are generally not used in HTML5, though they are still supported in various forms. With the newer smart phone technology that came online after 2007, it was decided that most of this new media would not be supported on mobile devices going forward. And so the plug-in model is dying fast. Tags like the 'applet' and 'embed' elements are dying too, even in modern desktop browsers. Legacy websites today that still contain unique custom multimedia objects like this must now be removed or replaced with alternative media types, as so many of the "players" that once supported rich media like this are no longer around to play them (post-2010). Adobe Flash, for example, was discontinued just a few years ago (c. 2017) in all browsers, though it was once hugely popular as a choice for highly interactive solutions in thousands of desktop websites, at one time. (I actually used to write Adobe Flash animations and applications in Actionscipt.) This change has not stopped video, audio, or other applications from being embedded in web pages, however. HTML5 has simply come up with alternate elements where the players are built into the browsers that parse them. Keep that in mind. Yet the 'object' tag has remained behind to support the continuing growth of various multimedias online, which HTML5 has still not addressed. So, if you see these older elements, 'object' or 'embed', and are deciding to remove them or update them with HTML5, use the newer HTML5 elements and media types available instead ('img', 'picture, 'iframe', 'video', and 'audio' using MPEG4, WebM, etc.).
    3. So, why use 'object' in modern HTML5 pages? The 'object' element, unlike the 'embed' element, was a part of the HTML4 spec's. In fact, the 'object' tag has been around since the birth of HTML and the 1990's (it was used by Internet Explorer because IE did not support the 'embed' element, like old Netscape 4). Because 'object' became a universal element for IE browsers over the years, while 'embed' became a player element for all other browsers, 'object' often contained 'embed' elements which were used as a fallback to Microsoft's ActiveX 'object' version. (Internet Explorer 6-11 had limited support of the 'embed' element and always looked for an ActiveX 'object' element.)
      But 'object' is now strangely still a part of HTML5. Why? It was adopted early on mostly by Microsoft and Internet Explorer as a popular alternative to Netscape's 'embed' element, and to support their ActiveX control player. But over time, it went on to become the standard tool to add other types of specialized content into browsers, including Java controls and Acrobat documents, that no other element could offer. This is still the case today for specialized media. ActiveX and Java are now nearly dead as far as "player technology" used online.
      The 'object' element is still required to add instances of special media into web pages. Some types, like Adobe Acrobat document players, have built in browser support. So those files are readable without downloading a player in many cases. In other browsers, however, they may not be. So you need the 'object' element to show them inside a web page. As such, the 'object' element is designed to provide an infinitely extensible means of inserting specialized content into pages using HTML, where 'video' and other new HTML5 elements are not suitable. Know that you can still play many types of media using the 'object' element, including: Images, Video, Audio, Flash, iframes, and more. The browser will interpret the media player required based on the file extension and the 'type' attribute, then attempt to load a player to display it or play the media with its own tools. Because of these crazy cross-browser issues using 'object', the deprecated ActiveX support, deprecated Java and Flash support, and the fact images, video, and audio can now be displayed in newer HTML5-friendly elements, there really is no reason to use 'object' EXCEPT to support specialized or older multimedia types. In addition, older browsers that still do not know the HTML media elements, like 'video', will still require 'object'. If you want to play movies in browsers created, say prior to say 2012, you will always need the 'object' tag. Most of the "other" media the 'object' element once supported have gone anyway and were driven away by deprecated multimedia players that have been discontinued years ago due to security concerns. Because 'object' requires download and activation in most cases of an outside "player" (or ActiveX control in IE's case) to display any media contained inside it, it's not recommended for video or audio in newer browsers. However, you may find a use case in newer browsers. One case for using the 'object' element is support of video in older browsers while using the 'video' element in newer HTML5 browsers. I wrote an example of some sample code for this in my article in this page called "How to Create a Cross-Browser Video in HTML5".
    4. Types of Media You Can Use in the 'object' Element: Besides video, you can use the object tag to insert all kinds of media into your web page, including images, iframes, audio, Flash, PDF, Word Docs, and more. Think of the 'object' element as the "workhorse" element, one used to display any non-typical media or files no other element will support. 'object' itself was supported in HTML5 in order to allow you the flexibility to do just that. But, there is no guarantee it will display, as 'object' uses players and plugins to render most of these files. If the browser or version does not have the software to do that, it will fail. If you do use it, be sure to add the "data" attribute with a path to the file on the server, and add the "width" and "height" to give your embedded file dimensions.
    5. The 'object' element supports a number of attributes, including 'width', 'height', 'data', and media 'type'. The 'width' and 'height' are used to set the dimensions of your file. The 'data' attribute is the primary means of connecting your object element to a path that connects to the location of your multimedia file on the server. The 'type' should have the generic MIME type of your media object and is a hint to the browser of how to interpret it (example, type="image/jpeg").
    6. Deprecated Attributes: There are many old attributes used by 'object' by browsers of the past that may not work. I have listed the ones below I recommend you avoid: bgcolor, hspace, palette, pluginspage, pluginspace, quality, salign, scale, vspace. Note: I have added the "loop=false" attribute to the code above, though it is likely not supported in modern HTML5 browsers today. But it prevents some older browsers from repeating video playback in a loop forever.
    7. As usual, always include an 'id' and a 'title' on these click-able multimedia objects.
    8. The 'alt' attribute in 'object' elements helps screen readers and the blind identify the meaning of embedded video elements, just like images provide. For that reason, always add the "alt" attribute.
    9. The Optional Child 'param' Element: Since 2000, the 'param' child element of the 'object' element has been used to help define its various parameters. Today, the 'param' element is optional as 'object' has assigned most of these values to its own attributes. But many older browsers may not know them and benefit from the old 'param' element. I would therefore still us it. The 'param' element adds name-value pairs associated with your media file using "name" and "value" attributes. A common use for 'param' was to add "movie" for its name and value the URL path. Another would be "width" or "height". It also comes with an optional "type" or MIME type attribute and an optional "valuetype". Because the 'object' element is often used for playing media that requires a 3rd party plug-in or player, the 'param' element is often used by these special players. Old Adobe Flash and shockwave files often needed these name-value parameters that controlled its numerous objects properties.
    10. Fallback alert text is often used between 'object' tags to alert users of non-support if media playback fails In the old days of the Internet, 'object' was often part of a block of elements designed with fallback tags if a browser did not support 'object', like 'embed'. In the example above, you will see how I have added a fallback text message if a browser or screen reader does not understand the 'object' parent element. (See my sections called "How to Create a Cross-Browser Video in HTML5" for examples of this.)
      In older web pages still online today you may see 'object' elements used with many strange attributes no longer supported in HTML5. Almost all of these were added to support a variety of custom 3rd party player/plugin/ActiveX features. Many plug-in vendors typically made available a 'classid', 'codebase', 'codetype', and various other attributes and URL's needed to download and install plug-ins. 'classid' was the most popular and used in the old days to specify the location of the object's player implementation via a URL. Object implementations included things like Java Applets or Flash player downloads. These usually pointed to 3rd party implementation for the data subject or file. 'codebase' gave a base URL for a class ID, player download on the Internet, or some base path to resolve the 'data' path. 'codetype' specified the media type of the code referred to by the 'classid'. Some implementations of object 'data' elements, like images, could be done by the browser, so 'classid' and 'codebase' would not be needed. Flash and the Adobe Flash plug-in download was a common use for these attributes and extra 'param' elements. When a user displayed the page and did not have the player a popup would fire up asking them to install it. Use of these old attributes is less common today. Note: Because the 'object' element and its players/plugin/ActiveX are a security risk in modern browsers, I do not recommend you use them.
    11. Warning: Most versions of older non-IE browsers (pre-2010) have never supported 'object' and prefer the 'embed' element instead, as it supports their older players. Also note that IE version 9-11 have adopted support of HTML5's 'video' and 'audio' elements instead of 'object'. This is another reason to avoid the 'object' element when possible and move to the newer HTML5 'video' or 'audio' element instead when supporting multimedia in your web pages. If you support video in these older browsers, however, you may find you need all three elements. Note: For a powerful new cross-browser video solution that works in old and new browsers and combines 'video', 'object', and 'embed' elements, see my section in "best practices" below called: "How to Create a Cross-Browser Video in HTML5".
    12. Warning: The sample video above may not play in Internet Explorer using Windows Media Player. If the video above does not play in IE or your browser, it could be because the media player used by the browser does not support the codec capable of decoding the video information. Your OS may recommend the installation of an additional codec to make up for this deficiency so that you can play the movie in your media player.
    13. Warning: Use CSS to set custom 'width' and 'height' using 'object' in supporting newer HTML5 browsers, as the attribute version may not honor the dimensions you set. (see my example above)
    14. As mentioned, I recommend you NOT use 'object' for playing audio and video in web pages, but use the 'img', 'picture', 'video', or 'audio' elements instead. Even though HTML5 still supports 'object', because it is an element that is more reliant on the older "plug-in" player model, its better to avoid its use going forward unless you MUST support specialized media that is not video, audio, or images. Again, DO NOT use 'object' for displaying video, audio, images, pictures, or iframes. Use the new HTML tags whenever possible and reserve use of object for SPECIAL multimedia objects, like Adobe Flash, Java Applets, or documents like PDF which require the 'object' element to display them. HTML5 has no other elements available but 'object' or 'embed' in those special cases. Just keep in mind that in IE 5-8, because they do not support HTML5 elements, they will use ActiveX inside 'object' to try and resolve those types of specialized files. Again, if you must support IE or older browsers with special multimedia, you may need to use a fallback HTML design with 'object' and 'embed' combined together to support these older browsers with special players installed.
    15. As mentioned above, see my article below called "How to Create a Cross-Browser Video in HTML5" below in "best practices" for a newer, more modern example of how to combine 'video', 'object', and 'embed' elements together and to enable wider video playback support across many older browsers at once in your web pages.
    <ol> ol, ordered list

    Ordered List

    see <li>
    My Recommendations:
    1. The 'ol' element defines an ordered list. See the <li> element for a full description.
    <option>, <optgroup> option, option group

    Option / Option Group

    see <select>

    The 'option' and 'optgroup' elements are children of the 'select' element. Shown below is an example of these elements when using the 'select' element form control.


    <form id="formoption" name="formoption" method="post" action="#" title="Option and Option Group Example" aria-label="Option and Option Group Example" autocomplete="off" autocapitalize="off" spellcheck="false">
    <fieldset id="formoption_fieldset1" name="formoption_fieldset1" form="formoption" style="background-color:#fff;">
    <legend style="background-color:#aaa;color:#fff;">Option and Option Group</legend>
    <div>
    <select id="formoption_select1" name="formoption_select1" size="1" title="Select a Fruit" aria-label="Fruit" tabindex="0">
    <option value="" selected="selected">-- select a fruit --</option>
    <option value="strawberry">Strawberry</option>
    <option value="banana">Banana</option>
    <option value="grape">Grape</option>
    <optgroup label="Apple" role="group">
    <option value="apple_reddelicious">Red Delicious</option>
    <option value="apple_macintosh">Macintosh</option>
    <option value="apple_green">Green</option>
    </optgroup>
    </select>
    </div>
    </fieldset>
    </form>
    Option and Option Group

    A select form field contains multiple child 'option' elements. If you need sub-grouped options with a group name, use the 'optgroup' element, as shown below.

    My Recommendations:
    1. The 'option' and 'optgroup' elements define child elements of a 'select' element that support additional choices within the listing. Like 'select', the 'option' element has been around since the 1990's and in the earliest of HTML recommendations by the W3C. 'optgroup' was added later and not supported in browsers, like Internet Explorer till version 5.5. Like most form controls, the 'select' element and its children are considered a "replaced" elements, as their design and actions are controlled by the browser and operating system. This applies to styling 'option' and 'optgroup', which is still difficult.
    2. Always Assign a 'value' Attribute in 'option': When a user choose one or more items from your 'select' element then submits the form, the 'select' elements "values" are sent to the web server along with the "name" of the 'select' element, when the form is submitted. For that reason, always add a "value" attribute inside each 'option' element, even if empty, with its text or data attached. Example: <option value="{my option value}">My Option Text</option>.
      Often the text name inside the 'option' element is the same as "value" (like "yes"/"no", "on"/"off", etc.). But it can also be different from the "value". But the "value" is what is sent to the server as data, and part of the "name-value" attribute pair sent to the server from your form control when the 'select' is submitted. In the case of a 'select' element set as "multiple=multiple", each selected "option" will always send the same 'select' element "name" value for all the 'option' "values" selected. So make sure each 'option' "value" is unique, as you have to loop through the same array of names to get each value selected. The data for multiple select choices sent to the server will appear like this: myselect=1&myselect=2&myselect=3. IMPORTANT: If the "value" attribute in 'option' is omitted, the value is taken from the text content of the option element! Some older browsers will always do this. This is why, as a rule I try and match my text string to the value, unless its multiple words, a non-unique value, or the value is in another non-friendly format, like an abstract number, id, or value a user will not recognize.
    3. Use the 'selected' Attribute: If you have a preselected item you want selected in a 'select' element, use the "selected" attribute inside the 'option' element. If no item has this attribute, the select will pick the first 'option' in your list and select it. That is why many designed add an empty "value" in the first 'option' element with instructions, like "-- select an item --". If the field is not required and sent to the server, a blank value will be sent indicating an explicit non-choice was made (which is better that not knowing). Note: Always use the XML-friendly version, or "selected=selected".
    4. Do Not Use the 'disabled' Attribute: If you have an 'option' item in your 'select' element you do not want selected, you can set it to "disabled" to prevent users from selecting it from the listing. This confuses users who might not understand why an option cannot be selected. Some browsers may ignore this feature, enabling selection and messing up your data. Others could disable the whole form when this is set. So, I do not recommend use of the "disabled" attribute on 'option', and instead disable the whole form or remove the option item completely. Note: Always use the XML-friendly version, or "disabled=disabled".
    5. Always Use the 'label' Attribute in 'optgroup': Always add the "label" attribute inside your 'optgroup' tag, which gives it a group text name for the subgroup of options inside the 'select' listing. It provides for no other feature but as a label for a group of sub-options in the listing.
    6. Do Not Use the 'label' Attribute in 'option': The "label" attribute is required in 'optgroup', but not 'option'. In 'option' it is not used often and gets confused with the "value" attribute and the text inside the 'option' element itself. Two uses of "label" in 'option' were to display a shorter text version of what is in the option element text, in which case the browser was supposed to pick the "shorter" text version. This no longer works this way in many browsers. The second use case was to use "label" to define the "meaning" of an option's text. Today, this is rarely used or needed. So, avoid use of "label" in 'option' elements.
    7. When 'select' Elements use the 'multiple' Attribute: If you need users to select more than one item from your 'select' element, add the "multiple=multiple" attribute. The box will then be resized to show multiple items by default rather than one. This shows users that multiple items can be chosen. I like to set the first 'option' element in the list with an empty "value" attribute and to say, "-- choose multiple items --". This instructs them on what to do with the multiple-select listing. Remember, in multi-selects, you can either hold the control key on your keyboard and select multiple, one at a time, or hold the shift key and select large blocks of items at once.
    8. Trouble Styling Replaced Controls with CSS: "Replaced" elements like 'select', 'textarea', and others are notoriously difficult to style using CSS and have been for years. So is the 'option' and 'optgroup' elements. See the <select> element section for more details about this issue and the 'select element in general.
    <output> output

    Output

    In the example below, I have added the new HTML5 'output' element (last box) in combination with the new "range" and "number" HTML5 form controls. This allows a user to change the "range" and "numeric" input types, have a JavaScript event ("oninput") on the 'form' element add the values together, then have it post the mathematical result to the 'output' element box. Browser support for this feature is still weak.

    <form id="formoutput" name="formoutput" method="post" action="#" title="Input Example" aria-label="Input Example" autocomplete="off" autocapitalize="off" spellcheck="false" oninput="formoutput_output1.value=
    parseInt(formoutput_range.value)+
    parseInt(formoutput_number1.value)">
    <fieldset id="formoutput_fieldset1" name="formoutput_fieldset1" form="formoutput">
    <legend style="background-color:#aaa;color:#fff;">Output Example</legend>
    <div>
    <input type="range" id="formoutput_range" name="formoutput_range" value="50" min="0" max="100" minlength="1" maxlength="3" tabindex="0" autocomplete="off" title="Slide the Range Indicator" aria-label="Slide the Range Indicator" /> +
    </div>
    <div>
    <input type="number" id="formoutput_number1" name="formoutput_number1" value="0" min="0" max="100" minlength="1" maxlength="3" tabindex="0" title="Number" aria-label="Number" /> =
    </div>
    <div>
    <output id="formoutput_output1" name="formoutput_output1" for="formoutput_range formoutput_number1" tabindex="0" value="0" title="Number Output" aria-label="Number Output"></output>
    <label for="formoutput_output1" title="Output">Output</label> </div>
    <hr />
    </fieldset>
    </form>
    Output Example
     +
     =

    My Recommendations:
    1. The 'output' element is a new HTML5 element that represents a new form field "output" box which can receive the results of mathematical calculations or other output. It was originally designed to provide output from operations based on input made by an end-user. However, it relies heavily on JavaScript and is not widely supported in current browsers, old and new. Therefore, it should not be used.
    2. 'output' Element Attributes and JavaScript: This new HTML5 form field should have the same features and attributes as a typical form field control (see the <input> for all the details). As such, it should reside inside a typical 'form' control and perform like any other input, except the unique property that a user cannot enter data into it by default. It must rely on some outside script or source to add values to it, which makes it a non-typical HTML form field element.
      There are many ways to run calculations from other form fields and insert the results into 'output'. Note the added JavaScript on the 'form' element in my sample code above. But my demonstration might not work in older browsers, simply because they do not support the 'output' element. In addition, I do not like the fact this element depends on JavaScript to be functional (Why not just use a plain "text" input box instead?).
      Note: Internet Explorer has no real support for the "number" input type, the "range" type is partially supported in IE, and IE 1-11 and Edge 12 have no support for 'output' at all! Add up my list of issues above with the non-browser support (plus buggy CSS design below) and you see why I cannot recommend the use of the 'output' element in modern HTML5 web pages today.
    3. 'output' Element and CSS Style Sheets: This new HTML5 form field should have the same design as a typical form field control (see the <input> element design). But it does not. This control should be visible, but by default, most browsers do not show any marker or visible features for 'output' until an output value appears via a JavaScript event. So, it will appear as an invisible control with no form field dimensions until some script inserts a value into it, triggering its display. In the example above, I have tried to style the 'output' to match my 'input' textbox elements, so you will see it has a border, padding and other features. But the styling turned out to be more difficult that I planned in some browsers. In most cases, you want 'output' to be simply an empty white box ready to receive values. But it's invisible with no dimensions in some browsers, initially. To address this I found you had to change the display to "block" and give it width and height. This of course defies the default "inline-block" dimensions of other form fields, which can also slide next to each other, if needed. Setting the control to block allows us to give it an appearance, but no ability to float alongside other form fields, now. But that is fine. It must act like a block-level element and drop down below any neighboring 'input' or other elements if it has to be seen. Its a fair trade-off. Again, I do not recommend this element's use, but if you do, below is a style that at least gives it an appearance in the browser:
      
      body output,
      body output:visited,
      body output:hover,
      body output:focus,
      body output:active {
          display: block;/* Defines its dimensions and thus forces its appearance. */
          width: 12em;/* Defines its dimensions and thus forces its appearance. */
          max-width:12em;/* Defines its dimensions and thus forces its appearance. */
          height: 1.8em;/* Defines its dimensions and thus forces its appearance. */
          cursor: pointer;
          width: auto;
          padding: .2em .2em;
          padding: .2rem .2rem;
          margin: 0;
          border-radius: .2em;
          border-radius: .2rem;
          border: 2px solid #bbb;
          background: #fff;
          line-height: normal;
      }
      
    4. Sadly, the "range" type and 'output' element in this example above have poor support in mobile Safari browsers (iPhone versions included, until after 2018). "number" and 'output' do not work in Internet Explorer 1-11 or even Edge 12! Even if this 'output' calculation works in your browser, it does not have wide enough browser support in most browsers to be usable. And, it requires custom JavaScript to work when it does. Therefore, do not use the 'output' element as it is does not have any support in older browsers (pre-2010), nor much support in many HTML5 browsers.
    <p> paragraph

    Paragraph

    <p>Lorem ipsum dolor sit amet, mea enim erat id, regione iudicabit consetetur ius ex. Qui vide errem ut, ius id movet atomorum. Sit pericula definiebas ei, ex eam essent maluisset. Duis ceteros pro ut. Mei eius labore ut. Iusto facete facilisi vel id, nonumy omnium constituto ad pro. Mei in sale option.</p>
    <p>Vim ei latine intellegat. Mei ea ferri suavitate. Scaevola comprehensam necessitatibus mel ad, at liberavisse signiferumque duo. Aeque tation nec ad, no sea mucius epicuri comprehensam.</p>
    <p>Invenire contentiones cum cu. Nullam timeam ceteros sed ne. Et usu case eleifend, atqui malorum civibus sed ea. At eruditi inimicus repudiandae qui, quo quaeque alterum gloriatur in.</p>

    Lorem ipsum dolor sit amet, mea enim erat id, regione iudicabit consetetur ius ex. Qui vide errem ut, ius id movet atomorum. Sit pericula definiebas ei, ex eam essent maluisset. Duis ceteros pro ut. Mei eius labore ut. Iusto facete facilisi vel id, nonumy omnium constituto ad pro. Mei in sale option.

    Vim ei latine intellegat. Mei ea ferri suavitate. Scaevola comprehensam necessitatibus mel ad, at liberavisse signiferumque duo. Aeque tation nec ad, no sea mucius epicuri comprehensam.

    Invenire contentiones cum cu. Nullam timeam ceteros sed ne. Et usu case eleifend, atqui malorum civibus sed ea. At eruditi inimicus repudiandae qui, quo quaeque alterum gloriatur in.

    My Recommendations:
    1. The 'p' element represents a block-level paragraph of text. Unlike the <br /> element between lines of text, the 'p' element wraps around a paragraph of text, creating both a new line break before and margins of spacing before and after that is collapsed into one between paragraphs. The paragraph patterns paragraph designs with text in old books. So its design comes from that original source, not the World Wide Web. Because paragraphs and the 'p' element has been around since the birth of HTML in the 1990's, this element has not changed in any of the browsers (except when it comes to how collapsing margins might work in a few) and so is very reliable.
    2. Collapsing Margins Between Paragraphs: Paragraphs act like block-level elements with dimensions, margins, and breaks. But they also often come styled with collapsible margins that often confuse developers or fail to act as expected in a few older browsers. I explain this in depth in my article in this web page entitled, "The Mystery of Collapsing Margins in HTML".
    3. Elements inside Paragraphs: I would wrap all paragraphs around text in your web page so its contained and managed safely with the right breaks and margins. Inside paragraphs, however, you should avoid any block or inline-block elements. It is safe to put many inline elements, like 'a', 'span', 'del', 'ins', 's', 'strong', 'em', and others. You can then add style classes to these elements to style pieces of text.
    4. Styling Paragraphs with CSS: Paragraphs often are styled appropriately by the user's browser and its built-in default UA style sheet. It is usually best to use the styles that come with 'p' elements. But I like to style my 'p' elements using my "reset" element style sheet so they look and act the same across a wide range of browsers. It is good to control your elements and their many styles this way so you understand how they work, have more control, and they look the same across lots of browsers, old and new. 'p' elements are almost always styled with "display:block", as block-level elements like 'div'. I like to set "padding:0" but also set "margin: 1rem 0rem;". This removes any left and right margins, but makes sure the top and bottom margins are equal to the text's default or starting font-size (or 1rem). When margins between two paragraphs meet, they merge into one, following a few rules. (see my margin article mentioned above for details). This provides some solid spacing between paragrAphs, even in older browsers, so text can breath yet without doubling the space between paragraphs. Finally, I make sure "line-height" is set to either "normal", "1.2" (which is close to normal), or "1" (same height as medium or default font-size, which is usually 16px). This latter style usually flattens paragraph text to the height of the font-size. These line-height styles allow your lines of text inside the paragraph to expand and breathe, though again, the default is likely good enough and close to the three values above. Often, paragraphs should reside inside a parent container, like a 'section' or 'div' element, which allows you to constrain multiple paragraphs of text and add extra padding or borders around the block, if you like. Do not try and style paragraphs with design beyond these few properties. They are really just empty "shell" elements meant to hold text only. Use its parent block-level container if you want to add colors, borders, and other visual design features.
    <param> parameters

    Parameters

    also see <object>

    The 'param' element is used inside a parent 'object' tag to control its multimedia parameters. An example of these parameters using a video object is shown below.

    <object id="object2" alt="object: Fireplace Video" data="video1.mov" type="video/quicktime" loop="false" style="width: 320px;height: 240px;outline: none;border:1px solid #bbb;" title="Fireplace Video" aria-label="Object File: Fireplace Video">
    <param name="movie" value="video1.mov" />
    <param name="type" value="video/quicktime" />
    <param name="play" value="true" />
    <param name="loop" value="false" />
    <param name="quality" value="high" />
    Sorry, your browser does not support this video.
    </object>
    Sorry, your browser does not support this video.

    (Above is an example using the 'object' tag. Depending on your browser and the plug-in supported, you should see a "MOV" (Apple Quicktime) video file. If you do not it is because this video format or codec is not supported by your browser.)

    My Recommendations:
    1. The 'param' element is used to define multimedia parameters for the 'object' element. It provides control over various properties for media objects used in a web page object using name-value pairs, and which various players and plugins use to control the media object. This element has been around since Netscape 4 Series which used it because of non-support of the 'object' element attributes. It was later used in HTML4 and early versions of Internet Explorer, which usually implemented 'object' parameters for support of Microsoft's ActiveX controls. Note that this element and its parent 'object' element is still supported in HTML5, but slowly being deprecated by other elements when displaying multimedia in the browser. Use the <img>, <picture>, <iframe>, <video>, or <audio> elements instead for those types, and <object> for specialized multimedia types only. Keep in mind 'object' relies on plug-ins and players to play its media, unlike the other HTML5 media types. More details below.
    2. The Optional Child 'param' Element: Since 2000, the 'param' child element of the 'object' element has been used to help define its various parameters. Today, the 'param' element is optional and rarely used as 'object' has assigned most of these values to its own attributes. Beside, most now use the 'video' and 'audio' elements in HTML5. But many older browsers may not know the newer HTML5 elements and benefit from the old 'object' element, instead. I would therefore still use 'param' with 'object', when needed. The 'param' element adds name-value pairs associated with your media file using "name" and "value" attributes. A common use for 'param' was to add "movie" for name and the URL path for its value. Another would be "width" or "height" values for name-value pairs, or to turn movie auto "loop" on or off. If the player does not recognize these optional parameters, they are simply ignored. It also comes with an optional "type" or MIME type attribute and an optional "valuetype". Because the 'object' element is often used for playing specialized media that requires a 3rd party plug-in or player, the 'param' element is often used by these special players to receive the parameters they need to play or display the multimedia object. For example, Old Adobe Flash and its shockwave files often needed specialized name-value parameters to control its numerous properties.
    3. ALWAYS use the XML-friendly version of 'param' with the " /" at the end as so: <param />. Do not let others convince you this is a "void" element or that this format is not compatible with HTML5, because it is.
    4. See my article below called "How to Create a Cross-Browser Video in HTML5" below in "best practices" for a newer, more modern example of how to combine video playback support across many older browsers with the 'object' element using multiple 'param' elements.
    <picture> picture

    Picture

    also see <img>

    Using Picture with the New HTML5 <figure> Element

    Below I have wrapped the 'img' element in a 'figure' element, then a 'picture' element. The 'figure' element provides a 'figcaption' or text caption for the image (not picture), assisting non-visual readers.

    The 'img' element below also has a set CSS "style" attribute with variable width and height added to support the possible variable dimensions of the alternate image types assigned by the 'source' elements. It does have "width" and "height" attributes whose values are based on its default image, which the browser should only use if it defaults to its first image. But those will be ignored as each source image with different dimensions is applied.

    If you see a "flowering tree" image ("webp" type) below, your browser supports one of the new alternate HTML5 image formats that the picture's 'source' element has assigned your 'img' element. If you see the "weather map" image it means your browser does not understand the WebP image type or failed the "media" viewport check in the previous 'source' element. Finally, if you see the default 'img' element's "World Wide Web" globe image ("jpg" type), the previous two image types failed and your browser only supports "jpegs".

    <figure aria-labelledby="picturecaption1" style="padding: .5rem;border: 1px solid #bbb;background: #f0f0f0;width: auto;height: auto;display: inline-block;">
    <picture id="picture1">
    <source srcset="image.webp" type="image/webp" />
    <source srcset="weather.gif" media="(min-width: 800px)" type="image/gif" />
    <img id="picture1_img" style="width: auto;height: auto;max-width: 100%;" src="www.jpg" width="255" height="200" alt="image: World Wide Web" title="The World Wide Web" aria-label="Image of the World Wide Web" loading="lazy" onerror="this.onerror=null;" />
    </picture>
    <figcaption id="picturecaption1" style="display:block;">
    "Which Image Appears?"
    </figcaption>
    </figure>


    image: World Wide Web
    "Which Image Appears?"

    * Note: My host provider does not support "WebP" images I found out, so if no "flowering tree" WebP image appears, it is not the code but my host provider. :(

    My Recommendations:
    1. The 'picture' element is a new inline HTML5 media element that allows for the display of new, alternate image formats in a web page. The 'picture' element enables the 'img' element to utilize more advanced image "choices" using 'source' element child tags and media queries, as well as newer image formats like WebP and others. In addition, 'picture' can now be contained within a 'figure' and 'picture' parent element to enhance the image with captions.
    2. The 'picture' versus 'image' Element: In the 'img' section in this page, you can get a more in-depth view of the older 'img' element and its history. The HTML5 'picture' element contains zero or more 'source' elements and an 'img' element. But, the main thing you need to know about the relationship between the 'picture' element and 'img' element is the fact that 'picture' always wraps around the older 'img' element, but that the 'picture' is nothing but a "shell" element, only providing alternative images to 'img'. 'picture' does not hold images or photos of anything, nor does it or should it have any styling or formatting. All the 'picture' element does is allow modern HTML5 browsers to provide alternate sources for the final photo that will appear inside the 'img' element. Understand that 'picture', like 'figure', is just an empty, invisible element and does not do anything other than to group images with captions and give the 'img' tag alternate image choices. It simply injects alternative image formats into the 'img' element, if the user's browser supports them. So keep in mind, the 'img' element remains the PRIMARY container of the image inside all these other elements. Because the 'img' element still contains and holds the final image, it was designed as a nice fallback for older browsers that ignore the 'picture' wrapper element and its 'source' children, but still recognize 'img'. Most of the HTML5 elements were poorly designed and do not have this nice fallback feature, so do not work gracefully with older browsers like 'picture' does. That is why I am highly supportive of 'picture' in HTML5, unlike the rest of HTML5 which fail quite badly in older browsers with very little support.
    3. The Picture Element and its Children: In HTML5, the new 'picture' element has the power to completely alter and improve how images are used in modern web pages. The idea is to save megabytes of download time by using smaller, better compressed images tailored for each screen and device. It provides this new ability via a new child element called 'source'. (See my article below called "The New Picture Element". I cover all the basics of using 'picture' and 'img' together in HTML.) As mentioned before, the 'picture' element only provides alternative image formats to the 'img' element based on browser support, viewport size, or other checks in the 'source' attributes. The browser first checks these 'source' elements one at a time. The browser examines each 'source' elements "srcset", "media", "size", and "type" attributes to select an image that best matches those criteria. If the image "type" is supported and/or viewport dimensions match, then the alternate "srcset" image URL is passed into the 'img' element below. If none are supported, then the default 'img' tag's image "src" URL is used.
      The 'picture' element itself does not do much. Its 'source' child elements do most of the work in controlling images. Multiple child 'source' elements can be added inside the 'picture' element, along with the 'img' element, to give newer HTML5 browsers the ability to choose from among numerous images in deciding which image to show inside the 'img' element.
      As mentioned, the 'img' element works exactly the same as before in older browsers, so that if 'picture' and its 'source' elements fail, the 'img' element can still deliver its default 'src' path and image, the same as it has done the past 20+ years. But if a newer HTML-supporting browser is present, it can choose from a much richer array of source image based on support for different image "types" supported by a user's device, the ratio of CSS pixels to "device pixels" on the user's device, or the dimensions of the user's viewport using media queries.And so, the picture element works like the new HTML5 'video' and 'audio' elements in that the 'source' elements control its various features. Multiple source tags are often added under 'picture' with each one having a different image choice for the browser. The browser will then look for the first 'source' element from the list and check both 'media' attribute its "query", then the 'type' attribute to see if the encoded image type is supported in the user's browser. When the media query value matches the current viewport width and the image type is supported, then the browser will use the 'srcset' path to the image and display it inside the 'img' element inside 'picture. Below are the four main <source> tag attributes supported and their role in controlling alternative images:
      • srcset - This works like "srcset" in the 'img' tag. It simply contains a path to an alternate image to use in the 'img' tag, plus a space then a place to add either the width of the alternate image ("320w") or the "device pixel" dimensions ("3x") the image should support. The latter means that the image may be saved at twice the standard PPI or resolutions of the default image, so would look better on say an iPhone or other high definition screen. Like the "srcset" attribute for the 'img' element, this last value is the "expected width" of the alternate image (actual width, not styled) or its resolution, which tell the browser its expected value and help the browser decide when to use the image based on the available width of the user's screen. Example: "srcset=image.webp 320w" means only use this image with actual width "320 pixels" if it can fit into the screen. Again, the 'picture' and 'source' elements do not do anything as far as design. They simply support the original 'img' element.
      • type - The "type" attribute or 'source' contains an image type in a media type format that matches the "media-type" section of "Content-type" format sent by web servers in HTTP headers: type/subtype. Example: "image/jpg" is often used for an image type, and matches the media or MIME type often sent to the browser from a web server as a hint along with the image. Each image type and its format or encoding may or may not be supported by modern browsers, however. Often, the 'source' element is only used to offer very advanced or newer image types, like "WebP", "AVIF", Base64 images, etc. But there is still problems with support of these new formats. For example, the new "AVIF" image format is currently only supported by Chrome Webkit browsers, so would fail for every browser except the newest Chrome versions. "WebP" is another promising alternative "type", but is not supported in any Internet Explorer browsers and many others, like iPhone Safari, which did not support "WebP" until 2020! So, types like this are offered as alternatives only, until browsers in the coming decades support them. But you could add these types of images using your "type" attribute in 'source' elements and thereby offer browsers reading your 'source' tags checks to see if they support them.
      • media - The new media "query" attribute allows you to set both when an image type should be considered by the browser, and any additional scaling (or stretching) of the image from its default value. It allows you to tell browsers when to scale these alternative images larger or smaller. Note that this only works in HTML5 browsers that support these types of media queries. There are two main media type formats to use: "Media Conditions", like "max-width" or "min-width", which relate to a devices viewport width, and "Media Intrinsic Width", which is the width the alternative image should resize or scale (based on a devices screen or viewport, not the image's actual size or styled size). Example: "media=(max-width:800px) 50vw" in a 'source' element means to only use this image alternative if the device or screen is less than 800 pixels, and when triggered scale the image to 50% of the viewport. This might trigger a user on an iPhone or tablet to pull down a higher resolution image thats designed for smaller screens but which is then scaled down an additional 50% to fit into the smaller space. Personally, I would not use the "scale" feature as its wasteful and redundant to scale or distort images. You should have them simply use their original size and resize them and their resolution or PPI in Photoshop.
      • sizes - If you want to rescale or "stretch" you image relative to the screen or viewport, you will want to use this attribute. I do not recommend it as "stretching" images is an old technique thats rarely if ever needed. But you could use this attribute to set a viewport value. An example of all this would be "100vw" which says, stretch the image in width 100% of the viewport. Again, not a good idea. I would rarely use the "sizes" feature unless you are ok stretching your images to fill the screen. Instead, use the "srcset" image width feature, like "500w", or the device pixel check, as in "2x". The first would tell the browser to fit a 500 pixel width image into any screen that is wide enough to hold it. The "2x" if used would says use this image in any screen device that has a "device pixel" value of 2 or higher. This means that the screens pixels are so tiny and can hold so many more than a desktop or laptop that you have created a high resolution image for these types of devices. Most iPhone screens now support 400+ PPI resolutions screen with tiny pixels, which translates into a 2-3x increased pixel density.
    4. Picture with Figures and Captions - In HTML5, the 'figure' and 'figcaption' elements are now used by modern browsers to wrap around 'picture' elements and add captions beneath then in HTML5. The 'figure' element wraps around both 'picture' and 'img' elements, with the "figcaption" appearing under the 'img' element with text describing it. Most photographic websites, online magazines, or article images carry more visual information in the 'img' element than normal, so require a text caption to connect the image with the article text. So, be sure to add captions when using images in HTML5.
    5. Picture and CSS - NEVER style the 'picture' element as its an empty, inline element. Instead, style the 'figure', 'figcaption', and 'img' elements.
    6. For more advanced examples using the new 'picture element, see my two articles below: "How to Display Images in HTML" and "The New Picture Element".
    <plaintext> plaintext

    Plaintext

    <plaintext>
    All content after this element would show text and HTML elements as is.
    My Recommendations:
    1. The 'plaintext' element is a deprecated HTML2 element used by older browsers to create text that ignores all HTML formatting below it and displays content and HTML elements as is. This tag is redundant as you can now control text formatting using CSS and was also never a part of HTML5. Do not use the 'plaintext' element.
    <pre> preformatted text

    Preformatted Text

    <pre>
      &lt;p&gt;Here is my sample paragraph using 'pre'.&lt;/p&gt;
    </pre>
        <p>Here is my sample paragraph using 'pre'.</p>
    
    My Recommendations:
    1. The 'pre' element defines a block-level piece of text in which the spacing, fixed-width fonts, line breaks, and layout are preserved as preformatted text. 'pre' is ideal for displaying computer code. For this reason it is commonly used with the 'code' element, to wrap around HTML, CSS, and JavaScript code that is shared online by developers. The 'pre' element has been around since early versions of HTML, so fully supported.
    2. Facts about the 'pre' Element: 'pre' text is usually in a monospace font by default to differentiate its purpose to the viewer. Because the CSS has supported the "white-space:pre" declaration for years (same look-and-feel as 'pre'), you can now assign the same formatting to any element as the 'pre' tag does using CSS. Therefore, the 'pre' element is not required to create preformatted text in many cases. However, some browsers (pre-IE 5.5 browsers or Firefox on Android) may not recognize this "white-space" value or allow such formatting, except when using the 'pre' element. So, its use is still recommended. WARNING: All sample HTML must be escaped in order to display markup examples inside the 'pre' elements. If you do not escape your HTML it will be rendered in the browser instead of showing the markup code. In the example above, the HTML angle brackets (chevrons) are now escaped with special "ampersand-prefixed" escape characters ("<" brackets in HTML replaced with code, like "&lt;") to show you how that is done.
    <progress> progress bar or indicator

    Progress Bar

    also see <meter>
    <p>
      <progress id="progress1" max="100" value="40" title="Loading Bar in Minutes" aria-label="Loading Bar">40 minutes left</progress>
      <label for="progress1" title="Loading Bar 1">Loading (min)</label>
    </p>
    <p>
      <progress id="progress2" max="1" value="0.8" title="Loading Bar in Percent" aria-label="Loading Bar">80%</progress>
      <label for="progress2" title="Loading Bar 2">Loading (%)</label>
    </p>

    40 minutes left

    80%

    My Recommendations:
    1. The 'progress' element is new in HTML5 and defines a range of fractional values represented visually as a colored image bar. 'progress', unlike 'meter', generally presents a bar showing "progress towards completion", like in a typical "loading bar". Note: Each browser displays this "bar" differently. Some may change the color of the bar based on low or high values. This element was designed as a simple way to graphically represent progression without complex scripting or 3rd party plugins.
    2. 'progress' Attributes: In general, always add a unique 'id' and a 'title' or tooltip to this visual element, so scripts can manipulate or update its attributes, and viewers can get more rollover descriptive information. Remember that visual elements also can fail, or not even be seen by screen readers. So, add an ARIA label.
      The main attributes used are "max" and "value". Unlike the 'meter' element, where you can customize ranges, 'progress' elements always start their minimum range at "0", so have no "min" attribute. "max" must be greater than "0", but defaults to "1" if left off. It can be any integer or a floating number 0-1. I recommend you set it to "1" or "100", this being the value at which an "activity" progresses to 100% completion. The "value" attribute is the current value in the range from "0" to the "max" value, but defaults to an "indeterminate" or unknown value if left off. This means that activity, like "loading", is ongoing and will continue. I do not recommend you do this unless you want to indicate some process is continuing indefinitely or stuck in progress. The "value" is best set at a known integer, or a floating point number of 0-1 in fractions if "max" is left off or "1". The idea with value is it could be reset by JavaScript on a page refresh, or with a new value from the server, to show progress towards 100% of completion. Let the user know its either ongoing, stuck, or soon to be completed using the progress bar and its "max" and "value" attributes.
    3. Sketchy Browser Support: This new HTML5 element is not supported in any older browsers, including Internet Explorer 1-9. But it does have much better support than its cousin, <meter>. It also falls back nicely to text inside the 'progress' tags (as shown in the code examples above) when the visual element collapses. And it supports labels. But many older browsers, IE, will not benefit from that text without the supporting graphic display, which is its hallmark. The graphics will change based on the browser and operating system of the user. The progress bar appears smaller or thinner than 'meter', in many cases. But, I recommend this element over 'meter' if you need a progress graphic element, though it's not widely supported.
    <q> quote, short quotation

    Quote

    Benjamin Franklin is known to have said <q cite="https://www.fi.edu/benjamin-franklin/famous-quotes" title="Famous Ben Franklin Quote">Well done is better than well said</q>.

    Benjamin Franklin is known to have said, Well done is better than well said.
    My Recommendations:
    1. The 'q' element defines a short inline text quotation in HTML5. Unlike 'blockquote', it adds quotation marks around its inner text.
    2. The 'cite' attribute is used to define an online URL source for the quoted text and its web page.
    3. The 'title' attribute is used as a tooltip quotation description and is optional.
    4. Always use 'q' for smaller inline quoted text and 'blockquote' for larger separate blocks of non-quoted text.
    <ruby>,
    <rt>,
    <rp>

    <rb>,
    <rbc>,
    <rtc>
    ruby elements

    Ruby Elements

    Only half of the ruby elements listed here have enough support by browsers today and in the past to be useful. These three ruby elements are the ones I currently recommend you use: <ruby>, <rt>, <rp>. These ruby elements are supported in many older Internet Explorer browsers and in all of the HTML5 browsers, so have the widest support in browsers today. The others are deprecated from current HTML5 browsers and never were supported in older ones. Below are some examples of how to use ruby the right way with the three ruby elements mentioned.


    Here is a basic use of the ruby structure to show you how it is laid out with the 'ruby', 'rt', and 'rp' elements. I have added a few inline styles to "bold" the ruby text. If your browser supports the 'ruby' element it should place the "ruby annotation" text above the "ruby base text". The 'rp' or ruby parenthesis element below is not seen by ruby-supporting browsers, but only appears for browsers that do not support ruby. The 'rp' tags can contain any text you like, but parenthesis are common. If ruby elements are not understood in a user agent, the 'rt' text drops to the right of the foreign language text with the 'rp' text around it.

    
    <p>
        <ruby style="font-weight:bolder;">
            ruby base text
            <rp style="font-weight:normal;"> (</rp>
            <rt style="font-weight:normal;">ruby annotation</rt>
            <rp style="font-weight:normal;">) </rp>
        </ruby>
    </p>
    

    ruby base text ( ruby annotation )


    In this example, I am doing a translation type of ruby annotation. Notice the 'ruby' element wraps around everything and is an inline element, so part of the sentence flow. I have added the "xml:lang" for Japanese to help the browser render the right characters, though it is not required.

    
    <p>This is how we say 
        <ruby xml:lang="ja">
            ようこそ
            <rp> (</rp>
            <rt>welcome</rt>
            <rp>) </rp>
        </ruby>
    in Japanese.
    </p>
    

    This is how we say ようこそ ( welcome ) in Japanese.


    In this example, I am translating text with ruby again, but translating a full sentence this time. In this ruby design, it might be better to drop the text translation below the Japanese text, which you can do with plain CSS styles. In the second example, I have used plain CSS styling to do change positioning of the ruby annotation to the bottom of the language text. Many use the "ruby CSS properties" to do this. The problem is, these special ruby properties have almost no support in older IE browsers and are sketchy in others.

    
    <p>
        <ruby xml:lang="ja">
            東京 に 行き たい。
            <rp> (</rp>
            <rt>I want to go to Tokyo</rt>
            <rp>) </rp>
        </ruby>
        <br />
    </p>
    

    東京 に 行き たい。 ( I want to go to Tokyo )

    
    <p>
        <ruby xml:lang="ja" style="position:relative;">
            東京 に 行き たい。
            <rp style="position:relative;top:2em;"> (</rp>
            <rt style="position:relative;top:2em;">I want to go to Tokyo</rt>
            <rp style="position:relative;top:2em;">) </rp>
        </ruby>
        <br />
    </p>
    

    東京 に 行き たい。 ( I want to go to Tokyo )


    In this example, I am combining "pronunciation" of the Chinese symbol(s) with an added ruby "translation", as well. To manage all this code block, I am also nesting two 'ruby' elements together, plus the added translation after it, so I can separate out the two languages better. Notice that "Welcome" sits above the nested 'ruby' pronunciation set. That is because I used two 'rt' elements. In many cases, the browser will stack the second 'rt' above the previous ruby set that it relates to. As bad as that may look, try and use the browsers "default ruby positioning" and avoid changing it. In older browsers that do not support ruby, the text will appear to the right with parenthesis.

    
    <p>
        <ruby xml:lang="cn">
            <ruby xml:lang="cn">
                欢迎<rp> (</rp>
                <rt>Huānyíng</rt>
                <rp>) </rp>
            </ruby>
            <rp> (</rp>
            <rt>Welcome</rt>
            <rp>) </rp>
        </ruby>
    </p>
    

    欢迎 ( Huānyíng ) ( Welcome )


    Here is an example of the above ruby code but using the new HTML5 ruby elements (<rb>, <rbc>, <rtc>) and a newer ruby CSS property, both of which are now deprecated according to HTML5 groups online. Again, you should avoid these elements as they have almost no browser support. Even if they work ok for your browser, remember no other browsers prior to 2010 or even later will support them, much less many newer ones.

    
    <p>
        <ruby xml:lang="cn">
            <ruby xml:lang="cn">
            <rbc>
                <rb>欢迎</rb>
                <rp> (</rp>
                <rt>Huānyíng</rt>
                <rp>) </rp>
            </rbc>
            </ruby>
            <rtc xml:lang="en" style="ruby-position: under;">
            <rp> (</rp>
            <rt>Welcome</rt>
            <rp>) </rp>
            </rtc>
        </ruby>
    </p>
    

    欢迎 ( Huānyíng ) ( Welcome )


    My Recommendations:
    1. The 'ruby' element represents a set of inline text annotations that are added above, below, or beside base foreign language text. This element is used to help provide translation or pronunciation to foreign language text in web pages by adding a small piece of guide text next to it. 'ruby' has been around since 2003 when the first W3C recommendations were completed for XHTML. Note that HTML4 never supported ruby, so it was not fully adopted until HTML5 (post-2010), though some browsers like Internet Explorer have supported ruby since the late 1990's. HTML5 added support for the XHTML ruby elements, plus added new elements to ruby that are no longer supported by most browsers.
    2. All the Supporting Elements of Ruby: The parent 'ruby' element controls the complete annotation set for a given ruby text. But it includes many other supporting elements. The main 'ruby' element design was never supported in HTML4 but was introduced into XHTML in 2003. It consisted of the 'ruby' parent element which held the foreign Unicode text and an 'rt' or "translation" element that contained the translation or pronunciation of the annotated text. An optional 'rp' or "parenthesis" element was added to wrap translation text in parenthesis and give additional information for browsers that did not support ruby at the time (2003). Those that do will hide whatever is wrapped by the 'rp' tags.
      Internet Explorer 5.5 early on supported ruby annotations, years before XHTML was adopted and supported ruby. But the other browsers did not support ruby for almost a decade! Chrome (2010) and Firefox (2015) were late in support of ruby until HTML5 adoption. But, the above three ruby elements continued to work in IE5 and 6 reliably, thought rarely used.
      In HTML5, ruby was officially adopted in most modern browsers. It also added a few new ruby elements: 'rb', 'rbc', and 'rtc'. However, I am told these have been deprecated since 2016 and no longer supported by most browsers (there may still be support in Asia). For now I do not recommend these new HTML5 attributes due to lack of browser support, and that you stay with the original XHTML ones now supported in HTML5 ('ruby', 'rt', 'rp').
      As mentioned, the 'ruby' element is the parent element for a range of smaller elements that help define the full ruby annotation set. I have included the supported ones and the non-supported ones below. So, if you see these deprecated ones in a web page, you will understand what they were supposed to do:
      • <ruby> or "ruby" (HTML4/XHTML/HTML5) - This is the main wrapper ruby element which creates the association between foreign text and its ruby annotations.
      • <rt> or "ruby translation" (HTML4/XHTML/HTML5) - Used for the purpose of displaying the markup, translation, explanation, meaning, or pronunciation of foreign text.
      • <rp> or "ruby parenthesis" (HTML4/XHTML/HTML5) - Provides fallback parenthesis ("(...)") for browsers which do not support ruby annotations but which need to see translation text inside parenthesis. You can put anything you like here, however, to support translations of text by non-supporting ruby browsers. Note that the text between these tags is hidden from supporting rub browsers.
      • <rb> or "ruby base" (HTML5) - New in HTML5, this element marks the foreign text to be annotated. This element I am told is now deprecated and no longer supported.
      • <rbc> or "ruby base container" (HTML5) - New in HTML5, this element serves as wrapper around 'rb' elements in more complex ruby annotations. This element I am told is now deprecated and no longer supported.
      • <rtc> or "ruby translation container" (HTML5) - New in HTML5, this element serves as wrapper around 'rt' elements in more complex ruby annotations. This element I am told is now deprecated and no longer supported.
    3. Additional Ruby Features: First, realize you can combine translation with pronunciation in ruby. (I demonstrate that in the code above). If your web page is delivered in one language (say English or "en"), but you are using foreign languages inside your 'ruby' element (often in Unicode), it is good to add the "xml:lang={code}" attribute to the 'ruby' element with the language encoding used. Example: <ruby xml:lang="ja"> for Japanese. You can also style ruby 'rt' text to float left, right, above, or below foreign text, though CSS support for special properties for ruby do not have wide support (example: "ruby-position: under"). Internet Explorer has almost no support for these properties. If you must position or style ruby child elements, I recommend you stay with the default browser formats or use a CSS class and say CSS "position:relative" and other traditional CSS properties to align the text as you need. Finally, there were some old properties on 'rt' (like "RBSPAN=3", etc.) and other element attributes no longer supported. So, stay with CSS when changing the design of ruby elements.
    4. I recommend you only use the original 2003 ruby elements (<ruby>, <rt>, <rp>) and avoid the ruby elements, as well as avoid the special ruby CSS properties, due to lack of browser support.
    <s> strikethrough

    Strikethrough

    The store will be closed on <s>9/19/2021</s>. <strong>Now we are open for another month!!</strong>
    The store will be closed on 9/19/2021. Now we are open for another month!!!
    My Recommendations:
    1. The 's' element represents inline quick "strikethrough" text that is no longer valid in meaning, but which is not a textual error or replaced with any correction. Often, browsers will style this text with a "strikethrough" line, which in this case indicates text that no longer has any meaning or validity in the web page.
    2. Strikethrough Confusion: This element is often confused with the <strike> element, which has been fully deprecated in HTML5 and was a design element only, much like <small> and <big> elements. But the 's' element is more often confused with the <del> element, which is supported and also uses a "strikethrough" on text. What is the difference then?
      In the latter case, you only use the 'del' with the 'ins' element, indicating a deleted text string and its text replacement. In the case of the 's' element, it indicates no text replacement, only the meaning of the struck text being invalid.
    3. The New Meaning of the Strikethrough Element: The 's' element has been around since HTML4, and was used in the past for styling any type of text needing the "strikethrough" format. There was no true semantic meaning associated with the element. This implied it could be "deleted text" and replaced with something else, invalid, misspelled, etc.
      But now, the 's' element strictly represents text whose meaning has changed and is no longer valid in the web page, but which has not been replaced. It is not a text error, but a change in meaning. So, you might use this element when posting changes in "facts" that you want to alert users to, like a product's price change comparison, items going on sale, or past events that have changed from previous text. These are not "text errors", like the 'del' element attempts to correct, but alerts to changes in meaning.
    <samp> sample output

    Sample Output

    <p>When I pressed the <kbd>Ctrl</kbd> key, my computer said <samp>"Hello World"</samp>.</p>

    When I pressed the Ctrl key, my computer said "Hello World".

    My Recommendations:
    1. The 'samp' element is a piece of inline text representing sample output from a computer program or script. This inline element is used to wrap around text strings that represent computer text returned to a user. As such, 'samp' is often combined with input values using the 'kbd' element. 'samp' has been around since HTML4 and is still supported in HTML5. This element is similar to <code>, <kbd>, and <pre> in that 'samp' formats text to represent abstract computer values.
    <script> script

    Script

    A 'script' element is a non-visual (invisible) element that is used to download and run JavaScript in your website. Below I have listed a rich set of <script> code examples and the many ways you can use this element to enhance your website with scripts. Note that I have added the right mix of attributes to the code examples below, so you can cut-and-paste my code and get up and running fast knowing that my 'script' examples will work well in most browsers. You just need to replace the "src" URL values with your own values, in most cases.


    Link with External JavaScript Files

    This example below demonstrates one of the two main use cases for the 'script' element in websites today: "External" JavaScript Files and "Embedded" JavaScript Code (or "internal"). I prefer you use this "external" file version of the 'script' element. Why? External style sheets are globally cached for days, weeks, or months by the browser and control the scripting needs of thousands of pages in your websites, unlike their less efficient cousin, the "embedded" script tag which loads script code for just a single web page. The latter type is wasteful and increases the bandwidth needed to support millions of downloads of JavaScript code from your server over years and years. Note: You typically add these links to external JavaScript files inside the <body> element at the bottom of your web page. This forces the browser to delay importing in the JavaScript file until after the main HTML markup in the web page is downloaded and parsed. Note the use of "defer" which helps preload then pause the script until the HTML is rendered.

    
    <script src="myscript.js" type="text/javascript" defer="defer"></script>
    
    

    Script with "Content Delivery Networks" (CDN)

    If you prefer to use CDN's (Content Delivery Networks) to deliver your script files, you can use this version of the 'script' element below that is designed to pull down JavaScript libraries from a 3rd party content provider. This one is free and available to anonymous users. Note: You typically add script downloads like this in the <body> of your web page at the bottom. This forces the browser to load the script last after downloading and rendering the HTML content. Note that I have added "defer" to force the script to pause until all HTML is rendered. I have also added a preprocessing 'link' for the external CDN URL, reducing the time needed to connect to the CDN's domain (see my section on <link>).

    
    <link rel="preconnect" href="//code.jquery.com/" crossorigin="anonymous" />
    
    <script 
        src="https://code.jquery.com/jquery-3.6.0.js" 
        integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" 
        crossorigin="anonymous" 
        type="text/javascript" 
        referrerpolicy="no-referrer" 
        defer="defer">
        </script>
    
    

    Avoid the "Embedded" version of the 'script' Element

    I do not recommend you use this "embedded" script element, as it only allows your scripts to affect a single web page. Unless you truly need a script that only affects a single page in your website, I recommend you use the "external" script version above, instead.

    Note: If you must use these single-page script blocks, I have added an XML-friendly, "no JavaScript support" friendly "CDATA" version to the "embedded" code example below, which is superior to any embedded 'script' coding block you will find online. It supports your page scripts in XHTML 1.1, XHTML5, XML parsers, browsers with no JavaScript support, JavaScript disabled for security reasons, or browsers with full support for JavaScript. Use this version below if you have to use "embedded" scripting. Note: You typically add script blocks in the <head> of your web page. This forces the browser to load the scripts first before downloading HTML content and should only contain scripts that need to be fully preloaded first and which directly affect or control HTML right after it is rendered. Note: The "strange" CDATA code that wraps around the scripts is "extra" code designed to hide/support JavaScript code in the tags from XHTML, XML parsers, and older non-supporting JavaScript browsers (see my recommendations below for a full explanation).

    
    <script type="text/javascript">
        <!--//--><![CDATA[//><!--
    
        alert('hello world!');
    
        //--><!]]>
    </script>
    
    

    My Recommendations:
    1. The 'script' element is used to download or execute scripts in a website. It is typically used to download JavaScript files ("external" version) or run a single block of JavaScript directly in a web page ("embedded version). 'script' elements have been around since the 1990's and have changed very little in the past 20 years. 'script' elements were first used after JavaScript was fully adopted by Netscape and other browsers in the late 1990's.
    2. The Two Types of 'script' Elements: Shown in the code above are the two types of 'script' elements you can use. Both types of 'script' element are used to run scripts (usually JavaScript code) directly in your website. They usually reside inside the <head> section of your web page or at the bottom of the <body> element. Each version of the 'script' element uses different strategies, however, as each type has a different purpose.
      For starters, I recommend you stay with the "external" version (first one above) and avoid the "embedded" one used for smaller script blocks. The reason is, the first type will allow you to use a single line of code for the 'script' element with a "src" attribute that points to a JavaScript file on the server to download. This allows it to download a complete set of JavaScript code one time in the browser and have everything your website needs fully cached for the JavaScript runtime engine to use when it is called. This element may be placed in the 'head' element of your website or at the bottom of the page inside the 'body' element. These 'script' tags often link to a single script file or library of scripts on the server. The browser must parse the 'script' element immediately when encountered in the page and download the script file to your browser. Often the script file is downloaded synchronously or in sequence before other processes in the browser, which means all HTML rendering and processes before the script is encountered are stopped until the script file is downloaded, parsed, and executed. When used, these script "links" allow your user's browsers to download all your JavaScript libraries one time and have their web browsers cache them for weeks or months, saving huge amounts of bandwidth. The browser will then call these cached JavaScript files from your device when running various scripts rather than downloading them over and over from the server each visit by a user. This saves huge amounts of bandwidth, processing, and time.
      The second type of 'script' element allows you to place raw JavaScript or other scripts directly in the browser using 'script' tags. It downloads this block of code each visit to the web page and is not cached unless the page is actively being used or is cached offline. It downloads its JavaScript code one time when the web page loads. However, on each refresh it will be downloaded again, just like HTML. If you have a unique page that needs a small amount of JavaScript specific ONLY to that one page, then removing this script from your larger "external" sheet and adding it to the "embedded" one might be beneficial. However, over time use of this strategy is wasteful and adds lots of bandwidth and redundant code. Note that the format of the "embedded" 'script' element with code inside should always include "HTML Comment" tags, or a full CDATA section wrapped around the inner JavaScript. This allows your 'script' tags to support scenarios where your web page is parsed as XML (as in an XHTML or XHTML5 polyglot page) but will not blow up as invalid XML. It also accounts for rare cases where JavaScript is not supported or even turned off in the browser. The scripts will then not be interpreted as HTML, text, or some other code that gets displayed in the web browser. The version of CDATA and HTML comments I have added to this 'script' example below demonstrates "best practices" when using JavaScript in a web page using the 'script' element. This CDATA code below inside the 'script' element supports HTML5 parsing, XHTML, XHTML5, and very old browsers that do not support the script tag or even JavaScript. In all cases, using the code below will not blow up in any of the browsers or allow your scripts to get rendered accidentally as markup or even text:
      
      <script type="text/javascript">
          <!--//--><![CDATA[//><!--
      
          // put your scripts here
      
          //--><!]]>
      </script>
      
      
      Some History on this Strange Code Above: Going back to the 1990's, you were allowed to place these HTML comments "<!--" and "-->" inside the 'script' element to hide JavaScript text from non-script supporting browsers, which would recognize the HTML comments and hide the scripts. Supporting JavaScript browsers back then would ignore them and execute the scripts. Why? These 'script' and 'style' elements read anything inside the tags as character data or CDATA, which means no HTML is recognized inside the tags. HTML comments are still HTML so ignored by them. So, most browsers that supported JavaScript back then ignored these HTML comments, as anything in these elements was considered CDATA, allowing JavaScript to execute safely for them. By the way, these now defunct older non-JavaScript supporting browsers included IE 1-3.01 and Netscape 1-1.4. For them, the HTML comments meant the script code was safely commented out. These same comment markers above, however, had to be redesigned to support even more scenarios of non-JavaScript supporting agents over time beyond just these older HTML4 browsers. Added to this problem has been XHTML and XML parsers, which do not know the code between these tags is just CDATA. Such parsers would blow up if they parsed JavaScript that contained any XML entities or markers. Many of these XML-friendly parsers did not run JavaScript or scripting parsers at all. To fix the code for them, I had to expand the comments above to force those parsers to ignore the scripting code, as well. And so that is how I came to develop the solution above. In the HTML5 browser world today, nearly all browsers known now support JavaScript. But adding the comments and safety code above allows you to still support a range of very old non-JavaScript supporting browsers, XHTML, and XML parsers combined, should you need to share your code or web pages with any of these parsers or browsers. They will not blow up now when encountering your JavaScript code using the comments above. The code above is completely safe to use now in newer, more modern HTML5 browsers. But when used, it will make sure your JavaScript blocks are ignored in XML parsers and non-JavaScript supporting older browsers alike.
    3. The "src" Attribute: Use the "src" attribute in "external" script tags to link to a URL path to a JavaScript file on the server. The path can be an absolute path, a relative path, or an external CDN or Content Delivery Network script on a remote server (see code examples above). Note that the "src" attribute only applies to the "external" script file download version of the 'script' element.
    4. The "type" Attribute: By default, every 'script' element defaults to a media type of "text/javascript". So you really do not need to add the "type" attribute. But many older browsers used other languages so did not default to javascript types. So I recommend you still add it for now. In HTML5, they recommend you do not add attributes to the 'script' element for that reason. But again because of older browsers, I still recommend you add "type". See below.
      The "type" attribute defines the media or MIME type of the file. This matches what web servers will often deliver to the browser using HTTP headers when sending JavaScript file type "hints". Since the 1990's the most common and most reliable JavaScript media "type" has been the text string, "type=text/javascript". This is still the type I recommend you use. But there are a few wrinkles in this as HTML5 has brought new changes. New recommendations in HTML5 says the MIME type for JavaScript should now be "application/javascript", not the old "text/javascript". It turns out, however, these new changes really don't matter much until you start using higher "planes" of unicode characters and languages in your JavaScript. The problem using the new type is that old Browsers will not know what that new type is and will possibly fail to parse your script file as a result. So, you need use the old type for now. The browsers that fail the most using this new HTML5 script type include Internet Explorer versions 1-8. If you leave off the "type" attribute in many new modern browsers the "default" script tag value is still "text/javascript". To solve this and let browsers decide, HTML5 recommends you just leave OFF type="text/javascript" from the 'script' tag. But again, I recommend you still use "type=text/javascript" on the 'script' element as I like supporting older browsers, who by default might not know its still the old type or have a default type. This media "type" attribute, however is still a "hint". Keep in mind, the "type" of javascript used in HTML pages as in 'script' tags is determined by the "Content-type:" value sent by the server first via HTTP, which also includes the charset, which you can also add to the 'script' element. (I do not recommend you use "charset" in the 'script' element though, as it is almost always utf-8 anyway, though script rendering engines in browsers usually ignore this and sniff the file encoding type themselves). But the script media "type", browsers almost always look at the script tags "type" AFTER looking at the HTTP "Content-type" value from the server. The server type most often delivered remains "text/javascript". So just to be safe, use the attribute "type=text/javascript" to match what most servers still use and not cause confusion or risk breaking script executions in older browsers like Internet Explorer, which in older versions allowed use of VBScript instead of JavaScript.
    5. Use of Legacy Attribute, "language=javascript" - For now you do not need to use this old attribute in 'script' tags. In the old days, many browsers like Netscape 3-4 supported various versions of early JavaScript. Often there was no way to tell Netscape what version of JavaScript to use. Remember, Internet Explorer 3-5 used JScript, its own form of ECMAScript/JavaScript. But in the old days, Netscape supported many versions of JavaScript.To help with this type of scripting support, many web pages with 'script' elements for Netscape 4 Series (c.2000) had the attribute "language=javascript" or "language=javascript1.2" or "language=javascript1.4" added with the version of JavaScript used. "javascript" defaulted to "javascript1.0", but you could choose later versions. All these versions were very 1990's versions of early ECMAScript/JavaScript no longer used. At this time, only in rare cases, it would not hurt to add this attribute to support old Netscape users. But because this browsers is so rarely found in the wild, I do not recommend it, unless you have a unique user base with this old browser.
    6. CDN and referrerpolicy="no-referrer" - Use this attribute and value if you want to block the external CDN sources from getting your user's referrer or source information. This blocks the origin data sent to their servers, which shows up in their logs every time a visitor of your web page uses one of their external scripts. Note: If this prevents you from accessing the external file, then you might have to remove it.
    7. The 'script' element and JavaScript: I will not be covering JavaScript and its history, as that is a separate and very large topic. Know that Javascript was not supported until Netscape 1.5 in 1995, but not fully implemented until Netscape 3.0. Support for the 'script' element pointing to external JavaScript files in web browsers was not supported until Internet Explorer 3.02 and Netscape 4.0 series in 1996. After that, use of the 'script' element became widely used as the various flavors of JavaScript in Netscape and Internet Explorer evolved after 1998. So, the 'script' element has been around a long time and still works the same as it did over 20+ years ago. As always, very little changes in the HTML world despite lots of people trying to wreck its elegant simplicity!
    8. The External 'script' element and Preloading - This discussion below only applies to the first "external" 'script' type, the one that links to a JavaScript file on the server.
      Trying to "preload" or enhance the performance of scripts downloaded from a web server is the act of a browser trying to load scripts as early as possible, yet without interrupting the downloading, parsing, and rendering of HTML. But this idea of speeding up script performance through some magical "preloading" or lazy loading of JavaScript code by tricking the browser is a dream as old as JavaScript and HTML. Yet, this act of speeding up file downloads or prevention of blocking of HTML rendering is often taken care for you by modern browsers in a very efficient way. Often there is nothing you need to do or change. But, note that this concept that you can somehow radically improve what browsers have been doing naturally for over 20 years changed radically with the use of heavy JavaScript use in websites the past few years.
      The main focus of many new developers and search engines in 2022 is how much faster web pages need to load, despite the advent of faster and faster optical cable lines and lightning speed 5G mobile networks. The irony is too sweet. Their idea now is that, as HTML gets parsed and the DOM is rendered, any external files or media that delay (or "render block" as they say) that process can slow down this web page process. In the majority of cases, plain HTML never causes problems, nor does external CSS style sheets, or much else. Yes, video on-demand and giant images can slow down some things. But often browsers over high speed networks download these files very quickly, now. Any real delays are more likely caused by slow connections and slow servers...not minimized "render blocking" CSS or HTML. Despite these concerns, developers have recently started using these heavy JavaScript API's that are very large in size. They have now moved from a server-side web model to a thick client-side model. As a result, this change has radically increased the megabytes of JavaScript loaded into the browser since 2010. Because of these JavaScript API's, the average volume of JavaScript shoved down the throat of most browsers in 2020 according to resources online is over 1.5 Megabytes!!! Sorry, but that is the problem. And that is the real cause of the bottleneck in slow web page rendering and search engine performance today.
      To address this issue, many JavaScript developers have not reduced their volumes of client-side scripting but instead tried to minimize and squeeze as many extra bits and bytes of code as possible from these gigantic libraries using minimizers, async'ing all external files, lazy loading scripts, using modular JavaScript components, and compressing or delaying CSS style sheet downloads. It is a real mess, as it's distorted the true nature of HTML and moved websites from simple markup displays to huge complex JavaScript applications that drive CPU's and download delay times up on mobile phone and desktop browsers alike. They have then added large preprocessing to files that add more and more dependencies, with very little performance gains to show for it. The solution to all this mess is not to strip out more spaces from code, minimize CSS, or delay external file downloads, but to stop downloading so much JavaScript!! It is just unnecessary and proves the collapse of thick client-side technologies will someday happen as they grow larger and larger. A return to simpler HTML and older server-based solutions is coming as a result, now.
      In the mean time, I have simplified a long list of these "preload tricks" used today when using the 'script' tag and its attributes. The idea is to attempt to reduce the delays caused by downloading these huge JavaScript files into the user's browser. In reality, these tricks are not that effective and might shave off a few hundred milliseconds from JavaScript download times. There just are very few tricks available for controlling JavaScript use, parsing, or downloading times in most browsers, beyond simply reducing the size of these giant libraries. But why is that, you ask? The reason is, many modern browsers now have very sophisticated solutions for managing these files and their connections and downloads, often without any help from your or I. There are also only 2-6 open and available connections by default in most browsers today when downloading images, code, scripts, and external media found in most modern websites. Many of these will be used by CSS files or images, so your scripts may be delayed by these very limited available connections. Your server also controls how fast it responds to those connections and download streams. In other words, it's rarely the code but the server and the browser that delays rendering of web pages in 2022. And like I said, most website HTML and CSS is not that large a download, anyway. The fact is, when it comes to JavaScript, you can only "trick" the browser so much until you just have to change how you use and manage your web application models using these gigantic JavaScript libraries.

      Below are a few things I recommend in trying to preload 'script' files and which I have added in my code examples above to help you squeeze the most performance from your 'script' tags using JavaScript. In the code above, I have added the attributes and code that will work best, so you can cut-and-paste the code as is, knowing I have added just what you need in your HTML5 code to improve a little on download times. But, below are all the dirty details of why I elected to use the code above:

      Tricks to Improve JavaScript Downloads

      • ALWAYS put your "embedded" script blocks in the 'head' element of your web page and with as little JavaScript content as possible. Never put this element in the 'body' element as that may delay its parsing. When placing scripts in the 'head' element of your page, ONLY add scripts into the 'script' element that are required to help render the HTML for display purposes in the DOM or trigger events that affect the page's final design. Placing these scripts in the 'head' area means they load events instantly and run right away as soon as events like "onload" or other page loading events fire. This allows these early scripts to execute as soon as the HTML is complete, as these types of embedded scripts usually need to control some aspect of the final HTML markup in the DOM. Remember: "embedded" scripts only affect one page, and are not used or cached for other pages in your website like "external" 'script' files do. So use them sparingly, if at all!
      • ALWAYS put your "external" script links, or any globally cached JavaScript files needed by the whole website, at the BOTTOM of all your HTML content inside the 'body' element. They will start downloading after the browser has downloaded the HTML above them and has parsed and rendered everything else. However, this order of processing is not guaranteed (see "defer" and "async" attributes below to fix that) because browsers will pause all processing when they encounter a 'script' element and must download, parse, and run the script, possibly delaying rendering of HTML. Note that, if you have critical JavaScript files which affect the rendering of the browser's DOM, then you DO want scripts to delay such parsing, stop all processes, and load their JavaScript files immediately. An example of this are the new Single Page Applications (SAP's) using these new JavaScript API's. Their 'script' tags will often need to appear at the top of the page in the 'head' element along with your 'link' CSS files. They will then download first or possibly in parallel with HTML, as they often control and manage the final DOM in the page. The rest, like JQuery scripts that manage animations or form validation, can be delayed. So, they should be placed at the bottom of your HTML page after all your HTML markup. Some scripts can fail even if loaded first or last and so still delay HTML parsing and rendering. Placing those dependent scripts last in your web page location guarantees that the page source order of any processing markup prior to running scripts is followed first in the page. Also, unless all the HTML markup is downloaded and available in memory, many scripts will also fail if they cannot find certain elements or events fire too early. This can also happen if they are not listed last in page order or run before all html is fully loaded. As a rule, you shouldn't rely or trust on any script order or prior parsing of any markup in any browser and add checks in your script to make sure elements even exist before running the script and add "onload" or other events which must fire first. But it still improves page performance to have all scripts but required ones run last in the web page.
      • ALWAYS put your "external" script links in a logical order of most important to least important at the bottom of your web page as browsers start downloading files initially in a sequential order. This may change based on the size of the files, using "defer" or "async" attributes (see below), or as connections open up. But, this is generally how browsers work. Some unusual properties of web pages include the fact that the browser will intelligently try and load some items in parallel into memory, as well, if enough connections are available. But source order of markup and scripts is still often strictly followed. This little order rule could save your page's overall performance as larger, less reliable scripts are downloaded last.
      • ALWAYS try and use the attribute "defer=defer" in your "external" script links to delay their use as long as possible until the DOM is fully rendered in the browser. This new "defer" attribute allows scripts to load in parallel with each other and with the downloading and rendering of HTML without delaying it. Deferred scripts once downloaded though, will not begin running until the complete HTML markup and page DOM is fully loaded, parsed, and rendered. Otherwise, by default, when browsers see 'script' elements, they will starting downloading and running script immediately, halting or delaying HTML rendering in the process. "defer" in the past told browsers the 'script' element will not generate any content and could be skipped by the HTML parser until all other content is downloaded. Therefore, the browser can continue rendering the body without considering the script element contents.
        Most browsers today, however, run the deferred script download in a parallel thread to all other downloads and processes as fast as possible, but do not delay HTML processing and delay running the script until the HTML is done and the DOM is ready. "defer" thus allows the elimination of parser-blocking JavaScript, where the browser would have to load and evaluate scripts in encounters in the page before continuing to download and parse HTML, causing a small page delay for the viewer. Deferring "non-essential scripts" is preferable and should always be used in pages with JavaScript linked via external files, especially those placed in the 'head' element where most of the delays can occur, UNLESS the script is critical in rendering the page. Otherwise, this attribute defers execution of JavaScript until all HTML downloading and parsing is completed. Note that multiple deferred scripts with the "defer" attribute all download in parallel, do not run their script files until the page is rendered, and honor script link order executed, whereas script tags with the "async" attribute (below) each run independently of each other and the order so they could arrive first or in any order at any time, and even delay other scripts by consuming connections. In practice, "defer" is used for scripts that need the HTML completed and the whole DOM rendered first before they can manipulate HTML and where their relative execution order is important. That is why I like to add "defer=defer" to all or most of my 'script' elements, including JQuery or validation scripts that do not need to run until after the page loads. In general, this attribute benefits most situations, except the heavy JavaScript API type files, like Facebook React and Google Angular, that do not need to be delayed for any reason and must get up and running as quickly as possible to build out the DOM themselves. Note that moving 'script' elements to the bottom of the web page is a form of "defer", but not guaranteed as using the attribute, as any script that downloads before HTML could stop its parsing and rendering. Note that IE 10 and later support "defer". In the past, there was a "fallback" strategy to help older IE browsers by using "async" and "defer" both as attributes. But that's no longer needed. Use "defer" in most cases.
        You can test when your scripts run by running this JavaScript code below. Deferred scripts will only fire after both the page is loaded and the DOM is built. You can test when that happens in your page using this script:
        
        document.addEventListener('DOMContentLoaded',
            () => alert("DOM ready after defer!"));
        
      • ONLY USE use the "async" attribute for JavaScript files that can be downloaded in parallel with HTML like "defer" but which must execute immediately or as soon as possible, pausing HTML or other parsing if needed. If you use the "async" attribute, understand it's used to fire up scripts as soon as possible. These types of script downloads might be best used with advertising displays, counters, or items that can appear immediately in a page, even if it means a short delay in page rendering. "async" works like "defer" in that both attribute types download without delaying HTML rendering, initially. But "async" will stop rendering and start running its code the minute its done. While the JavaScript is executing, it will stop all HTML processing until its completed. For this reason, I rarely use "async" in 'script' elements. Remember, unlike "defer" which downloads in order, "async" tells the file to start downloading in any order, as soon as an open connection is available. Take note, that not using either attribute means the browser synchronously downloads, parses, compiles, and executes JavaScript first, delaying HTML processing until its all done executing. Note that moving 'script' elements to the bottom of the web page is a form of "async", but not guaranteed as using the attribute, as any script at the bottom of the page that starts downloading could stop HTML parsing and rendering. IE 10 and later support "defer", where as IE 8-9 supports "async". In the past there was a "fallback" strategy to help older IE by using both "async" and "defer" as attributes. But thats no longer needed.
    9. Browser Support: 'script' elements have wide support in nearly all modern browsers and many older ones. So, they are fully supported.
    <section> section

    Section

    See also <header>, <nav>, <main>, <section>, <article>, and <aside>
    <section id="content" aria-labelledby="mainheading1">
      <h1 id="mainheading1">Section</h1>
      <p>Web page content goes here...</p>
    </section>
    Main

    Section

    Web page content goes here...

    Footer
    * A typical web page structure is shown above.
    My Recommendations:
    1. The 'section' element is new in HTML5 and defines an independent, self-contained piece of page content. It is used for defining a larger block-level area of content in a web page. Typically, the 'section' element is a child of the 'main' element and houses all of the text content found in the web page. There may be multiple sections, sections holding multiple 'article' elements, or multiple sections inside an 'article' element. Unlike its twin, 'article' which contains text content, 'section can contain almost anything. In HTML5, the 'section' is part of a set of new structural page elements that define the overall layout of most HTML5 website pages designed today (<header>, <main>, and <footer>, etc.).
    2. The New HTML5 Structural Elements include: header, nav, main, footer, section, article, and aside.
    3. ARIA: The 'section' element is a top-level, "self-describing" structure recognized by most modern screen readers without additional assistance. In the case of 'section', it is recommended you add an ARIA "aria-labelledby="mainheading", then inside 'section' add your top header element with an 'id' value that matches. This then allows screen readers to associate the web page's main top heading (h1) and title with the main content section of the web page.
    4. See the <main> element section for more details about this new HTML5 element.
    <select> select

    Select

    see <option> and <optgroup>
    see <form> for more details using <select> in forms

    Shown below is a complete code sample of the <select> element, which you can copy-and-paste into your web project. It has a rich set of attributes I recommend you use for each scenario. The visual design for this form is shown below the code. With these examples you have a complete set of code you can use in your web forms.


    <form id="formselect" name="formselect" method="post" action="#" title="Select Example" aria-label="Select Example" autocomplete="off" autocapitalize="off" spellcheck="false">
    <fieldset id="formselect_fieldset1" name="formselect_fieldset1" form="formselect" style="background-color:#fff;">
    <legend style="background-color:#aaa;color:#fff;">Select</legend>
    <div>
    <label for="formselect_select1" title="Single Select">Single Select Label:</label><br />
    <select id="formselect_select1" name="formselect_select1" size="1" title="Select an Item" aria-label="Single Select" tabindex="0">
    <option selected="selected" value="">-- select a fruit --</option>
    <option value="strawberry">Strawberry</option>
    <option value="banana">Banana</option>
    <option value="grape">Grape</option>
    <optgroup label="Apple" role="group">
    <option value="apple_reddelicious">Red Delicious</option>
    <option value="apple_macintosh">Macintosh</option>
    <option value="apple_green">Green</option>
    </optgroup>
    </select>
    </div>
    <hr />
    <div>
    <label for="formselect_select2" title="Multiple Select">Multiple Select Label:</label><br />
    <select id="formselect_select2" name="formselect_select2" size="6" title="Select One or More Items" aria-label="Multiple Select" multiple="multiple" aria-multiselectable="true" tabindex="0">
    <option value="" selected="selected">-- select multiple numbers --</option>
    <option value="1">one</option>
    <option value="2">two</option>
    <option value="3">three</option>
    <option value="4">four</option>
    <option value="5">five</option>
    <option value="6">six</option>
    <option value="7">seven</option>
    <option value="8">eight</option>
    <option value="9">nine</option>
    <optgroup label="ten to twenty" role="group">
    <option value="10">ten</option>
    <option value="20">eleven</option>
    </optgroup>
    </select>
    </div>
    </fieldset>
    </form>
    Select

    Single Select Example

    A select form field is also called a "dropdown" or "list" by some. Below is a standard single 'select' element. I am also using "optgroup" in the 'select' element below to show how items can be grouped.



    Multiple Select Example

    You can add the "multiple=multiple" attribute to support multiple choices, as I've done below. Hold the Shift key, then select multiple rows of options. Or, hold the Ctrl key to select multiple options one at a time from the 'select' element.


    My Recommendations:
    1. The 'select' element defines a type of form field control used for showing a group or list of items in a box that one can choose and submit to the server. The 'select' element has been around since the 1990's and in the earliest of HTML recommendations by the W3C. Like most form controls, the 'select' element is considered a "replaced" element, as its design and actions are controlled by the browser and operating system. It has changed very little in the past 20 years, so is a bedrock form field element supported in all browsers and versions. As such, it can be safely used in all your web forms.
    2. What is a Dropdown?: Since 1996, there have been many names given to "select" that confuse developers and users alike. The main reason for the confusion was that old Windows desktop software engineers refused to embrace HTML and the web as something unique unto itself. It has its own design and use limitations in browsers. But early engineers tried to layer over Windows application design concepts onto the Web, and over time they failed to change or define it. (That is why ASP.NET has gone through so many redesigns at Microsoft and failed the last two decades.....software people refused to respect, much less understand, the true simplicity and power of HTML!). Often we were stuck with desktop software terms for "select", like "list", "listbox", "dropdown", "multiselect controls", and many other confusing OS or API terms and definitions, all of which ended up spitting out the same "select" element into the web page, at the end of the day. They used these terms as they helped them remember the good 'ol days of Windows desktop applications from years ago when they built their various types panels and modal windows of dropdown boxes and lists that often filled grayscale panels in screens. But all this ended up confusing everyone on the Web using new tools and standards! ("dropdown"?....you mean "select"?) Why didn't they just call it what it was, "select"? lol. After decades of confusion, I encourage all new web developers to stick with the term "select" rather than "dropdown", "listbox", etc.. Besides, the "select" term happens to be the name given to the actual HTML element! That way we are all talking the same language, which is HTML - the Language of the Web!
    3. Always Wrap a <form>: Element Around Your 'select' Elements: When you wrap a form tag around a 'select' control, it tells the browser your 'select' is associated with a specific form "id" value and will only submit the field elements associated with that control. If you have multiple selects and form fields to submit to a web page, it is crucial you know what select belongs with which form. You can still place the element outside a form if you give it a 'form={id}' attribute with a value associated with a specific form "id". In that case, it will be submitted with all the fields inside that specific form, though it might lie outside the form. However, I do not recommend you move form controls outside of a form, as some older browsers may fail to send the right data when submitted.
    4. Always Use the <label> Element with Your 'select' Element: Try and use the 'label' element before your 'select' tag, then add the "for" attribute with a value that matches the select's 'id' value to associate the two together. This links the label to the form field and allows the browser, search engines, and screen readers to connect the two, adding semantic meaning. Often, the browsers will float the label text above the select control. But I have added a break after it as select boxes tends to float right as an inline-block element (see my code samples above for examples of labels and select controls). "clicking" on the label's text auto-selects most form fields, but not in the case of select. However, giving your 'select' element a label is still important. Be sure to add a descriptive 'title' attribute to your label, as well.
    5. Collecting Form Field Data Using Select: The process of using 'select' elements and other form fields to collect and process data is way beyond the scope of this tutorial. The single most important aspect of good form field design (beyond HTML) is validation. That is discussed in-depth in the 'form' element section. The main thing to understand about forms and form fields is that data collection is the single most complicated aspect of web design, simply because it requires so many levels of exchange, validation, processing, analysis, and storage. Data collection and processing of form field element data is way beyond the scope of this tutorial. Just know, I have built dozens and dozens of large data collection applications in my life-time, and I can tell you good data collection always begins with solid HTML design, not fancy JavaScript, not fast REST API's, not secure server processes, not relational databases, and not fancy business applications. HTML is always King simply because HTML is the gateway between your users, your server, and your database.
    6. Always Use the 'id' and 'name' Attributes: Always use 'id' and a matching 'name' attribute with the same value when possible on all form field elements. The 'id' affects client-side scripts that must access a unique 'id' on the form field in order to access the control and its data. But 'id' is never sent to the server, unlike 'name'. If there are multiple select controls provided to the user, it is critical each have an 'id' and matching name. These value pairs must be unique for each element in the current web page. As mentioned, I like to always match the 'id' value to the 'name' attribute, as I do in all my other form fields. Why? The 'name' attribute is what is always sent to the server, along with the input's "value" attribute. Assigning both 'id' and 'name' to the same value helps your server-side processes identify which form field you are processing and align the field's 'name' on the server or in the HTML with any client-side scripted validation or pre-processing that uses the 'id' value. If the two attribute values match, it's very easy to locate and sort client-side from server-side processes. Also, in form fields the 'name' attribute is often parsed first as it is used when building name-value form field key-value pair data system sent to the server on submit. So, be sure to give each 'name' a unique value, match the unique name to the 'id' element, and be sure to put both first in the element!
    7. Always Assign a 'value' Attribute on all 'option' Elements: When a user choose one or more items from your 'select' element then submits the form, the 'select' element's "values" are sent to the web server along with the "name" of the 'select' element, when the form is submitted. For that reason, always add a "value" attribute inside each 'option' element, even if empty, with its text or data attached. Example: <option value="{value}">>My Option</option>. Often the text name inside the 'option' element is the same as "value" (like "yes"/"no", "on"/"off", etc.). But it can also be different from the "value". This is what is sent to the server as data, and part of the "name-value" attribute pair sent to the server from your form control when the 'select' is submitted. In the case of a 'select' element set as "multiple=multiple", each selected "option" will always send the same 'select' element "name" value for all the 'option' "values" selected. So make sure each 'option' "value" is unique, as you have to loop through the same array of names to get each value selected. The data for multiple select choices sent to the server will appear like this: myselect=1&myselect=2&myselect=3. IMPORTANT: If the "value" attribute in 'option' is omitted, the value is taken from the text content of the option element! Some older browsers will always do this. This is why, as a rule I try and match my text string to the value, unless its multiple words, a non-unique value, or the value is in another non-friendly format, like an abstract number, id, or value a user will not recognize.
    8. Use the 'size' Attribute: Use the 'size' attribute to change how many selections are shown in the listing. The default is "1", but changes to a larger value when the "multiple" select attribute is added. I like to always set this to "1" for plain 'select' listings, and then set it to four or more for my multi-selects. You can also set it to the number of items in the 'select' element so every one is immediately shown and available to be selected.
    9. Use the 'multiple' Attribute: If you need users to select more than one item from your 'select' element, add the "multiple=multiple" attribute. The box will then be resized to show multiple items by default rather than just one. This shows users that multiple items can be chosen. I like to set the first 'option' element in the list with an empty "value" attribute and to say, "-- choose multiple items --". This instructs them on what to do with the multiple-select listing. Remember, in multi-selects, you can either hold the control key on your keyboard and select multiple, one at a time, or hold the shift key and select large blocks of items at once.
    10. Always Assign a 'tabindex' Attribute Number: Almost all browsers, old and new, add form field elements to a "tabindex" list. This means that all interactive elements are available for tabbing through by a user in the browser as they fill out larger forms. You really do not have to add this extra attribute to your form field elements or worry about this feature as it's built into all modern browsers. Most of the old ones, as well new ones will logically add all your form fields and buttons to a tab list. Nearly all form fields, links, and buttons are added to the tabindex, by default. However, you can manipulate this to change the tab order of your form fields in the index, remove a form field control from the tabindex, or add one that was missed by using the "tabindex" attribute. I always add the "tabindex=0" attribute to all my form fields to enforce addition of each control to browser's tabindex, which also lets the browser reorder everything, naturally. I add "tabindex=-1" to remove fields from the tabindex I do not want included. "hidden" types fields are never added to the tab index anyway, but I add the "-1" value to all other interactive form controls I don't want users stumbling across (including disabled fields, read-only fields, etc.). You can also granularly control tabindex by setting each of your controls to a specific number in an order, like "tabindex=2", and set the specific order you want your users to use. You can also set "autofocus=autofocus" to force focus immediately to a specific select field after the page renders. This overrides the natural tabindex, however. You don't have to override these features in browsers unless you want to change tab indexing. "tabindex" and "autofocus" can help enrich your forms and add more control over how you intend users to use them. See my code samples above which use "tabindex", and read my section in this page called "TabIndex and Autofocus in HTML" for more details on "tabindex".
    11. Title, Required, Disabled, Read-only, and Hidden Attributes - Always add a "title" tooltip attribute as it provides a nice rollover description of your form field control. For any form field that must be filled out or selected, you must use the "required=required" attribute. Required text means the form field must be filled out with some data by the user or an error will be generated and the submission will fail. This attribute can be overridden by add the "novalidate=novalidate" on the form or form field. Be sure to set any 'select element' you do not want sent to the server as "disabled=disabled" in your inputs. Data you do want sent to the server, but not changed by the user, should be set using the "readonly=readonly" attribute. Also set "tabindex=-1" on these "disabled" and "readonly" controls so the user does not tab through them. In modern HTML5 browsers, a form field element with the added "hidden" attribute will not be seen by the viewer but remain an active form field. But, if the browser does not supports HTML5 your form control will not be hidden! The new "hidden" attribute is redundant, however, as there is a "hidden" 'input' type you can use instead which is always hidden and always submitted. But, there may be rare cases where you just need to hide it. In those situations, I recommend you use CSS "visibility" instead to hide things, as it will work more reliably in older browsers. If you use "display:none" to hide controls, remember the input will not be seen AND will not be sent to the server on submission, unlike the CSS "visibility" property or the "hidden" element attribute. See my section called "How to Hide HTML5 Elements and Content using CSS" for more information on hiding elements in HTML correctly.
      Note: Always use the "XML-friendly" version of these attributes so your tags are always cross-compatible with both XHTML and XML. Do not use "readonly", but type "readonly=readonly".
    12. Optional 'novalidate': I discuss this attribute in more detail under the 'form' section (see <form>), as the form really controls this setting over all its child fields. But often you will have a 'form' with default settings and want to override them in each form field. A difficult one to manage is "novalidate". In general, the code samples above showcase my "best practices" and recommendations for how each field should use this attributes.
      The good news is "novalidate" is removed by default, meaning validation is enabled for the select control, which in my opinion is a good thing as HTML5 browsers now come with a new array of validation checks and features. Again, see my 'form' section for more details on how these work and some additional tricks to force them to do what you expect. But if you want to turn off validation on a field and override the 'form' element's default value, you can add the "novalidate=novalidate" attribute to your element.
    13. Do Not Use "accesskey": I do not recommend use of this attribute. Long ago, it was designed to allow keyboard presses to access form fields. But it is not reliable and requires various additional combinations of keys to work that are specific per device or just not accessible. It also conflicts with operating system shortcuts and could trigger other features on a laptop or phone by accident.
    14. Do Not Use New "inputmode": This new attribute is gaining in popularity, but still poorly supported in browsers. "inputmode" is now used as a "hint" to tell browsers the type of data to expect, like "email", "search", "url", etc. Because its not supported in IE, Safari, or Firefox browsers prior to version 24, it is not helpful or reliable.
    15. The Optional "data-" Attribute: As mentioned below in my "Best Practices" article called "The New 'data-' HTML5 Attribute", you can now safely use the new "data-" attribute in any HTML form element to store extra data values. Know that this is an extra attribute, and that "data-" values are not submitted to the web server anyway, so pretty useless. Its mainly an add-on for JavaScripted frameworks on the client-side.
    16. ARIA Attributes: The 'select' element is another "self-describing" structure recognized by most modern screen readers. Most screen readers can read each select box quite well, and understand what each one does. So, they do not need the ARIA "role" attribute. But they do need help knowing what type of data is being selected so they can identify its semantic meaning. For that reason, it is recommended you add an ARIA "aria-label={Name of Item}" on each 'select' element to give screen readers more details about your 'select' does and its meaning within the form. You should also use the "aria-multiselectable=true" on multiple 'select' types. You do not need the ARIA "live" attributes telling screen readers the "state" of your controls as they change unless you are manipulating the DOM using JavaScript. Use my code samples above to see "best practice" uses of ARIA attributes when designing select controls that assist screen readers.
    17. See the <option> and <optgroup> elements for a list of recommended attributes (I have tried to include those in the 'select' code examples above).
    18. Form Field Validation: As mentioned above, and in the <form> section, it is not enough to drop form fields like 'select' onto web pages and then hope the data coming into the server works. I have found too many cases where poor data processing ends up destroying a website! Even with fancy JavaScript, you cannot ignore the HTML design and server processing. That also includes heavy database scrubbing and processing. You need to always validate your form fields, no matter what the type, in ALL layers of your application. Do it, not just to improve data collection, but for security reasons as well! Data validation is not part of the scope of this tutorial but is native to the specific language, framework, network, and database architecture you are using. Don't rely on a single product like JQuery (JavaScript), either. Rely on good server-side validation, always, but good HTML design, too. It will help the user get the data right on their end without waiting on elaborate scripts to warn them later. Getting the HTML design right helps them navigate your forms faster, and makes it much easier for them to enter good data. Good HTML means it's one less layer you have to wrestle with. And it frees up control of data entry to your users, not your script libraries or your server.
    19. Trouble Styling Replaced Controls with CSS: "Replaced" elements like 'select', 'textarea', and others are notoriously difficult to style using CSS and have been for years. The reason is, they are not part of HTML but controls generated and dropped into the viewport by the browser. This is why these controls look so different between Macs, Windows PC's, and mobile phones. The browsers on these devices call the OS which helps determine their designs. Without getting into all the "hacks" and fixes out there to try and override these OS controls, I highly recommend you use plain HTML then stay with plain CSS code to style what you can and avoid all JavaScript, Modernizr, Polyfills, or "scripted hacks" to try and change their native designs. There are some clever CSS styles you can apply that alter the look-and-feel of these controls enough using just a few lines of CSS text that they are "presentable" and look close to the same across old and new browsers alike. There are also "prefixed" CSS rules (browser-specific styles like "-moz", etc.) that also can safely be used and which avoid JavaScript completely. If you start using scripts that hide or replace the HTML with a new form of control, you not only add complexity and unnecessary "hacks" that will likely cause form submission issues, but often it will fail completely in certain older browsers. In addition, your HTML will now be too complex for others to customize and likely erased when the next developer comes behind you.

      Below, I have added a very clean, widely supported piece of CSS code you can use to give your 'select' element a nice clean style that looks the same across many browsers and versions. This is the basic style I use for the 'select' example above:

      
      select,
      select:visited,
      select:hover,
      select:focus,
      select:active {
      	display: inline-block;
      	width: auto;
      	height: auto;
      	min-width: 0;
      	max-width: none;
      	padding: .17em .17em;
      	padding: .17rem .17rem;
      	margin: 0;
      	text-transform: none;
      	border-radius: .2em;
      	border-radius: .2rem;
      	border: 2px solid #bbb;
      	background: #fff;
      	cursor: pointer;
      	-webkit-appearance: listbox;
      	-moz-appearance: listbox;
          line-height: normal;
      }
      
      select:visited,
      select:hover,
      select:focus,
      select:active {
      	background: #f9f9ff;
      	border: 2px solid #999;
      }
      
      select:focus {
      	background: #fff;
      	border: 2px solid #999;
      }
      
      
    20. See the <form> element section for more details about this element within a form.
    <small> small, smaller

    Small

    This is some <small>small</small> text.
    This is some small text.
    My Recommendations:
    1. The 'small' element was used to show smaller text in an inline block of text.
    2. Do not use the 'small' element as it is deprecated now and was a member of old HTML4. Use CSS and 'font-size:smaller' on spans of text instead, like this (you would move the inline style below to a CSS class):

      This is some <span style="font-size:smaller;">smaller</span> text.

      This is some smaller text.
    <spacer> spacer

    Spacer

    <p>Some text<spacer type="horizontal" size="20"></spacer>some text</p>

    Some textsome text

    My Recommendations:
    1. The 'spacer' element is deprecated but was a non-standard HTML element used by older browsers to create white space. This tag is redundant as you can now control spacing using CSS and was also never a part of HTML5. Do not use the 'spacer' element.
    <span> span

    Span

    <p>Lorem ipsum dolor sit amet, mea enim erat id, regione iudicabit consetetur ius ex. Qui vide errem ut, ius id movet atomorum. <span style="color:blue;font-weight:bolder;">Sit pericula definiebas ei</span>, ex eam essent maluisset. <span style="color:red;font-weight:bolder;">Duis ceteros pro ut.</span> Mei eius labore ut. Iusto facete facilisi vel id, nonumy omnium constituto ad pro. Mei in sale option.</p>

    Lorem ipsum dolor sit amet, mea enim erat id, regione iudicabit consetetur ius ex. Qui vide errem ut, ius id movet atomorum. Sit pericula definiebas ei, ex eam essent maluisset. Duis ceteros pro ut. Mei eius labore ut. Iusto facete facilisi vel id, nonumy omnium constituto ad pro. Mei in sale option.

    My Recommendations:
    1. The 'span' element represents a small inline piece of text. Unlike the <p> element, the 'span' element wraps around smaller pieces of text within a larger paragraph, allow for styling or other CSS customizations of text. For this reason, it most often is used inside the 'p' element. Because the 'span' element has been around since the birth of HTML in the 1990's, this element has not changed in any of the browsers, and so is very reliable.
    2. CSS and the 'span' Element: The 'span' element's primary function is as a means to mark up or customize text. Changing spanned text with CSS is quite common. Avoid "inline" styles (as I am using) in spans and instead use CSS "class" attributes with a class selector in your style sheets when styling spanned text.
    <source> source

    Source

    also see <audio>, <picture>, and <video>

    The 'source' element is only used as a child element for a 'audio', 'picture', or 'video parent elements in HTML5. It defines alternative "sources" of media for all three tags. Shown below is an example of how to use the 'source' element with the 'picture' element. In this example, the 'source' tags provide alternative images for the 'img' element.

    <figure aria-labelledby="source1_caption" style="padding:.5rem;border:1px solid #bbb;background: #f0f0f0;width: auto;height: auto;display: inline-block;">
      <picture id="source1">
        <source srcset="image.webp" type="image/webp" />
        <source srcset="weather.gif" media="(min-width: 800px)" type="image/gif" />
        <img id="source1_img" style="width: auto;height: auto;max-width: 100%;" src="www.jpg" width="255" height="200" alt="image: World Wide Web" title="The World Wide Web" aria-label="Image of the World Wide Web" loading="lazy" onerror="this.onerror=null;" />
      </picture>
      <figcaption id="source1_caption" style="display:block;">
        "Which Image Appears?"
      </figcaption>
    </figure>


    image: World Wide Web
    "Which Image Appears?"

    * Note: My host provider does not support "WebP" images I found out, so if no "flowering tree" WebP image appears, it is not the code but my host provider. :(

    My Recommendations:
    1. The 'source' element is a new inline HTML5 media element that allows for the display of alternate media formats for the 'audio', 'picture', and 'video' elements. The 'source' element enables these media element to utilize more advanced media "choices" and media queries, as well as newer media formats.
    2. The 'source' Element: The 'source' element provides alternative formats for the 'audio', 'picture', and 'video' elements based on browser support, viewport size, or other criteria using four main attributes (see below). The browser first checks these 'source' elements one at a time. The browser examines each 'source' element's "srcset", "media", "size", and "type" attributes to select a media file that best matches those criteria. If the media "type" is supported, media dimensions or device resolutions match, and viewport dimension requirements are met, then the alternate "srcset" URL value is passed into the media element and used for display. If the criteria are not met then the default media tag's "src" URL or fallback text message is used.
      Multiple child 'source' elements can be added inside the media element to give newer HTML5 browsers the ability to choose from among numerous media types in deciding which one to show inside the main media element. In the case of 'picture', the 'img' element receives the 'source' element's "srcset" url and image file. In the case of 'audio' and 'video', the 'source' element itself holds the media file. Multiple 'source' element options can allow browsers the ability choose from a much richer array of media files based on support for different media "types" supported by a user's device, the ratio of CSS pixels to "device pixels" on the user's device, actual width of the media file, or the dimensions of the user's viewport using media queries. For this reason multiple source tags (usually 2-3) are often added under the main media element, with each one having a different media choice for the browser. The browser will then look for the first 'source' element from the list and check its 'media' "query" value, if any, then the 'type' attribute to see if the encoded image type is supported in the user's browser. When the media query value matches the current viewport width and the media type is supported, then the browser will use the 'srcset' path to the media file and display it inside the media element (audio, video, picture). Below are the four main <source> tag attributes supported and their role in controlling alternative media:
      • srcset - It simply contains a path to an alternate media file to use, plus a space then a place to add either the width of the alternate file in the case of images ("320w") or the "device pixel" dimensions ("3x") the file should support. The latter means that the media file may be saved at twice the standard PPI or resolutions of the other files, so would look better on say an iPhone or other high definition screen. Like the "srcset" attribute for the 'img' element in 'picture', this last value is the "expected width" of the alternate file (actual width, not styled) or its resolution, which tells the browser its expected value and helps the browser decide when to use the file based on the available width of the user's screen. Example: "srcset=image.webp 320w" means only use this image that has an actual width "320 pixels" if it can fit into the screen. The browser will decide this. Instead of using the supported image width, you can use the device pixel check, as in "2x". The "2x" value if used would says use this image in any screen device that has a higher "device pixel" value of 2 or higher. This means that the screens pixels are so tiny and can hold so many more than a desktop or laptop that you have created a high resolution file twice as dense in resolution (same width as other images, though) to support these types of devices. Most iPhone screens now support 400+ PPI resolutions screen with tiny pixels, which translates into a 2-3x increased pixel density for images. In those cases, say using the value "srcset=mynormalfile,jpg 1px, my2xfile.jpg 2x", you would prepare the first image with a normal PPI resolution for desktop browsers, then the same image for the second with the same width as the other, but with twice the resolution or PPI density of pixels for say iPhone HD displays. In the case of the 'picture' and its 'source' elements, they do not do anything other than support the 'img' tag with a new "src" URL and file. For 'audio' and 'video' media elements, the 'source' elements "srcset" sets the chosen file directly so are the supporting media elements.
      • type - The "type" attribute on the 'source' element contains a media type in a given format. Example: "image/jpg", "video/mpg4", etc. It is usually a common media or MIME type often sent to the browser from a web server as a hint along with the file. Each media type and its format or encoding may or may not be supported by modern browsers, however. Often, the 'source' element is only used to offer very advanced or newer media types, like "WebP" for images, etc. Know that there are still problems with support of these newer formats in browsers today. For example, the new "AVIF" image format is currently only supported by Chrome Webkit browsers, so would fail for every browser except the newest Chrome versions. "WebP" is another promising alternative "type", but is not supported in any Internet Explorer browsers and many others, like iPhone Safari, which did not support "WebP" until 2020! So, types like this are offered as alternatives only, until browsers in the coming decades support them. But you could add these types of media files using your "type" attribute in 'source' elements and thereby offer browsers reading your 'source' tags checks to see if they support them.
      • media - The new media "query" attribute allows you to set when any given media type should be considered by the browser, and if any additional scaling (or stretching) of the media from its default value should occur. It allows you to tell browsers when to scale these alternative files larger or smaller in dimensions relative to the viewport. Note that this only works in HTML5 browsers that support these types of media queries. There are two main media query formats to use: "Media Conditions", like "max-width" or "min-width", which relate to a devices viewport width or supporting characteristics, and "Media Intrinsic Width", which is the width the alternative file should resize or scale to (based on a devices screen or viewport, not the file's actual size or styled size). Example: "media=(max-width:800px) 50vw" in a 'source' element means to only use this media file alternative if the device's viewport or screen is less than 800 pixels. Second of all, it says, when triggered, scale the image to 50% of the viewport or "50vw". This might trigger a user on an iPhone or tablet to pull down a higher resolution file that's designed for smaller screens, but which is then scaled down an additional 50% to fit into the smaller space. Personally, I would not use the "scale" feature as its wasteful and redundant to scale or distort images and media files. You should have them simply use their original size and resize them and their resolution or PPI as needed to fit the viewport.
      • sizes - If you want to rescale or "stretch" you media file relative to the screen or viewport, you will want to use this attribute. I do not recommend it as "stretching" files is an old technique that's rarely if ever needed. But you could use this attribute to set a viewport value. An example of all this would be "100vw" which says, stretch a media file in width 100% of the viewport. Again, not a good idea. I would rarely use the "sizes" feature unless you are ok stretching and distorting your media files to fill the screen. Instead, use the "srcset" feature to decide what dimension or resolution of image to use.
    3. 'source' and CSS - NEVER style the 'source' element as its an empty element. Instead, style and resize the 'img' (inside 'picture), 'audio', or 'video' elements directly.
    4. ALWAYS use the XML-friendly version of 'source' with the " /" at the end as so: <source />. Do not let others convince you this is a "void" element or that this format is not compatible with HTML5, because it is.
    5. For more advanced examples using the new 'source' element, see my articles below: "The New Picture Element" and "How to Create a Cross-Browser Video in HTML5".
    <strike> strike, strikethrough

    Strike

    This is some <strike>struck through</strike> text.
    This is some struck through text.
    My Recommendations:
    1. The 'strike' element was used to represent text with a "strikethrough" line. The struck text could represent text that was deleted, changed, bad, misspelled, or replaced in a sentence. Because the context was lost and this was a purely visual element, it was removed from HTML5.
    2. Do not use the 'strike' element as it is deprecated now and was a member of old HTML4. Use the new <s> or "strikethrough" element which represents text whose meaning has changed, or the <del> and <ins> elements to indicate deleted text that has been replaced.
    <strong> strong

    Strong

    <p>This text has <strong>strong</strong> importance and should stand out.</p>

    This text has strong importance and should stand out.

    My Recommendations:
    1. The 'strong' element is a piece of inline text representing very important text that needs to be stressed. It is usually represented visually by bold or bolder text.
    2. Note: Use 'strong', not 'b' in your HTML. The text these two tags wrap around looks the same but does not carry the same meaning. In old HTML4, tags like 'b' were used to only format or style text, not stress its importance. And so the meaning of the text was lost using 'b'. Today in HTML5, importance has shifted to semantic tags that carry meaning as well as style, like 'strong', which tells search engines and readers this piece of content has weight and should stand out. When you have text in a paragraph that has strong importance use the 'strong' element rather than the 'b' element.
    3. What is the difference between 'em' and 'strong'? Use 'em' for a shift in tone or voice that represents emphasis. Use 'strong' for VERY important text that carries more weight than 'em'. 'strong' might also be seen as "stronger emphasis". (see 'em' for its sibling type)
    <style> style

    Style

    also see <link>


    A 'style' element is a non-visual (invisible) element that resides inside the <head> element of a typical web page. This element contains "embedded" style sheets that only apply to a single web page. Below I have listed a code example you can use to enhance your website with styles. Note: I do not recommend you use the 'style' element for styling websites, however, as it only applies to a single page and therefore wastes bandwidth delivering the same code over and over on every single page view. Instead, use the <link> or "external" CSS style sheet strategy which applies a single downloaded style sheet to an unlimited number of web pages at once. It is also fully cached for weeks or months in the web browser. Note: The "strange" CDATA code that wraps around the CSS in 'style'. This is "extra" code designed to hide CSS styles in the tags from XHTML/XML parsers and older non-supporting CSS browsers (see my recommendations below for a full explanation). This code, however, works fine in all HTML5 browsers going forward.


    
    <style type="text/css">
        <!--/*--><![CDATA[/*><!--*/
    
        p {
    	    display: block;
    	    clear: none;
    	    padding: 0;
    	    margin: 1em 0em;
        }
    
        /*]]>*/-->
    </style>
    
    
    My Recommendations:
    1. The 'style' element appears in the head of a web page and is used to apply "embedded" CSS styles within a single web page. An alternative to the 'style' element is the 'link' element or "external" style sheet system that can download larger style sheets pages for all web pages. The 'style' element has been around since the 1990's and has changed very little in the past 20 years. 'style' elements really began when CSS (Cascading Style Sheets) was adopted by the first web browsers. The first CSS-supporting browsers were Internet Explorer 3 in 1996 and Netscape 4 in 1997. So the 'style' element was supported in web browsers around that time. Unless you truly need "embedded" styles that only affect a single page in your website, I recommend you use the "external" 'link' version, instead.
    2. Cascading Style Sheets (CSS) - I recommend you avoid 'style' elements with "embedded" CSS style sheets. Use of "external" CSS files using the 'link' element is superior to 'style' when managing the design and layout of your website. Why? External CSS is far superior to "embedded" (<style>) and "inline" element styles (<span style="color:blue;">my text</span>) simply because external styles downloaded to the browser are cached for every page in your website and affect all web pages, not just one. Often inexperienced developers use inline or embedded styles and forget about externally linked CSS sheets. They assume they are slower, inferior, antiquated, or difficult to manage when the opposite is true. They then lose out on valuable, reliable, proven technology that is far superior to anything built today. Links to multiple external CSS files also download in parallel to each other in a very quick fashion in most browsers, so there are few delays. Browsers have been doing this for over 20 years. Unlike large libraries of scripts, linked CSS often has a very tiny footprint and so has very little affect on page rendering or paint delays, simply because modern browsers manage these downloads very effectively and have been for decades. Once your CSS files are downloaded, they are cached and indexed in browser folders, allowing future page views of your site to be rendered and painted in the browser very quickly. Note that these "embedded" styles are only really useful for "offline" styling of pages. The only real benefit to using these "embedded" style blocks was for caching of offline styles for devices like old handhelds, which reallu benefited from using cached pages with associated styles attached to them. Today, that is rarely needed.
    3. The "type" and "media" Attributes: When using CSS in 'style' elements, the browser will recognize the 'style' element as used for CSS and default to a "type" of "text/css". But it is a good idea to go ahead and explicitly set its attribute as so: "type=text/css". Note: Some HTML5 validation tools online may not validate with this "type" setting as many recommend you remove the attribute altogether, for some strange reason. The assumption may be 'style' elements are exclusive to CSS, now, so the attribute isn't necessary. But older browsers may not assume that is true. So, I recommend you ignore the validators in this situation and keep the attribute in place, as described above, for wider cross-browser support.
      The "media" attribute is widely used to determine the type of device the styles should be applied to, much like the 'link' element (see the <link> element recommendations for more details). If you leave off, say "media=screen", the styles will generally apply to "media=screen" by default in many older browsers using the HTML 4.1 spec. Note that this is the opposite for 'link' elements, which default to "media=all" today in HTML5. As with 'link', never use "all" explicitly due to lack of browsers support, but use "screen", "print", and specific types. For now, I recommend you do not use a media type setting on the 'style' element based on HTML5 recommendations. Instead, just leave it off and assume your styles affect all devices.
    4. The "style" Element with CDATA Comments: If you must use these the 'style' element for delivering CSS, I have added an XML-friendly, "no CSS support" friendly "CDATA" version to the "embedded" code example below, which is superior to any embedded 'style' coding block you will find online. It supports your page scripts in XHTML 1.1, XHTML5, XML parsers, browsers with no CSS support, and more modern browsers with full support for CSS. Use this version below if you have to use "embedded" style sheets. Note: You typically add style blocks in the <head> of your web page. This forces the browser to parse and load the styles first into memory before downloading HTML content and should only contain styles that need to be fully preloaded first and which directly affect or control HTML right after before it is rendered and painted. This CDATA code below inside the 'style' element supports HTML5 parsing, XHTML, XHTML5, and very old browsers that do not support the style tag or even CSS. In all cases, using the code below will not blow up in any of the browsers or allow your styles to get rendered accidentally as markup or even text:
      
      <style type="text/css">
          <!--/*--><![CDATA[/*><!--*/
      
          /* put your styles here */
      
          /*]]>*/-->
      </style>
      
      
      Some History on this Strange Code Above: Going back to the 1990's, you were allowed to place these HTML comments "<!--" and "-->" inside the 'script' element to hide CSS and style code text from non-CSS supporting browsers, which would recognize the HTML comments and hide the style text. Supporting CSS browsers back then would ignore them and execute the styles. Why? These 'script' and 'style' elements read anything inside the tags as character data or CDATA, which means no HTML is recognized inside the tags. HTML comments are still HTML so ignored by them. So, most browsers that supported CSS back then ignored these HTML comments, as anything in these elements was considered CDATA, allowing CSS to execute safely for them. By the way, these now defunct older non-CSS supporting browsers included IE 1-2 and Netscape 1-3. For them, the HTML comments meant the style code was safely commented out. Added to this problem has been XHTML and XML parsers, which do not know the code between these tags is just CDATA. Such parsers would blow up if they parsed CSS that contained any XML entities or markers. Many of these XML-friendly parsers did not need CSS at all. To fix the code for them, I had to expand the comments above to force those parsers to ignore the CSS code, as well. And so that is how I came to develop the solution above. In the HTML5 browser world today, nearly all browsers known now support CSS. But adding the comments and safety code above allows you to still support a range of very old non-CSS supporting browsers, XHTML, and XML parsers combined, should you need to share your code or web pages with any of these parsers or browsers. They will not blow up now when encountering your CSS code using the comments above. The code above is completely safe to use now in newer, more modern HTML5 browsers. But when used, it will make sure your JavaScript blocks are ignored in XML parsers and non-CSS supporting older browsers alike.
    5. Cascade Order and the 'style' Element: Does the order of "embedded" (<style>) and "external" (<link>) style sheets in the <head> of your web page affect the cascade order of similar style rules on elements? It is an important question. It turns out it DOES in modern HTML5 browsers, but did NOT in many older browsers (pre-2010)! Why? Older browsers used to have a very good rule the W3C used to require they follow. It basically said that no matter where external <link> styles appear in the <head> of your web page, "embedded" or <style> CSS was always last in the order set inside the browsers cascade memory, not in your web page. In other words, embedded styles always cascaded over linked styles using the same selectors, even if you placed external linked CSS AFTER embedded CSS in your web pages. Linked external CSS elements always came before embedded CSS in the memory of the browser, no matter what physical order your code used. This is NOT the case in newer HTML5 browsers, I found out. This might be a subtle issue to you, but if you stack lots of "element" style rules in your external and internal style sections of your web page 'head' element, rules that use the exact same selectors, if you do not order your linked external CSS elements correctly then you might see some cascade over others, unexpectedly in newer HTML5 browsers! Order of styles now matters in your pages, where in the past it did not. The reason newer HTML5 browsers now strictly honor specific style sheet "source order" in the "head" of your page, regardless of linked vs embedded types, is because HTML5 has gotten lazier and looser in defining such things. In other words, be careful in the order you place linked and embedded styles, as they do matter today. Embedded sheets no longer have higher source order over linked sheets, as they did in the past. To match old and new browsers so they both work the same using external and embedded sheets, ALWAYS add your linked sheets (<link>) above your embedded ones (<style>) in the head of your page.
      Unfortunately, newer browsers today using HTML5 decided to ignore W3C and Web Standards, so now order matters. This is counter-intuitive, so I recommend you follow the rule above and you will have no issues with CSS cascade order going forward in any of the browsers you support.
    6. Avoid All Internet Explorer "Conditional Statements": In the long and troubled history of Internet Explorer and its support/non-support of HTML and CSS, many developers over the past few decades solved those cross-browser issues by hiding specific style sheets from all browsers but IE using special "Conditional Statements". In the past, many authors tried to address the numerous CSS bugs in Internet Explorer by using special code that hid certain linked style sheets from other browsers, but which were only specific to a version of Internet Explorer. Without going into the long history of this type of trick, I can say today this technique no longer works for newer IE browsers (version 10, 11, or the new Edge browsers). So, it is time to retire them completely. An example of such code is shown below so you know to avoid this code trick when trying to design CSS for older IE versions. This code below hides two linked CSS files that have special CSS hidden from all browsers but two older, specific Internet Explorer browser versions):

      <!--[if IE 8 ]>
      <link media="screen" rel="stylesheet" type="text/css" href="/styles/ie8only.css" />
      <![endif]-->

      <!--[if IE 9 ]>
      <link media="screen" rel="stylesheet" type="text/css" href="/styles/ie9only.css" />
      <![endif]-->

      * DO NOT USE THIS CODE! Because IE is nearly dead, plus IE 10-11 no longer supports these conditional statements. I do not recommend you use these IE coding tricks going forward, but instead cope with older IE versions using other techniques (I use a new CSS framework I built which uses "@import" rules IE 1-7 cannot understand and which hides my CSS style sheets from all IE 1-7 versions, giving these older browsers plain white HTML pages). Avoiding these custom page-by-page IE hacks means one less customization you now have to worry about in your web pages when dealing with the complexity of styling for older browsers using 'link' elements. (The ONE EXCEPTION to this rule is in my "Best Practices" section below called "How to Force New HTML5 Elements to Work in Old Browsers" where I encourage the use of IE Conditional Comments for forcefully adding missing HTML5 elements to non-HTML5 IE versions 1-8 browsers using a script.)
    7. The Myth of CSS @Import Render Blocking: I recommend you also use the 'style' element to directly import in external CSS files if you like. To do that you can use the "@import" CSS declaration. Because this tutorial only covers HTML I cannot go into style sheets. But it is an option I encourage you to use. And no, @import will not "render bock". Let's talk about that concept now.
      The CSS rule "@Import" is often used to make additional calls to external CSS inside embedded CSS files. A 'style' with @import calls to other external files is a very common practice and fully supported by all CSS recommendations today and 20 years ago. But sadly, some developers have started to demonize the practice unfairly, as a technique that causes "blocking" delays of other linked CSS style sheets. The fact is, this is completely false.
      When using the CSS rule "@import", the idea is to break up reusable CSS into files that can be delivered in pieces as needed. Often these CSS styles are placed into a single 'style' tag so all the import calls are managed in one place. Some claim these calls then add additional download time as they are "render-blockers", meaning they cause either the other "@import" calls to wait, or other 'link' CSS file downloads to be delayed. Others claim the reason for this is that import calls no longer download in parallel with each other or the other synchronous sheets, like linked sheets are designed to do. It turns out all that is completely false!
      In fact, multiple imported style sheets inside a linked style sheet all download in parallel relative to each other, with no blocking issues ever, and use shared connections for added speed in most browsers. The "@import" style rule only adds one extra call when combined with CSS styles inside the same linked parent sheet as the importing of other sheets must make one call in addition to the parent sheet call that holds them. Any delay here is on that one extra connection, not the import call. Thats it! The parent sheet that holds imports starts the new required connection then downloads all internal import sheets together as long as there is no other delays in receiving its own CSS. My sheets never have any additional CSS, only more imports. Only old Internet Explorer browsers had some inability to download imported files in parallel with other linked sheets. The main way to reduce render blocking is NOT avoiding use of "@import" CSS rules, but by using fewer external files and smaller files, like smaller images and less JavaScript. Most modern browsers have a default connection limit of 6 connections anyway, as I have mentioned, so parallel downloads of numerous imported CSS files does not speed up CSS if scripts or images are being downloaded in parallel via those few connections. "@import" isn't affecting parallel downloads of files as long as you avoid combining them with other raw CSS in the same file. I never do this, so using @import is a viable CSS strategy to use in connecting to multiple CSS files in your web page and to hide cutting-edge CSS3 from older browsers. The "myth" of these "blocking" claims has been exposed and should now be ignored. It is 100% safe to use @import in CSS linked files to download more CSS you might need without any worry of page render delays or blocking of other linked CSS files.
    8. Browser Support: 'style' element has wide support in nearly all browsers, old and new. So, is fully supported.
    <sub>, <sup> subscript, superscript

    Subscript and Superscript

    <p>Here is a chemical formula: H<sub>2</sub>O. <br />Here is a famous equation: e=mc<sup>2</sup>.</p>

    Here is a chemical formula: H2O.
    Here is a famous equation: e=mc2.

    My Recommendations:
    1. The 'sub' and 'sup' elements represent inline subscript or superscript text that must appear half a character below or above existing text. This text is often formatted in a smaller font-size setting for typographical reasons. Both 'sub' and 'sup' have been around since early HTML standards and still used today. Use these types of text for footnotes, mathematical expressions, scientific formulas, date notation, references, and more.
    <summary> summary

    Summary

    also see <details>

    The "summary" text is show below. It is the top gray "click-able" section in the 'details' element below.


    <details id="summaryexample1">
      <summary style="background-color: #ccccccff;box-shadow: 2px 2px 3px #aaa;">&copy; Copyright 2022</summary>
      <div style="margin: 0;padding: .2em 1em;background-color: #efefef;box-shadow: 2px 2px 3px #aaa;">
        <p>Owned by Company ABC. All Rights Reserved.</p>
        <p>All content and graphics on this web site are the property of Company ABC.</p>
      </div>
    </details>
    © Copyright 2022

    Owned by Company ABC. All Rights Reserved.

    All content and graphics on this web site are the property of Company ABC.


    My Recommendations:
    1. The 'summary' element is new interactive element in HTML5 which belongs to the 'detail' interactive element. It represents a title, caption, or legend for additional content contained within a "click-able" disclosure box. The text summary shows additional hidden text details that the user can see by clicking the summary text. This is usually created by the browser as a piece of title text with a dropdown toggle arrow that reveals hidden content. The 'details' element is typically used as a JavaScript-free toggle widget to disclose additional information if the user chooses to view it.
    2. CSS and the 'summary' Element: In general, avoid styling this element or risk "erasing" the browser's built-in arrow and toggle interactive feature. Some like to add block-level elements inside the 'summary' tags. But this gets pushed down below the arrow to the next line and destroys the layout feature. Changing 'summary' to then be a "display:inline" element pulls the block element back up, but then text below 'summary' in 'details' pulls up to the right of the element in many browsers (like IE). Because IE and Trident Edge still do not support this element correctly (see the 'details element), changing the CSS on it start confusing browsers and dismantling its native interactivity. You then get into a rabbit hole with elaborate CSS hacks. Developers then start adding elaborate JavaScript "polyfills" to compensate, and before you now it you have turned a simple, elegant HTML5 feature into a monstrosity! I recommend you stick with only changing colors and text styles on the 'summary' element, if you choose to style it, and avoid these circus tricks.
    3. See the <details> element for more detailed information about this element and all its features and properties.
    <svg> scalable vector graphics

    Scalable Vector Graphics

    also see <canvas>


    A Simple SVG Example

    Below, is a simple example of how to use SVG in HTML5 to create an image dynamically in the browser. If your browser supports HTML5, then it will likely see the words "SVG" drawn in the middle. There are many more powerful examples of SVG art online.

    
    <svg height="120" width="120" xmlns="http://www.w3.org/2000/svg" title="My SVG Image" aria-label="SVG Image">
        <text x="0" y="0" style="font-size:3em;fill:green;">
            <tspan x="32" y="55">SVG</tspan>
        </text>
      Sorry, your browser does not support Scalable Vector Graphics technology (SVG).  
    </svg>
    
    SVG Sorry, your browser does not support Scalable Vector Graphics technology (SVG).

    SVG for Cross-Browser Support

    If you plan to use "external" SVG XML files (which I recommend you do), you have the power to deliver alternative SVG images to regular HTML5 browsers with added bitmap versions or alternative images of your SVG in pixel formats for older browsers that do not support HTML5. Below is an example of a "fallback" code you can copy and modify as needed when supporting older browsers that do not support SVG. Modern HTML5 browsers will read the 'object', 'embed' or "xlink" image source, while older browsers will either see a pixel JPEG image or text.

    
    <object 
        id="mysvgobject1" 
        name="mysvgobject1" 
        data="mysvgfile.svg" 
        type="image/svg+xml" 
        title="My SVG Image" 
        aria-label="SVG Image" 
        title="My SVG Image" aria-label="SVG Image">
            <embed 
                    id="mysvgembed1" 
                    src="mysvgfile.svg" 
                    type="image/svg+xml" 
                    title="My SVG Image" 
                    aria-label="SVG Image" 
                    title="My SVG Image" aria-label="SVG Image">
                <img xlink:href="mysvgfile.svg" src="myfallback.jpg" title="My SVG Image" aria-label="SVG Image"> />
                <noembed>
                    Sorry, your browser does not support Scalable Vector Graphics technology (SVG).  
                </noembed>
            </embed>
    </object>
    
    My Recommendations:
    1. The 'svg' element stands for "Scalable Vector Graphics" and is a new graphics display element in HTML5 which allows rendering of visual design in the browser using XML. This new graphics coding ability in HTML5 browsers supports fast rendering of linear or "vector-based" designs using points, lines, and effects which are scalable and transferable across various systems using simple XML code rather than JavaScript libraries, static pixelated images, or image processing software.
    2. Features of the new 'svg' Element: The promise in HTML5 of using faster, coded forms of graphics and images in web browsers arrives with the new 'svg' element! We have been using this type of image format for decades and decades offline, in applications like Adobe Illustrator and Adobe Acrobat with their ".eps" and ".pdf" postscript formats. The power to design text using vectors is the basis for font technology, as well. Most of this technology came about in the 1980's, and has been in use for laser printing and other screen rendering technologies for many decades. But the web browser has not had this graphics feature until now in HTML5.
      Unlike its HTML5 cousin, <canvas>, the 'svg' ("Scalable Vector Graphics" or SVG) element is a fully-featured linear 2-D design feature that gives you complete control over images using simple XML code. It is fully compatible with HTML5 and markup, as a result. Like 'canvas', the browser is used in creating the image and visuals. But 'canvas' relies on a "one time" rasterized image call using the graphic libraries in the device's operating system. As such, it will not re-render the image as the browsers viewport changes. 'svg' elements, however, will redraw images, as they rely on the browser's rendering abilities to draw vector shapes in the viewport. This gives 'svg' elements a very fast and powerful edge over all other pixel-based, static, or rasterized image systems online. However, photographic imagery is not suitable for 'scalable vector images. So 'svg' is generally not used for high definition imagery or manipulating pixels in photos. Understand it has its place in solving some image-rendering issues, but not all.
      Below is a list of the main features of SVG elements, and things to remember:
      • SVG is XML - You may love or hate XML, but it is still a powerful way to structure data. In SVG's case, that is exactly what it does and why it works so well, as unlike JSON or other data document formats, XML has full support for nesting, tag attributes, and custom tag design.
      • The main 'svg' parent element is a "window" - The top-level 'svg' element controls available boundaries to your inside images, much like a "window". So, be sure to add dimensions to it. All its child elements and graphics will fit inside it, not outside it. By default, elements that attempt to overflow this parent box are "cut off", or rather designed to not overflow this boundary box defined by the 'svg' parent. But if you get used to the idea of 'svg' as a "boundary" or "visual "box" and add dimensions to it, it will start to make sense how your designs should fit inside it. You can of course assign widths and heights on this box using CSS styles. I encourage you to do so.
      • Use an external XML 'svg' file - Instead of typing SVG code directly in your page, some developers download an XML SVG file into an <object>, <embed>, <use>, or <image> tag. The advantage to this technique is you manage all your complex SVG code externally and in modules you can add as needed using a set of small XML files. It also allows you to use cross-browser support for non-supporting SVG browsers, with an alternative pixel-based image in the 'img' tag for browsers that do not support the SVG code (see my example above).
      • Cross-browser support for SVG - If you want to support older browsers that do not know SVG or HTML5, the best solution similar to the same one I supply for <video> elements in my article, "How to Create a Cross-Browser Video in HTML5". I have created a custom version of this in the code examples above. You must use an external SVG file for this to work properly. Basically, using the 'object', 'embed', and 'img' tags, browsers that fully support SVG will display the external SVG file downloaded into 'object'. Some browsers use the 'embed' element to run an SVG application in the browser. Finally, those browsers that need to download the SVG file as an image can use the 'img' tag. All legacy browsers would download a plain image you supply that is a screenshot of the SVG file. This would give you nearly 100% fallback support of your SVG image using alternative pixel-based images in older browsers.

      Addendum: Using Scalable Vector Graphics (SVG) is a "big" topic with many features - too many to list here! So, I will not go into all the various forms of code available here. The code example I provide above will help you get started. There are also large tutorials online. Just know that 'svg' elements and their children allow you a must faster and wider ability to display imagery online than ever before. Though a wide range of older browsers will fail to see your 'svg' elements, I still recommend its use, as long as you offer some alternative imagery for those browsers that will not support your images. The same approach applies to screen readers who will not understand your visual images. "title" attribute tooltips and alternative ARIA labeling will help. I have added a few of those to the example above.
    3. Browser Support for the 'svg' Element: With Scalable Vector Graphic elements now for the web, we have the promise of faster image rendering using simple XML code. The problem, however, is the same one we have always had with new technology for the Web: Lack of cross-browser support. The good news is most of the major HTML5 browsers have ramped up to support more and more of the recommended SVG features. This includes Internet Explorer 9-11, which usually has good support, though some features like filters, Gaussian blurs, etc. will not be supported. That means, most of your users online will see 'svg' graphics ok. But, many may see partial or no implementation of your carefully designed code. Because most older HTML5 browsers have good SVG support, I do recommend use of this element, as long as you provide a full set of fallback pixel-based images, alert messages, and text description alternatives to assist various user agents understand what your SVG designs were meant to convey.
    4. Free SVG Images and Software: There are free SVG libraries of images and even software online to help you build powerful SVG XML files and images for your website. I encourage you to use those!
    <table>,
    <thead>,
    <tbody>,
    <tfoot>,
    <tr>,
    <th>,
    <td>
    table

    Table

    also see <col> and <colgroup>

    Included in this section is <table> and all its child elements: <thead>, <tbody>, <tfoot>, <tr>, <th>, <td>


    Plain Table Example

    Below, I am showing an example of a basic table template you can use in all your projects. This one has all the traditional "grouping" table elements, including 'thead' at the top and 'tfoot' at the bottom. 'thead' and 'tfoot' not only support the 'tbody' data in the page, but are added at the top and bottom of printed pages in many browsers. The 'tbody' contains all of the main content cells. Included are two examples of spanning, a process which allows cells to stretch across multiple rows and columns using the "rowspan" and "colspan" attributes. The new ARIA attributes of "aria-colcount=4" and "aria-rowcount=6" tell screen readers the expected count of columns and rows in your table, if you know those values. I've also added the "scope" attribute in the header elements to help screen readers understand labels as they relate to groups of columns. I have added an optional "headers" attribute to cells to help screen readers associate them with headers using their "id" values. If you use "scope", this is not needed. But I have added it to show how they are used. I have also added the optional 'colgroup' and col' elements to create the blue color. These two elements are generally non-traditional elements used to control background or other design features in tables. But I do not recommend you use 'colgroup' or 'col' elements in tables at this time. Try and use CSS "class" attributes with styles instead to control the look-and-feel of your table's columns and rows.

    
    <table id="tableexample1" title="Table Example With Column Groups" 
        aria-label="Table Example 1" aria-colcount="4" aria-rowcount="6">
    <caption>Table Example 1 : Column Groups</caption>
    <colgroup>
        <col style="background-color:white;"/>
        <col span="2" style="background-color:lightblue;" />
    </colgroup>
    <thead>
        <tr>
            <th id="header1" scope="col">header 1</th>
            <th id="header2" scope="colgroup" colspan="2">header 2</th>
            <th id="header3" scope="col">header 4</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td headers="header1" >body 1</td>
            <td headers="header2">body 2</td>
            <td headers="header2">body 3</td>
            <td headers="header3">body 4</td>
        </tr>
        <tr>
            <td headers="header1">body 1</td>
            <td headers="header2" colspan="2">"colspan" applied</td>
            <td headers="header3">body 4</td>
        </tr>
        <tr>
            <td headers="header1" rowspan="2">"rowspan" applied</td>
            <td headers="header2">body 2</td>
            <td headers="header2">body 3</td>
            <td headers="header3">body 4</td>
        </tr>
        <tr>
            <td headers="header1">body 2</td>
            <td headers="header2">body 3</td>
            <td headers="header3">body 4</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td headers="header1">footer 1</td>
            <td headers="header2">footer 2</td>
            <td headers="header2">footer 3</td>
            <td headers="header3">footer 4</td>
        </tr>
    </tfoot>
    </table>
    
    Table Example 1 : Column Groups
    header 1 header 2 header 4
    body 1 body 2 body 3 body 4
    body 1 "colspan" applied body 4
    "rowspan" applied body 2 body 3 body 4
    body 2 body 3 body 4
    footer 1 footer 2 footer 3 footer 4

    Nested Table Example

    Below, I am showing an example of a table with an added nested table so you can see how that is done.

    
    <table id="tableexample2" title="Table Example Containing a Nested Table" 
        aria-label="Table Example 2"  aria-colcount="3" aria-rowcount="3">
        <caption>Table Example 2 : Nested Tables</caption>
        <thead>
            <tr>
                <th scope="col">header 1</th>
                <th scope="col">header 2</th>
                <th scope="col">header 3</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>body 1</td>
                <td>
                    body 2
                    <table id="tablenested1">
                        <tr>
                            <td>nested 1</td>
                            <td>nested 2</td>
                            <td>nested 3</td>
                        </tr>
                    </table>
                </td>
                <td>body 3</td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <td>footer 1</td>
                <td>footer 2</td>
                <td>footer 3</td>
            </tr>
        </tfoot>
    </table>
    
    Table Example 2 : Nested Tables
    header 1 header 2 header 3
    body 1 body 2
    nested 1 nested 2 nested 3
    body 3
    footer 1 footer 2 footer 3

    Multi-Header Table Example

    This example shows how you can have "headers" ('th') in columns, as well as rows. This example contains both types to show you how you can create tables with horizontal and vertical titles. Notice I changed the "scope" in the 'tbody' header cells to "row" to tell screen readers these left-hand headers represent the row of cells only. The 'tfoot' group was removed at the bottom of the table, as it is not needed.

    
    <table id="tableexample3" title="Table Example Containing Multiple Headers" 
        aria-label="Table Example 3" aria-colcount="4" aria-rowcount="4">
        <caption>Table Example 3 : Multiple Headers</caption>
        <thead>
            <tr>
                <th scope="col"> </th>
                <th scope="col">top header 1</th>
                <th scope="col">top header 2</th>
                <th scope="col">top header 3</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th scope="row">left header 1</th>
                <td>cell 1</td>
                <td>cell 2</td>
                <td>cell 3</td>
            </tr>
            <tr>
                <th scope="row">left header 2</th>
                <td>cell 1</td>
                <td>cell 2</td>
                <td>cell 3</td>
            </tr>
            <tr>
                <th scope="row">left header 2</th>
                <td>cell 1</td>
                <td>cell 2</td>
                <td>cell 3</td>
            </tr>
        </tbody>
    </table>
    
    Table Example 3 : Multiple Headers
      top header 1 top header 2 top header 3
    left header 1 cell 1 cell 2 cell 3
    left header 2 cell 1 cell 2 cell 3
    left header 2 cell 1 cell 2 cell 3
    My Recommendations:
    1. The 'table' element represents a set of tabular data defined by rows and columns. The 'table' element is the top container or box. It holds numerous child HTML elements that define the table structure (see below). The origin of the 'table' element goes back to the birth of HTML in the 1990's and has been a stable element since its creation. It is still part of the HTML recommendations and has changed very little in 20+ years. The table remains a reliable element for displaying tabular grids of data and information in web pages today.
    2. The History of the 'table' Element: Little has changed in the design and layout of the table. The first proposal for HTML tables began in 1993 and continued until its standardized HTML 3.2 integration in 1997. In later years, the newer HTML4 recommendations (1998) added additional features, like interior elements for 'thead', 'tbody', and 'tfoot' to further define sections of the table grid, semantically.
      Most web developers have used the 'table' element in fulfilling its original purpose of displaying grids of tabular data. But some developers starting in 2001, out of frustration with trying to build "flexible" layout designs in stubborn Internet Explorer 5 and 6, starting using tables to build page layouts and structures in HTML. At first, it seemed that tables in HTML provided the perfect flexible architecture for laying out flexible grids. These worked well across all browsers instantly and solved the issues around cross-browser flexible layouts. The problem was the table was not meant to do web page layouts. This defied the true purpose of the 'table' element. And so began what I call the "Table Wars". In 2000, this battle raged in parallel with the browser wars between Internet Explorer and Netscape, and between those that loved and hated JavaScript. Back then we used 'div' quite successfully for layout with elaborate negative margins and positioning tricks to build these flexible layouts in troublesome browsers like IE6. After some work, these worked great! We never ever needed to even consider tables. But we suffered from rushed developers back then that refused to take the time to learn these CSS tricks or IE's "quirksmode" issues, which we had elegantly resolved for them.
      By 2001, many professional web developers began noticing this trend among some using tables for layouts and quickly caught the problem and explained that semantically using 'table' elements was confusing to both developers and search engines. They later showed that such use was forbidden. Web layout did not represent tabular data. This led to a brief battle over HTML structure vs semantics vs design in web logs online, which birthed the "Web Standards" movement in 2003. This universal concept for acceptable HTML use in web pages helped the W3C to refine the semantic purpose and use of all HTML tags and pushed for more standardization of each element's use. Most young developers today think this discussion happened after 2010, but Web Standards started a decade before and was resolved many years prior to even the first HTML5-supporting browsers. The first Mozilla browsers in 2001 were already very much compliant with HTML4.1 and the correct use of tables was already recommended. Today's discussion about tables and standards in 2022 is thus just a second "reworking" of what we already figured out in 2003. The people learning today about tables represents a generation not bothering to learn from the past, and so reinventing the wheel by re-investigating the debate 20 years later. Today in 2022, it is not "illegal" to use the 'table' element to layout a grid for your web page. It is just not recommended and is poor HTML page design. Besides, HTML5 finally has its own layout elements now.
      In summary, the history of the 'table' element ends with the fact almost no one now uses tables for layouts, though some on "medium.com" still pretend its a new issue. There is nothing new online when it comes to HTML and tables. Sadly, convincing people that tables used for layouts was bad took HTML5 and CSS3 to fix it by adding new elements and styles. But why did it take 20+ years to convince developers to stop using tables in the first place?
    3. The 'table' Child Elements: Rather than list each of these child elements in their own section in this HTML5 tutorial, I felt it was much easier to combine them here under 'table' and show how each are used (see my code examples above). Below is a comprehensive list of all the possible child elements of 'table' in HTML5 and my recommendations for how to use them. Included are any special attributes needed, or ones now deprecated and not recommended. Always review my code samples above for full examples of coding best practices when building tables in HTML:

      Table Elements

      • <table> - The 'table' element is the root element for all the elements below and creates the "box" or grid that holds rows and columns of data. Note that you can nest tables inside each other as well as grids for more complex data structures. Below are the recommended attributes for 'table'.

        Recommended Attributes

        • 'id' - Always give tables a unique 'id' value so scripts can quickly identify it in the DOM for script manipulation.
        • 'title' - Always give tables tooltips so on rollover there is some basic description of the table in addition to its caption or label.
        • ARIA - In general, avoid "role=table" here as tables are self-describing, have the 'caption' element for descriptions, support 'title' attributes, and the data represents most of the meaning, anyway. You can add "aria-label" to add a simpler name to your table. Two attributes you can add, if you know these values, are "aria-colcount" and "aria-rowcount", which just tells screen readers the total counts of data expected.
        • 'class' (CSS) - See my sample CSS below to get started using a clean, cross-browser design for all your tables.
        • 'summary', 'align', 'cellspacing', 'cellpadding', 'border', 'bgcolor'. 'background', 'bordercolor', 'attributes', 'height', 'width', 'rules', 'nowrap', 'frame' - DO NOT USE THESE! These attributes on 'table' elements were used years ago to control the design of tables but are deprecated in HTML5, so avoid them.

      • <thead> - The 'thead' element is one of the newer semantic wrappers and defines the section of rows and columns that define a "header" for all body and footer rows and columns. This element had poor support in early versions of Internet Explorer and Netscape (pre-2000) so was avoided. Later versions fully supported them. Typically, headers in this group represent bold text titles in a top horizontal row. But these can be moved to the left or right in a table to represent the first or last column in multiple rows. Note: If you leave these "wrapper" elements out of tables most browsers will insert them anyway around your rows and columns in the Document Object Model. These grouped elements usually have no design or formatting by default. Note that this attribute has "display:table-header-group" assigned. When printing a large table that spans multiple pages, this element can enable the table header and footer to be printed at the top and bottom of each page. By default, many modern browsers will print the 'thead' and 'tfoot' content at the top and bottom of every printed page.
      • <tbody> - The 'tbody' element is one of the newer semantic wrappers and defines the section of rows and columns that define the main "body" of data. This element had poor support in early versions of Internet Explorer and Netscape (pre-2000) so was avoided. Later versions fully supported them. Note: If you leave these "wrapper" elements out of tables most browsers will insert them anyway around your rows and columns in the Document Object Model. These grouped elements usually have no design or formatting by default. Note that this attribute has "display:table-body-group" assigned. Browsers or CSS can use this element to enable scrolling of the table body independently of the header and footer when you have large sets of table data.
      • <tfoot> - The 'tfoot' element is one of the newer semantic wrappers and defines the section of rows and columns that define the lower "footer" area of the table. This element had poor support in early versions of Internet Explorer and Netscape (pre-2000) so was avoided. Later versions fully supported them. Footer supplemental information that supports the main data in 'tbody' is usually added here. Note: If you leave these "wrapper" elements out of tables most browsers will insert them anyway around your rows and columns in the Document Object Model. These grouped elements usually have no design or formatting by default. Note that this attribute has "display:table-footer-group" assigned. When printing a large table that spans multiple pages, this element can enable the table header and footer to be printed at the top and bottom of each page. By default, many modern browsers will print the 'thead' and 'tfoot' content at the top and bottom of every printed page.
      • <tr> - This is the original HTML 3.2 table row element and holds multiple columns inside it. It can be contained inside any of the three group table elements above. Table rows usually have no design, padding, or formatting by default. But see my CSS code below.

        Recommended Attributes

        • ARIA - In general, avoid the ARIA "role" and "aria-label" attributes here as this element is self-describing. If some rows appear or disappear from your table due to settings, and you want to help screen readers identify the index of a row from the total, you can add "aria-rowindex={row number}".
        • 'class' (CSS) - See my sample CSS below to get started using a clean, cross-browser design for all your tables.
        • 'align', 'valign', 'bgcolor' - DO NOT USE THESE! These attributes on 'table' elements were used years ago to control the design of tables but are deprecated in HTML5, so avoid them.

      • <th> - This is the original HTML 3.2 table header element and holds a single header or title for a single column inside it. This can include text, images, lists, media, grids, tables, or other items. It can be contained inside any of the three group table elements above. Text is usually bold and centered by default to highlight the "column title" aspects of headers.

        Recommended Attributes

        • 'id' - You are only required to assign a unique 'id' attribute to an 'hd' element if you plan to use the "headers" attribute in 'td' cells. The "headers" attribute would then point to your 'id' value.
        • 'colspan' - This attribute allows you to set a single table cell to span multiple columns in a table. The number represents the number of columns the cell should fill.
        • 'rowspan' - This attribute allows you to set a single table cell to span multiple rows in a table. The number represents the number of rows the cell should fill.
        • 'scope' - The scope attribute specifies whether a header cell is a header for a column, a row, a group of columns, or a group of rows. Note: The scope attribute has no visual effect in ordinary web browsers, and is mainly used by screen readers.
        • ARIA - In general, avoid the ARIA "role" and "aria-label" attributes here as this element is self-describing. If some columns appear or disappear from your table due to settings, and you want to help screen readers identify the index of a column from the total, you can add "aria-colindex={column number}".
        • 'class' (CSS) - See my sample CSS below to get started using a clean, cross-browser design for all your tables.
        • 'align', 'valign', 'bgcolor' - DO NOT USE THESE! These attributes on 'table' elements were used years ago to control the design of tables but are deprecated in HTML5, so avoid them.

      • <td> - This is the original HTML 3.2 table data or column element and holds a single piece of data for a single column. This can include text, images, lists, media, grids, tables, or other items. It is usually contained inside 'tbody' and 'tfoot' group elements, is left aligned, vertically aligned to the middle, not bold, and not padded by default in tables.

        Recommended Attributes

        • 'colspan' - This attribute allows you to set a single table cell to span multiple columns in a table. The number represents the number of columns the cell should fill.
        • 'rowspan' - This attribute allows you to set a single table cell to span multiple rows in a table. The number represents the number of rows the cell should fill.
        • 'headers' - The headers attribute specifies which 'th' element a specific 'td' element is associated with using the 'id' value of the 'th' tag in the "headers" value. This is a screen reader technology and not needed if you use the "scope" attribute above. Most screen readers will identify what cells fall under which header elements quite easily, anyway. So, I do not recommend this element.
        • ARIA - In general, avoid the ARIA "role" and "aria-label" attributes here as this element is self-describing. If some columns appear or disappear from your table due to settings, and you want to help screen readers identify the index of a column from the total, you can add "aria-colindex={column number}".
        • 'class' (CSS) - See my sample CSS below to get started using a clean, cross-browser design for all your tables.
        • 'align', 'valign', 'bgcolor' - DO NOT USE THESE! These attributes on 'table' elements were used years ago to control the design of tables but are deprecated in HTML5, so avoid them.

      Additional Table Elements

      • <caption> - Captions sit on top of a table box and are usually centered. It provides a text title or description of your table and replaces the outdated "summary" attribute on the 'table' element.

      Table Elements I Would Avoid

      • <colgroup> - This element is shown in the example above but is not recommended as you can easily replace this element with CSS classes and styles.
      • <col> - This element is shown in the example above but not recommended as you can easily replace this element with CSS classes and styles.
    4. Table Cells and Weirdness in Formatting - In general, it's best that you ALWAYS remove all spacing inside 'th' and 'td' cells and align table cells next to content immediately after each tag, stack each table header or cell on a single line, and add content without any spaces, carriage returns, or line breaks between content as so: <td>My Text or Image</td>. Why do this tight wrapping of elements around table cell text? In the old days, many older browsers like Netscape 4 Series would create artifical padding and line breaks in tables if you had spaces, carriage returns, or added images that were not on the same line as your table cell HTML tags. So, always line up all your table tags around text and images and you will never see this spacing!
    5. Designing Tables with CSS - Because most default table designs in modern browsers are terrible, I have created a "reset" table element style sheet set below you can use to give your tables a solid starting design which you can easily customize:
      
      body table {
      	display: table;
      	margin: 0;
      	padding: 0;
      	border: 1px solid #000;
      	border-spacing: 0;
      	border-collapse: collapse;
      	vertical-align: top;
      }
      
      body thead {
      	display: table-header-group;
      	margin: 0;
      	padding: 0;
      	border: none;
      	border-spacing: 0;
      	border-collapse: collapse;
      }
      
      body tbody {
      	display: table-row-group;
      	margin: 0;
      	padding: 0;
      	border: none;
      	border-spacing: 0;
      	border-collapse: collapse;
      }
      
      body tfoot {
      	display: table-footer-group;
      	margin: 0;
      	padding: 0;
      	border: none;
      	border-spacing: 0;
      	border-collapse: collapse;
      }
      
      body tr {
      	display: table-row;
      	margin: 0;
      	padding: 0;
      	border: none;
      	border-spacing: 0;
      	border-collapse: collapse;
      }
      
      body th {
      	display: table-cell;
      	margin: 0;
      	padding: .5em;
      	padding: .5rem;
      	border: 1px solid #000;
      	border-spacing: 0;
      	border-collapse: collapse;
      	text-align: center;
      	font-weight: bold;
      	color: inherit;
      }
      
      body td {
      	display: table-cell;
      	margin: 0;
      	padding: .5em;
      	padding: .5rem;
      	border: 1px solid #000;
      	border-spacing: 0;
      	border-collapse: collapse;
      	color: inherit;
      }
      
    <template> template

    Template

    This 'template' element and its content below would be hidden by most HTML-supporting browsers until revealed by some type of JavaScript code.

    <template id="template1">
      <p>My hidden Template Text.</p>
    </template>
    My Recommendations:
    1. The 'template' element is new in HTML5 and reserves a hidden piece of content until revealed by a script. Most modern HTML5 browsers that support 'template' should "hide" the element and not parse it while loading the rest of the page into the DOM. You can then use JavaScript to show the 'template' and its content. But, I do not recommend use of this element due to its scripting dependency.
    2. If you choose to use 'template', it should have a unique 'id' and value so that JavaScript can locate it in the DOM faster and reveal it. Scripts will typically process the contents by parsing its contents then showing it, or cloning and appending it to another HTML node.
    3. Do Not Use the 'template' Element: Keep in mind, most older, non-HTML5 supporting browsers will render such a hidden element as this visible by default, destroying its main feature. Scripting as a dependency with this element is the next problem. Those which do support 'template' but have JavaScript disabled, some scripting features turned off, or no support for scripting at all might never see its contents! Because this element depends upon JavaScript to function, yet has no support in many older non-HTML5 browsers (like Internet Explorer 1-11), I do not recommend its use. There are simply too many ways it can appear or not appear.
    4. Alternatives to the 'template' Element: The 'template' element is really not needed and redundant, as there are numerous ways to now show and hide content from browsers. These new ways also allow you to use scripted and non-scripted techniques, including several CSS techniques, a "hidden" input element type, and even the new HTML5 "hidden" attribute which you can use on any element now. See my article below called "How to Hide HTML5 Elements and Content using CSS" for better options in hiding elements using plain CSS. These techniques have worked reliably in all browsers, old and new, the past 20 years
    <textarea> textarea

    Textarea

    see <form> for more details using <textarea> in forms

    Shown below is a complete code sample of the <textarea> element, which you can copy-and-paste into your web project. It has a rich set of attributes I recommend you use for each scenario. The visual design for this form is shown below the code. With these examples you have a complete set of code you can use in your web forms.


    <form id="formtextarea" name="formtextarea" method="post" action="#" title="Textarea Example" aria-label="Textarea Example" autocomplete="off" autocapitalize="off" spellcheck="false">
    <fieldset id="formtextarea_fieldset1" name="formtextarea_fieldset1" form="formtextarea" style="background-color:#fff;">
    <legend style="background-color:#aaa;color:#fff;">Textarea</legend>
    <div>
    <label for="formtextarea_textarea1" title="Textarea">Textarea Label:</label><br />
    <textarea id="formtextarea_textarea1" name="formtextarea_textarea1" title="Textarea" aria-label="Textarea" tabindex="0" contenteditable="true" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="true" maxlength="200">Enter your text here...</textarea>
    </div>
    </fieldset>
    </form>
    Textarea

    A textarea form field is also called a "textbox" or "text" by some. The Textarea allows users to submit large volumes of text in a form. Notice I have added the "spellcheck" attribute, which means in most HTML5 browsers, any misspelled word in the textarea box will have a "wavy" line under it. This indicates a misspelled word that needs to be corrected. Right-click the word to see a list of correct options provided by the browser.


    My Recommendations:
    1. The 'textarea' element defines a type of form field control used for submitting text. Unlike the 'input' text box, 'textarea' allows larger volumes of text to be submitted. The 'textarea' element has been around since the 1990's and in the earliest of HTML recommendations by the W3C. Like most form controls, the 'textarea' element is considered a "replaced" element, as its design and actions are controlled by the browser and operating system. It has changed very little in the past 20 years, so is a bedrock form field element supported in all browsers and versions. As such, it can be safely used in all your web forms.
    2. Always Wrap a <form>: Element Around Your 'textarea' Elements: When you wrap a form tag around a 'textarea' control, it tells the browser your 'textarea' is associated with a specific form "id" value and will only submit the field elements associated with that control. If you have multiple textareas and form fields to submit to a web page, it is crucial you know what select belongs with which form. You can still place the element outside a form if you give it a 'form={yourformid}' attribute with a value associated with a specific form "id". In that case, it will be submitted with all the fields inside that specific form. However, I do not recommend you move form controls outside of a form, as some older browsers may fail to send the right data when submitted.
    3. Always Use the <label> Element with Your 'textarea' Element: Try and use the 'label' element before your 'textarea' tag, then add the "for" attribute with a value that matches the textarea's 'id' value to associate the two together. This links the label to the form field and allows the browser, search engines, and screen readers to connect the two, adding semantic meaning. Often, the browsers will float the label text above the textarea control. But I have added a break after it as textarea boxes tend to float right as an inline-block element (see my code samples above for examples of labels and textarea controls). "clicking" on the label's text auto-selects the textarea and places your cursor in its box. Also add a 'title' attribute with description of your textarea to the your label.
    4. Collecting Form Field Data Using Textarea: The process of using 'textarea' elements and other form fields to collect and process data is way beyond the scope of this tutorial. The single most important aspect of good form field design (beyond HTML) is validation. That is discussed in-depth in the 'form' element section. The main thing to understand about forms and form fields is that data collection is the single most complicated aspect of web design, simply because it requires so many levels of exchange, validation, processing, analysis, and storage. Data collection and processing of form field element data is way beyond the scope of this tutorial. Just know, I have built dozens and dozens of large data collection applications in my life-time, and I can tell you good data collection always begins with solid HTML design, not fancy JavaScript, not fast REST API's, not secure server processes, not relational databases, and not fancy business applications. HTML is always King simply because HTML is the gateway between your users, your server, and your database.
    5. Always Use the 'id' and 'name' Attributes: Always use 'id' and a matching 'name' attribute with the same value when possible on all form field elements. The 'id' affects client-side scripts that must access a unique 'id' on the form field in order to access the control and its data. But 'id' is never sent to the server, unlike 'name'. As mentioned, I like to always match the 'id' value to the 'name' attribute, as I do in all my other form fields. Why? The 'name' attribute is what is always sent to the server, along with the input's "value" attribute. Assigning both 'id' and 'name' to the same value helps your server-side processes identify which form field you are processing and align the field's 'name' on the server or in the HTML with any client-side scripted validation or pre-processing that uses the 'id' value. If the two attribute values match, it's very easy to locate and sort client-side from server-side processes.
    6. Always Assign a 'tabindex' Attribute Number: Almost all browsers, old and new, add form field elements to a "tabindex" list. This means that all interactive elements are available for tabbing through by a user in the browser as they fill out larger forms. You really do not have to add this extra attribute to your form field elements or worry about this feature as it's built into all modern browsers. Most of the old ones, as well new ones will logically add all your form fields and buttons to a tab list. Nearly all form fields, links, and buttons are added to the tabindex, by default. However, you can manipulate this to change the tab order of your form fields in the index, remove a form field control from the tabindex, or add one that was missed by using the "tabindex" attribute. I always add the "tabindex=0" attribute to all my form fields to enforce addition of each control to browser's tabindex, which also lets the browser reorder everything, naturally. I add "tabindex=-1" to remove fields from the tabindex I do not want included. "hidden" types fields are never added to the tab index anyway, but I add the "-1" value to all other interactive form controls I don't want users stumbling across (including disabled fields, read-only fields, etc.). You can also granularly control tabindex by setting each of your controls to a specific number in an order, like "tabindex=2", and set the specific order you want your users to use. You can also set "autofocus=autofocus" to force focus immediately to a specific textarea field after the page renders. This overrides the natural tabindex, however. You don't have to override these features in browsers unless you want to change tab indexing. "tabindex" and "autofocus" can help enrich your forms and add more control over how you intend users to use them. See my code samples above which use "tabindex", and read my section in this page called "TabIndex and Autofocus in HTML" for more details on "tabindex".
    7. Title, Required, Disabled, Read-only, and Hidden Attributes - Always add a "title" tooltip attribute as it provides a nice rollover description of your form field control. For any form field that must be filled out or selected, you must use the "required=required" attribute. Required text means the form field must be filled out with some data by the user or an error will be generated and the submission will fail. This attribute can be overridden by add the "novalidate=novalidate" on the form or form field. Be sure to set any 'select element' you do not want sent to the server as "disabled=disabled" in your inputs. Data you do want sent to the server, but not changed by the user, should be set using the "readonly=readonly" attribute. Also set "tabindex=-1" on these "disabled" and "readonly" controls so the user does not tab through them. In modern HTML5 browsers, a form field element with the added "hidden" attribute will not be seen by the viewer but remain an active form field. But, if the browser does not supports HTML5 your form control will not be hidden! The new "hidden" attribute is redundant, however, as there is a "hidden" 'input' type you can use instead which is always hidden and always submitted. But, there may be rare cases where you just need to hide it. In those situations, I recommend you use CSS "visibility" instead to hide things, as it will work more reliably in older browsers. If you use "display:none" to hide controls, remember the input will not be seen AND will not be sent to the server on submission, unlike the CSS "visibility" property or the "hidden" element attribute. See my section called "How to Hide HTML5 Elements and Content using CSS" for more information on hiding elements in HTML correctly. Note: Always use the "XML-friendly" version of these attributes so your tags are always cross-compatible with both XHTML and XML. Do not use "readonly", but type "readonly=readonly".
    8. Optional 'novalidate': I discuss this attribute in more detail under the 'form' section (see <form>), as the form really controls this setting over all its child fields. But often you will have a 'form' with default settings and want to override them in each form field. A difficult one to manage is "novalidate". In general, the code samples above showcase my "best practices" and recommendations for how each field should use this attributes.
      The good news is "novalidate" is removed by default, meaning validation is enabled for the textarea control, which in my opinion is a good thing as HTML5 browsers now come with a new array of validation checks and features. Again, see my 'form' section for more details on how these work and some additional tricks to force them to do what you expect. But if you want to turn off validation on a field and override the 'form' element's default value, you can add the "novalidate=novalidate" attribute to your element.
    9. Do Not Use "accesskey": I do not recommend use of this attribute. Long ago, it was designed to allow keyboard presses to access form fields. But it is not reliable and requires various additional combinations of keys to work that are specific per device or just not accessible. It also conflicts with operating system shortcuts and could trigger other features on a laptop or phone by accident. Also avoid legacy attributes, like 'wrap', etc.
    10. Do Not Use New "inputmode": This new attribute is gaining in popularity, but still poorly supported in browsers. "inputmode" is now used as a "hint" to tell browsers the type of data to expect, like "email", "search", "url", etc. Because its not supported in IE, Safari, or Firefox browsers prior to version 24, it is not helpful or reliable.
    11. The Optional "data-" Attribute: As mentioned below in my "Best Practices" article called "The New 'data-' HTML5 Attribute", you can now safely use the new "data-" attribute in any HTML form element to store extra data values. Know that this is an extra attribute, and that "data-" values are not submitted to the web server anyway, so pretty useless. Its mainly an add-on for JavaScripted frameworks on the client-side.
    12. ARIA Attributes: The 'textarea' element is another "self-describing" structure recognized by most modern screen readers. Most screen readers can read each textarea box quite well, and understand what each one does. So, they do not need the ARIA "role" attribute. But they do need help knowing what type of data is being used so they can identify its semantic meaning. For that reason, it is recommended you add an ARIA "aria-label={Name of Item}" on each 'textarea' element to give screen readers more details about your 'textarea' does and its meaning within the form. You do not need the ARIA "live" attributes telling screen readers the "state" of your controls as they change unless you are manipulating the DOM using JavaScript. Use my code samples above to see "best practice" uses of ARIA attributes when designing textarea controls that assist screen readers.
    13. Form Field Validation: 'textarea' does NOT support "pattern matching" like 'input' fields. So validation must be limited to removing any dangerous injected scripts. Try spellcheck attribute to improve user spelling, and maxlength to limit text entries before entering textarea values into the database. As mentioned above, and in the <form> section, it is not enough to drop form fields like 'textarea' onto web pages and then hope the data coming into the server works. I have found too many cases where poor data processing ends up destroying a website! Even with fancy JavaScript, you cannot ignore the HTML design and server processing. That also includes heavy database scrubbing and processing. You need to always validate your form fields, no matter what the type, in ALL layers of your application. Do it, not just to improve data collection, but for security reasons as well! Data validation is not part of the scope of this tutorial but is native to the specific language, framework, network, and database architecture you are using. Don't rely on a single product like jQuery (JavaScript), either. Rely on good server-side validation, always, but good HTML design, too. It will help the user get the data right on their end without waiting on elaborate scripts to warn them later. Getting the HTML design right helps them navigate your forms faster, and makes it much easier for them to enter good data. Good HTML means it's one less layer you have to wrestle with. And it frees up control of data entry to your users, not your script libraries or your server.
    14. Trouble Styling Replaced Controls with CSS: "Replaced" elements like 'select', 'textarea', and others are notoriously difficult to style using CSS and have been for years. The reason is, they are not part of HTML but controls generated and dropped into the viewport by the browser. This is why these controls look so different between Macs, Windows PC's, and mobile phones. The browsers on these devices call the OS which helps determine their designs. Without getting into all the "hacks" and fixes out there to try and override these OS controls, I highly recommend you use plain HTML then stay with plain CSS code to style what you can and avoid all JavaScript, Modernizr, Polyfills, or "scripted hacks" to try and change their native designs. There are some clever CSS styles you can apply that alter the look-and-feel of these controls enough using just a few lines of CSS text that they are "presentable" and look close to the same across old and new browsers alike. There are also "prefixed" CSS rules (browser-specific styles like "-moz", etc.) that also can safely be used and which avoid JavaScript completely. If you start using scripts that hide or replace the HTML with a new form of control, you not only add complexity and unnecessary "hacks" that will likely cause form submission issues, but often it will fail completely in certain older browsers. In addition, your HTML will now be too complex for others to customize and likely erased when the next developer comes behind you.

      Below, I have added a very clean, widely supported piece of CSS code you can use to give your 'textarea' element a nice clean style that looks the same across many browsers and versions. This is the basic style I use for the 'textarea' example above:

      
      textarea,
      textarea:visited,
      textarea:hover,
      textarea:focus,
      textarea:active {
      	display: inline-block;
      	width: auto;
      	height: auto;
      	min-width: 20em;
      	min-width: 20rem;
      	max-width: 100%;
      	min-height: 10em;
      	min-height: 10rem;
      	padding: .2em;
      	padding: .2rem;
      	margin: 0;
      	-webkit-appearance: textarea;
      	-moz-appearance: textfield-multiline;
      	cursor: text;
      	overflow: auto;
      	resize: both;
      	background-color: #eee;
      	word-wrap: normal;
      	border: 2px solid #bbb;
      	border-radius: .2em;
      	border-radius: .2rem;
          line-height: normal;
      }
      
      textarea:visited,
      textarea:hover,
      textarea:focus,
      textarea:active {
      	background: #f9f9ff;
      	border: 2px solid #999;
      }
      
      textarea:focus {
      	background: #fff;
      	border: 2px solid #999;
      }
      
      
    15. See the <form> element section for more details about this element within a form.
    <tt> teletype text

    Teletype Text


    <tt>This is teletype text. If your browser supports it, it should be in a monospace font.</tt>
    This is teletype text. If your browser supports it, it should be in a monospace font.
    My Recommendations:
    1. The 'tt' element represents inline teletype text as would appear in a monospace font in fixed width displays and devices. This element is either deprecated in HTML5, not supported, or not recommended. Any element that is used solely for style is generally not useful in HTML. If you need monospace text use the <span> inline element with a CSS "class" attribute added and the following style declaration: "font-family:monospace". So, avoid use of the 'tt' element.
    <time> time

    Time

    <p>It is <time datetime="2021-06-26T22:00:00Z" title="2021-06-26T22:00:00Z">5 o'clock</time> here in my state. But what time is it in your state? My 'time' element might help!</p>

    It is here in my state. But what time is it in your state? My 'time' element might help!

    My Recommendations:
    1. The 'time' element is a new HTML5 element. It represents an inline piece of text representing time, date, date-time, or duration. It mainly assists search engines, screen readers, and other user agents in accurately interpreting page text as more complete, formal units of date and time. It is common to include the 'time' element with the local "datetime" attribute translated into Coordinated Universal Time (UTC).
    2. How Can The 'time' Element Help You? The local clock, time format, or calendar available on one computer, browser, or server can often fail to relate to time units posted elsewhere online or around the world. The 'time' attribute helps software, like search engines, ingest your text and extract out valuable date-time information. To do that, it needs your help. If you post time units online it is good practice to help others translate your time, date, or "time zone" information into a format others can relate to. Add this element where you would like the search engines, screen readers, or even some browsers to interpret your text as a formal date or unit of time they can use.
      Because there are so many different clocks and date time formats, its often important to frame them as some calendar date or time format that's relative to some standard universal unit of time, like UTC. The 'time' element is there to help interpret text in a "better" date-time format. To do this, its important to use the "datetime" attribute to display an "alternative" but formal unit of time in a format thats a supported "date-time standard" others know. So use this attribute for that dual purpose: To show your date or time text again in a more accurate format, but also in a standard unit that is know, like Coordinated Universal Time or "UTC".
      Example: It might be "5 o'clock" where you are, but what is that in UTC? Here, you might assume "PM" in Central Standard Time. But others online would have no idea what you intended. A good way to help them know what time you meant would be to translate your local time into universal time using "Coordinated Universal Time" (UTC). This time set is known around the world. Using UTC also helps search engine databases who can now easily index your time then translate it into multiple other "offsets" or time zones for others. To translate your time into UTC you would need to express your time in a new attribute in the 'time' element called "datetime". Add your translated date-time value there to help search engines or parsers see your time as UTC. An example would be expressing your local time shown in the example above as: "datetime=22:00:00Z" in UTC (this is assuming a standard time format, not daylight savings time). So, this value of "22:00:00Z" is what you might put inside the "datetime" attribute to give these search engines or the browser a frame of reference for your actual time relative to the rest of the world. Or, maybe you just need to clean up the "local" time format by expressing it as "datetime=5 PM CDT". Or, maybe you simply need show a more complete UTC format by also adding a full date to your time: "2021-06-26T22:00:00Z". Wow, that is really detailed now! Use "datetime" for those reasons. I highly recommend you read up on "UTC" and the global standard for time offsets for UTC, time in various web formats, and then "time zones". I also recommend you start translating all times and dates to the UTC format translation, which will then open up all your dates and time displays to an easily parsed UTC time both JavaScript and the web server can easily store and translate into other dates and times, using the UTC version of your local date-time values. Your web page will then have some longevity as search engines will be able to share your dated web page accurately for many years to come.
    3. Styling the 'time' element: By default, the 'time' element does not come with any styles. It also has no rollover or other default UA style in most browsers. It mainly serves parses and search engines. But I like to allow the 'time' element to have some visual effects. So above I have added the 'title' attribute with the UTC time in the rollover. In my style sheets, I've also added a dotted underline to the 'time' element ("text-decoration: underline dotted #000") so a user knows it is interactive.
    4. No Internet Explorer browser (IE 1-11) supports the 'time' element, nor any browser that does not support HTML5. But, because it adds value and is a non-obtrusive inline element when it fails, 'time' is safe to use.
    <title> title

    Title

    see <html>
    My Recommendations:
    1. The 'title' element defines the title of a web page as found in the head area of a web page. See the <html> element for a full description.
    <track> track, video tracks

    Track

    Avoid the 'track' element' in video in HTML5 until wider support for common track file "types" are more widely supported. But, an example of how to use the 'track' element in 'video' elements is shown below.


      <video id="trackvideo1" controls="controls" preload="metadata" title="My Video with Tracking">
        <source src="video1.mov" type="video/quicktime" />
        <source src="video1.ogv" type="video/ogg" />
        <track default="default" kind="subtitles" srclang="en" src="video/track.vtt" />
        <p><strong>Sorry, this video file will not play. Your browser does not support the video element or the file formats available.</strong></p>
      </video>
    My Recommendations:
    1. The 'track' element is a new HTML5 element that represents a set of timed text tracks added as captions, subtitles, chapters, or descriptions to movies or multimedia. This element is a child of the <video> and <audio> elements, and allows you to load caption timed text using a secondary "track" text file and display that text within the parent media file. This element is supported in HTML5, but because of the industry-wide failure to agree to a standard (to match common media types with tracking file types in web display), most text tracks technology will fail to achieve cross-browser minimum support, so I do not recommend its use today.
    2. Problems With Playing Web Video Persist: In past years, I have built and sold my own video, audio, and multimedia website software. So I know what I am talking about when it comes to the inherent issues in delivering successful cross-browser multimedia on the Web. I cover some of that history of movies and video on the Web and my experiences in my <video> section. But here is a bit more.
      Prior to 2010, there were only a handful of video formats and players for web browsers to use when displaying movies online. The main ones supported were Windows Media Player for ".wmv" files, Apple's Quicktime player for ".mov" files, Adobe Flash for ".flv" files, and a handful of others that included open source video, like .mpeg1, .mpeg2, .avi, etc. Today there are dozens. After 2007, adoption of the Adobe Flash Player was so widespread that most video could be encoded into Flash and be delivered widely across millions of websites and multiple browsers (and their many versions) with minimal issues. The Flash player was universal back then. But after 2010 and the demise of Flash on mobile, this solution has faded. We are now back to an even worse situation in HTML5, despite the "promise" of universal browser support of video online.
      Most of the video formats once supported years ago are diminishing and being replaced with a "potpourri" mess of partially supported codices that each manage player support, web browser support, and track file support differently. Add to this problem, the "specialized" 3rd party video players and products like YouTube, that require you to use their streaming architecture if you want to play videos. You must upload files into their system which use an amalgam of JavaScript, encoding, and other techniques to control video playback and encoding online. To use their product you also must embed video in a very proprietary way into your web site. It is not the "open" video system that HTML5 promised us. If you want a good video playback solutions in your website, you are stuck with 3rd party vendors, yet again.
      Without confusing you too much more, the problem with delivering video or any multimedia object online is the fact you are stuck with too many video products that each use their own proprietary system. This translates into video that often will not play in certain browsers, has no or partial support in older browsers, and is very inconsistent in how they support HTML5's new video player. Remember, when a video is created, it comes with its own unique "codec" or software that must be used to encode and decode it for Web display. Add the fact that each type requires a special "player", plugin, or software tool to play it. Each browser also comes with support for only specific "sub-versions" of each encoded type (older or newer versions of the MPEG-4 codec, operating system versions, etc.). And some players support either one type or multiples of each. But the Operating Systems also have limitations. For example, playing Apple ".mov" files on Windows, or the opposite, Windows Media Video files on Apple Mac's, was problematic in the past, regardless of which browser was used. Web "players", or third party software you downloaded to the browser solved this issue 2 decades ago. But the situation is far worse today, simply because HTML5 is trying to force all video to work inside the new 'video' element which must support as many video formats as possible, but often does not. Because so many factors influence video display in web sites (browser type, browser version, the operating system, codec type, codec version, player type, p[layer version, support of HTML5's 'video' element, etc.), there is no solid or predictable video tool to help you decide what's best in all scenarios. Example: The best video codec today with the "widest support" is MPEG-4. But MPEG-4 alone has different "encoding" types for each operating system, with Apple having one, DivX another, Windows another, etc. Some may or may not play based on operating system version, what software is installed, and whether the video is encoded in a version or type to support playback on that particular OS with its various players and their versions. Its possible some devices or browser versions do not have the player to play MPEG-4's at all, or have an older player that does not support a newer codec. On Windows 10 today this is still an issue for millions of people using MPEG-4, which is supposed to have almost universal support. So my point is, the problem of using 'track' elements begins with the problem of just getting video to consistently play across browsers and devices commonly used today.
    3. Problems Using 'track' Elements in Video: The 'time' track element is dependent on a supported video format and player in the user's browser, but is also dependent upon a "time track file" it must download and which must have both the right text and the right video codec support necessary to display that text inside the video. That track file dependency is what often fails in web videos, for multiple reasons, and why time track captions do not work reliably today. My goal in delivering web video and tracks, like my goal in HTML, has always been to pick the solution with the biggest "chances" of working for the most users possible. But in the case of "video tracking" files, this still is almost impossible for the fact that so many types of video and tracking in video is not standardized across the industry. I could give you one solution and tell you how to do it. But then for many of the readers of this article, it is not likely to work. One example is using the new "WEBVTT" format. It turns out it might work in MPEG-4, but will not in Apple Quicktime or many versions of Windows Media video files. In addition, there are numerous "versions" of each video codec that support different formats for tracking files used in video. Even if you added in all the variations of codecs, then added in all their supporting tracking file types, the video file might still fail across a wide range of devices, like iPhone, or Windows 10 users, etc.
      Video "time tracking" file "types" have their own problems and just compound the issues, when you truly look at all the types available today. There are so many "types" and "versions" of video tracking files in 2022, its way too complicated to sort out what is truly supported on what OS or browser. Below is a short list of the tracking file "types", some of which work for multiple video types, while others work for just one type:
      • .smil (Apple movies mainly)
      • .dfxp (Flash using ttml)
      • .vtt (new WebVTT format for the web)
      • wmp.txt (For Windows Media using .wmv formats)
      • .ttxt (3g devices)
      • .sami
      • .srt
      • .sub
      • .ttml
      Compound this issue with the fact there are multiple ways to add captions to videos. Beyond files, some video types have internal captions that do not support tracking files, where the captions must be encoded INTO the file. Some formats do not have any tracking, subtitle, or caption support. For these reasons and more, I recommend you abandon the 'track' element and instead use third party products and their proprietary caption systems. Most of these allow you to creatively build your videos and caption text online using their services or software, or have text captions embedded into their proprietary video formats. They then customize the video to support "on"/"off" caption and subtitling, translate the text for languages, and add other features and goodies way beyond what a simple HTML 'track' element might provide. YouTube would be one type I recommend. They also offer free streaming of the video (rather than on-demand downloads from your web server) and easy ways to "embed" the video into your web site. Some like YouTube, even offer monetization so you get paid when someone views your video! (This is a HUGE industry I will not discuss here).
      For these reasons and more, I cannot recommend use of the 'track' element until either HTML5's "living standard" matures to the point that an agreed on standard is supported across MOST of the browsers and players and codecs, or one codec amongst all the types available rises to the top of the heap, and becomes so widely supported and used that it becomes the standard online. It appears MPEG-4 has the best chance of that occurring. If you wanted to attempt to use the 'track' element, I would start with that codec. But right now in 2022, there is no clear winner when it comes to video much less track file formats. So, until that occurs, I cannot recommend use of the 'track' element in either video or audio. Otherwise, you risk seeing lots of browsers and frustrated users fail to see your carefully built time track text in videos.
    4. Cross-Browser Support of the 'track' Element: The 'track' element has decent support across all HTML5-supporting browsers except IE9. But it has NO support or alternative solution for all older browsers that do not support HTML5. So, tracking would not appear for those viewers. But, because lack of support of the 'track' element does not harm video playback, the lack of seeing text captions in video would do no real harm, and would be acceptable, in my opinion. It just would not work in most cases, anyway. So why try?
    5. See the following article for a full discussion of video codec types and limitations with creating a cross-browser video experience on the Web: "How to Create a Cross-Browser Video in HTML5".
    <ul> ul, unordered list

    Unordered List

    see <li>
    My Recommendations:
    1. The 'ul' element defines an unordered list. See the <li> element for a full description.
    <u> underline, unarticulated annotation

    Unarticulated Annotation

    Note that this element used to be called the "underline" element, but is now called the "Unarticulated Annotation", indicating text that is a non-textual annotation. This means it should be used to decorate text that needs further explanation, like a spelling error.

    This is some <u>mis-pelled</u> text that is given focus.
    This is some mis-pelled text that is given focus.
    My Recommendations:
    1. The 'u' element represents inline text that is different from the surrounding text. It often uses a plain "underline" to denote text that is "different", misspelled, or has an error. The general term for this element in 2022 changed to "Unarticulated Annotation"", or text that requires an explanation outside the context of the text content meaning.
    2. The Changing Purpose of the 'u' Element in History: In old HTML4, this element was used as a general way to "underline" any type of text that represented an idea or meaning that was important in a sentence. Later, this element was removed from earlier HTML recommendations because, like the 'small' or 'i' element, it was used by designers solely for styling text, not for assigning any semantic meaning to it. CSS could do that much better. But, in HTML5, the 'u' element has been reinstated. Why? Its purpose and meaning has now changed, though its name and style remain the same. It still underlines text, but the 'u' element now represents text which must be given focus because it is "different". It is now used to wrap around annotated text or text that has an extra meaning, like "misspelled words", mark text that stylistically is different, or text which has an error of some kind. But I do not recommend its use unless you completely change its CSS style, as shown below.
    3. The 'u' is Not Recommended: Why? I personally do not like the HTML5 definition of underlined 'u' text as representing misspelled words as that concept has no real meaning in the world of books and online text pages. No web pages or books I know of ever underlined text to alert someone of spelling errors. Why? Because they corrected them! In addition, you cannot use 'u' for emphasized or important text in a sentence, because 'em' and 'strong' are now designed to cover those scenarios. You also cannot use 'u' to underline text, as that will confuse readers with the 'a' element, or hypertext links. In addition, underlined text has been traditionally used in books for "focused parts" of a sentence, or to alert readers to important text. For all these reasons and more, you will just confuse viewers using 'u' and its default underline style. Plus, we now have the "spellcheck" attribute, which catches all "spelling errors" anyway and underlines them with a "wavy" line for you! So the 'u' element is truly redundant in websites today. And I do not recommend use of this element for the purpose stated in the new HTML5 standard, nor as a quick means of underlining "different" text, UNLESS you change its "underline" style permanently using CSS. If you do use the 'u' element, I HIGHLY recommend at the very least you change the "underline" style of the element to a "wavy" line (as shown above), or at least a "dashed" line for older browsers so users understand something is wrong with the text string (spellcheck error line). This also removes the confusion with hypertext links that are traditionally underlined in millions of web pages today. Because some older browsers supported the older 'u' element style, or might not format 'u' elements at all, I recommend you set the element with this permanent new CSS style. This then associates the underlined text as looking like a true "error". An example is shown below that works in old and new browsers. Note that some older browsers do not support the "wavy" style of line (like IE5), so the fallback "dashed" style is added below:
      
      u {
          /* Older IE browsers only */
          text-decoration: underline dashed red;
      
          /* Try and use the "spellcheck" wavy error line instead. */
          text-decoration: underline wavy red;
      }
      
    <var> variable

    Variable

    <p>The formula is: <var>a</var> + <var>b</var> = <var>c</var>.</p>

    The formula is: a + b = c.

    My Recommendations:
    1. The 'var' element is a piece of inline text representing a variable in a mathematical expression. This inline element is used to wrap around text strings that represent "variables" in equations. 'var' has been around since HTML4 and is still supported in HTML5. This element is similar to <code>, <kbd>, and <samp> in that 'var' formats text to represent abstract computer programs, keys, equations, or ideas.
    <video> video

    Video

    <figure aria-labelledby="myvideo" style="padding: .5rem;border: 1px solid #bbb;background: #f0f0f0;width: auto;height: auto;display: inline-block;">
      <video id="video1" alt="video: Fireplace Video" width="320" height="240" style="width: 320px;height:240px;border:1px solid #bbb;" controls="controls" preload="metadata" title="A Video of a Cracklin' Fireplace" aria-label="Fireplace Video">
        <source src="video1.mov" type="video/quicktime" />
        <source src="video1.ogv" type="video/ogg" />
        <p><strong>Sorry, this video file will not play. Your browser does not support the video element or the file formats available.</strong></p>
      </video>
      <figcaption id="myvideo" style="font-size:smaller;">"Fireplace Video" [<a href="http://creativecommons.org/licenses/by-sa/3.0" target="_blank" rel="noreferrer nofollow noopener">CC BY-SA 3.0</a>],
    via <a href="https://commons.wikimedia.org/wiki/" target="_blank" rel="noreferrer nofollow noopener">Wikimedia Commons</a></figcaption>
    </figure>

    Notes on this Video Example: If your browser supports the video element below you should see a movie of a fireplace. In this example, I have given HTML5 browsers two video "sources" to choose from: MOV (Apple Quicktime) and OGG. Your browser must support the new HTML5 'video' element and one of the two video codecs in order to see the movie.

    "Fireplace Video" [CC BY-SA 3.0],
    via Wikimedia Commons
    My Recommendations:
    1. The 'video' element is a new HTML5 tag used to embed movie content in web pages, including video files, streams, or movies files. (It replaces the old 'object', 'applet', and 'embed' elements in HTML4). Note: Unlike the old 'object' and 'embed' elements, which were often used with 3rd party plugins and players to play movies in past browsers, the new HTML5 'video' element is built into the browser and managed without a secondary player. Different browsers and OS's support different multimedia codices. So it is never 100% certain your browser or device will support your video file. That is why the 'video' element also comes with the new <source> child element with its "type" attribute to support your many video encoded alternatives (as show in the code above).
    2. The 'video' tag is structured like the <picture> element with multiple fallback child <source> tags representing alternative video file sources inside it. The browser will pick the first source file format it can play successfully from a list, or report a text message indicating no file format or audio element support.
    3. In the code example above, I have wrapped a 'figure' element with a 'figcaption' element around the 'video' element, so you can see how a full caption can be applied. This adds powerful ARIA attributes and descriptions for your videos so they are accessible by screen readers and the blind, as well. This matches how the new HTML5 'picture' element is used with 'figure', as both elements now work the same way with captions.
    4. As always give your element an 'id' for script control and a 'title' attribute to tell users what the video control will do.
    5. The 'src' attribute in 'source' elements must point to a valid video file or the video controls will not play a file when pressed.
    6. The 'alt' attribute in 'video' elements helps screen readers and the blind identify the meaning of embedded video elements, just like images provide. For that reason, always add the "alt" attribute.
    7. The 'width' and 'height' attributes can be set on the element, as well as in CSS. I recommend you ALWAYS set the attribute dimensions first, so the browser can create a placeholder for the 'video' element's dimensions. But you can always override those values and set dimensions in CSS so you have more flexibility. Note: The video element is a "replaced" inline element controlled by the operating system. I recommend you give it a "display:block" CSS value so you can at least control its borders, margins, and background features.
    8. The controls="controls" attribute specifies that video controls should be displayed. By default it generally includes play, pause, volume, time, and playtime position controls. Note: There is a controlless version of the video element, but I do not recommend you play video without giving a user control.
    9. The 'preload' attribute specifies a hint to the browser as to when the video file should be loaded. "auto" generally means to load the complete file as the page loads, but some browsers may ignore this feature. "none" would mean to not load the video file as the page loads and would load the file only when the play button is clicked. "metadata" would only load the metadata for the video file as the page loads. The default value is different for each browser. The spec advises it to be set to "metadata", so I recommend that value be set so you don't slow down the display of your web page with large video file downloads in the background. Note: These types of files are not true streams and are likely "on-demand" download streams buffered and negotiated with the server over http, unlike a true video streaming service and video player would negotiate over a streaming protocol like udp/rdp, etc. So, keep that in mind if your page has lots of video files on your server!
    10. There are other 'video' attributes you can apply, like 'loop', 'muted', 'crossorigin', 'poster', and 'autoplay' you can use for more control of your video, though I do not recommend them.
    11. There are numerous scripted methods and events you can apply to your video element along with scripts to fully control and customize your video player.
    12. Beneath the video control sample above I have added some small text with more info about the video file as well as licensing information. This is generally good practice so users understand the source of the file and have access to more textual information about its licensing. Notice I wrapped a Figure with Figcaption around the video element, so its text description becomes its caption. This allows it to work with captions as a 'picture' or 'img' element would do.
    13. CSS styling of the video control is difficult if not impossible, so realize there is limited support for designing video controls.
    14. Many modern mobile phone browsers as well as Internet Explorer 8 and earlier browsers on the desktop do not support the 'video' element! These older agents prefer the 'embed' (non-IE) or 'object' (IE only-ActiveX) elements, instead. So, keep in mind the limited support many modern browsers may have for the video control and its many features.
    15. I recommend use of the new HTML5 'video' element, but with the understanding many older browsers will not support it. Be prepared to offer 'embed' and 'object' alternatives for wider support in older agents. If you need more universal support for video controls across devices and browsers consider building a JavaScript-based video control. See the following article for a full, cross-browser movie example using the new 'video' element with alternative code for older browsers: "How to Create a Cross-Browser Video in HTML5".
    <wbr> word break

    Word Break

    <div style="border:1px solid black;width:auto;padding:.5em 1em;">
      <p>This (wbr) <wbr /> sentence can (wbr) <wbr /> drop down only where (wbr) <wbr /> I put a wbr element.</p>
    </div>

    This (wbr) sentence can (wbr) drop down only where (wbr) I put a wbr element.

    My Recommendations:
    1. The 'wbr' element is still supported in HTML5, though it was invented by Netscape 1.1 in the 1990's. It represents an inline "marker" that creates a word break "opportunity" should the text block need to break to the next line. Unlike the <br /> element, the 'wbr' does not create a "break" in the word or sentence unless it finds an opportunity to do so. It is rarely used, however.
    2. When to Use the 'wbr' Element: Add this element where you would like the browser to consider "breaking" text strings to the next line, should a breaking opportunity occur. This element allows article writers a little more control in how and where their sentences drop down to the next line when filling a browser window.
    3. 'wbr' and XML: HTML5 suggests you use the <wbr> element version. But, as I mention elsewhere in this tutorial, never use incompatible XML elements like this as they will cause your markup to fail in XML or XHTML parsers should your pages be parsed that way. Instead, always use the correct "XML-friendly" version: <wbr />
    4. No Internet Explorer browser (IE 1-11) supports the 'wbr' element, nor any browser that does not support HTML5. But, because it adds value and is non-obtrusive when it fails, it is safe to use.
    <xml> xml, data island

    Xml Data Island

    Xml Data Islands provided a way to store data in specialized xml tags. These would not be rendered in certain browsers (mainly Internet Explorer pre-version 9) and allow you to use various API's to extract client-side data. The two main methods used were to code directly into 'xml' tags or overload the script tag with these elements. Note: This latter idea was likely to fail in XHTML browsers without special CDATA tags. Today these tags are no longer needed because scripting API's and alternative data access via scripts has changed how and where client-side data is stored.


    <xml id="xmlid1">
      <xmldata>
        <data>text data</<data>
      </xmldata>
    </xml>


    <script id="xmlid2" language="xml">
      <xmldata>
        <data>text data</data>
      </xmldata>
    </script>

    My Recommendations:
    1. The 'xml' element is a deprecated element once supported in old Internet Explorer (pre-v9) and used to store data in a web page. That data was then accessible on the client-side using MSXML or other built in browser parsing JavaScript libraries. Often these were proprietary to Microsoft browsers or Windows users, or limited to JavaScript API library access. Most 'xml' data island tag support by Microsoft in their browsers ended after 2016 after the end of Internet Explorer browser support. It is no longer supported in HTML5 and rarely used. In 2022, you can now turn any element into data in a web page, use new HTML custom attributes like "data-" to store data, or use JavaScript API data solutions in combination with new the Web Workers API, window.LocalStorage, or storage of data in browser memory. My Recommendation: Do not use the 'xml' element or xml data islands to store data in web pages.
    <xmp> xmp

    Xmp

    <xmp>Non-formatted text with <span style="color:red;">HTML</span> text.</xmp>

    Non-formatted text with <span style="color:red;">HTML</span> text.
    My Recommendations:
    1. The 'xmp' element is a deprecated element once suppported in old HTML2/HTML3 that rendered text between the start and end tags without interpreting the HTML in between them. In some modern browsers, the 'xmp' tag may still function, but still should be avoided. Because 'xmp' is no longer supported in HTML5, do not use the 'xmp' element.
    2. Because 'xmp' text is also displayed in a non-formatted, monospaced font, this element can be replaced with the <pre> and <code> tags combined, escaping out HTML brackets as shown below. This simulates a display of HTML code, with text that is allowed to display in its native format, without line breaks, with added HTML escaped characters, and in a monospace or coded font. Use the sample code below to simulate this format in modern browsers:

      <pre><code>Non-formatted &lt;span style="color:red;"&gt;HTML&lt;/span&gt; and text.</code></pre>

      Non-formatted and escaped <span style="color:red;">HTML</span> text.
    * Global HTML Attributes
    The following Global Attributes Apply to all Elements and are Recommended:
    1. 'class' Attribute: Always assign a CSS class attribute to your elements, or multiple classes as needed (example: class="myclass1 myclass2"). Controlling styles this way with classes and matching class selectors in external style sheets is superior to embedded or inline page styles. AVOID the inline 'style' attribute on elements as it runs the risk of cascading over every class style you have, unless you are testing or building up styles on an element you will move to a style sheet later (example: style="font-size:2rem;"). Note: I only used inline style in my examples to show you how I would apply CSS to elements.
    2. 'id' Attribute: Always assign an 'id' with a unique value to all top-level structural elements (example: <header id="header">), to interactive elements like form fields and buttons, and to any element needing manipulation by JavaScript. HTML id's are easy to locate using scripts this way. Make sure they are always unique. I also like to use id's for styling elements, even though many say not to. If a unique elements needs to have its own special style, the heavy weight of an ID in Cascading Style Sheets rules will give it a 1000+ weight and make sure it cascades over any other styles applied. Just remember that 'id' styles only apply to that one element.
    3. 'hidden' Attribute: The new hidden="hidden" attribute can now be applied to any element in HTML. It is used to hide elements and works just like "display:none" in CSS. I still prefer the rich control of CSS as it has more options for hiding things. If you choose to rely on CSS for hiding things, then use "visibility:hidden" or "display:none". But the new HTML5 'hidden' attribute has promise! See my section called "How to Hide HTML5 Elements and Content using CSS" for more details.
    4. 'title' Attribute: The 'title' element can appear as an attribute on any element that appears on mouseover/rollover by the user. As mentioned, I like to apply titles (or what some call "Tooltips") to all my interactive elements, including all images, form fields, links, and headings. It is a nice rollover popup feature you can use when you want to give users more descriptive information about what an image, button, link, or form field represents. Many new developers avoid it in their HTML and leave out a critical piece of good web page interactivity, when they do.
    5. 'data-' Attribute: As mentioned below in my "Best Practices", you can now safely use the new "data-" attribute in any HTML element and name them anything you want after the 'data-' extension. Browsers ignore these, but scripts can use them to store and retrieve powerful information about your elements and the data they represent. Note: Older browsers will safely ignore this new HTML attribute, so its use will degrade gracefully in those older user agents, as well. Note that "data-" attributes are never sent to the server with form data! So do not rely on them for data processing, just scripting tricks.
    6. 'aria-' Attribute: As mentioned below in my "Best Practices", you can now safely use the new 'aria-' attribute in your elements to add additional accessibility and meaning to your HTML markup for screen readers and the blind. Use these new attributes to assist screen readers and other devices in understanding the semantic meaning of your HTML beyond what the elements already provide. But do not overdo it as most HTML elements have semantic meaning that most screen readers already interpret without additional attributes. The exception is "aria-label" which does allow you to "name" an element and its function, assisting screen readers. ARIA attributes are especially critical if you are building heavy Single Page Applications (SPA) using JavaScript-based, client-side web applications that update the browser's DOM behind the scenes without any server refresh or knowledge of those updates provided to screen reader software. In those cases you may find you need to not only add ARIA attributes to your HTML tags but the "live" versions as they change via scripts. Because this is affected by scripting technology, this is not discussed here. Note: Older browsers will safely ignore these new HTML ARIA attributes, so its use will degrade gracefully in those older user agents.
    7. 'inputmode' Attribute: This new attribute is gaining in popularity but still poorly supported in browsers. "inputmode" is now used as a "hint" to tell browsers the type of data to expect, like "email", "search", "url", etc. Because its not supported in IE, Safari, or Firefox browsers prior to version 24, its not widely supported enough to be helpful yet. For now, I do not recommend it. But as browser increase support of it in the years ahead, be prepared to to add it back in.
    8. 'spellcheck' Attribute: This new attribute is gaining in popularity, but still poorly supported in browsers. But when the browser comes with spell checking, adding "spellcheck=spellcheck" to any form element causes a "wavy" colored line to appear under any misspelled word typed by the user. This improves the quality of data coming into your website, when it is supported. Because it does no harm when it fails, it's totally safe to use. I like to add it to all my 'textarea' form fields so users can be alerted when they need to correct their text.
    9. Microdata: Microdata and its array of "item" attributes is a new annotation attribute for decorating your HTML elements with additional data and search engine metadata using name-value pairs that is more machine-readable. Basically you can add Microdata by adding "itemscope" to a top level element to create an "item" for the search engine spiders to index. All tags inside this parent that have an "itemprop=propertyname" tells the engines the tags property name, with the property's value being the text inside the tag. A "schema" is often used for "itemtype" on the parent, and defines a range of recognizable, agreed on standard properties to use. The schema also helps search engines categorize the data quickly when indexed. A simple example of how to use Microdata is shown below:
      
      <div itemscope="itemscope" itemtype="http://schema.org/Movie">
          The itemtype attribute above has been assigned to a third party "schema", and uses its content definition for "Movie" to help identify available properties for the data shown below.
          <h1 itemprop="name">Avatar</h1>
          <p>Here the search engine will see an item for a movie schema with one property assigned called "name" whose value is "Avatar". What is contained in the itemscope is itemprop or a property of the "Movie" schema type. This then tells search engine exactly what the content is and its category of data used by its property and value.</p>
      </div>
      
      This isn't a required HTML attribute, but can be helpful in building apps that will be indexed by search engines. Google is already using this to improve search results and add more granular metadata meaning in all parts of the web they index. Because most HTML is self-describing, this is often extra fluff to what is built into HTML already, and so not needed. Like the "data-" attribute or 'data' element above, it does not affect form field data sent to the server, the design of web pages, or the semantic characteristics of HTML. It is not helpful in terms of adding real meaning to your web pages. It is mainly for JavaScript or certain search engine effects. I would only use it for enhancing search-engine friendly markers in your HTML and for pages that have lots of tabular data. One example is large public-facing, informational websites that will get heavily indexed or archived by many types of parsers, bots, and search engines. Microdata is only fully supported in Firefox on Android at this time, so without wider browser adoption I cannot recommend Microdata.
    10. Microformats: Microformats, like Microdata, allows you to associate more meaning with your HTML and content. Minus the schema design found in Microdata, Microformats allows search engines, booksmarks, subscriptions, feed readers, and future browser extensions to extract more data from your content. The ultimate goal with this strategy is to extract data into JSON or other formats, and enable more access to your web page content and its meaning.
      One example of Microformats is shown below. The "h-card" is inserted into the CSS style "class" attribute, and represents any individual or organization to parsers of Microformats. In theory, this would allow this link to be parsed as a contact "card" to a specific person with a name, email, and "Twitter account" link. This data might be parsed by social media, search engines, and other feeds using your web page:
      
      <dev class="h-card">
          <span class="p-name">Your Name</span>
          <a class="u-email" href="mailto:name@website.com">name@website.com</a>
          <a class="u-url" rel="me" href="https://twitter.com/sometwitter">@sometwitter</a>
      </dev>
      
      Many of these new technologies are being integrated into public-facing websites build by 3rd party products like Wordpress and others. They then allow a limited set of browsers and parsers a slightly improved connection to your page data. This data is then parsed into data formats like JSON or XML, and linked back to your site. However, until we see wider adoption and more more general use, none of these technologies add a real benefit to your pages. Unlike Microdata, Microformats seems to have wider support in browsers. But Microformats is still is not supported by Internet Explorer or Safari browsers, desktop and mobile. It still does not yet replace standard search engine parsing or indexing to a degree that a solid argument can be made for its consistent use in building HTML pages. Until we see wider adoption and IDE's enable more implementations of Microformats in JSON, I do not recommend a major effort in using this new technology. Unless you are designing a very large public-facing site with with data tied into authors, organizations, social media, and indexed data, I see no reason to use Microformats at this time.
    11. RDFa: RDFa (Resource Description Framework in Attributes), like Microformats and Microdata, allows you to associate more meaning with your HTML content using HTML properties attributes tied to schema terms. Like the others, it has limited browser support and even less use-cases to warrant the effort in decorating your HTML with such attributes. If you do choose to use RDFa, remember that it has limited search engine support, is more closely tied to XHTML than HTML, and is best implemented when needing to develop large public sites with lots of rich data that must be consumed by search engine bots. It should be combined with the other data formats described above, so you cover all the various types of search engines and parsers. When used in combination with the other formats, it then becomes a measure of your overall web page search engine indexing performance and search ranking goals versus the cost of maintainability. That is why such HTML attributes are best used in larger sites, like Wordpress blogs and social media sites, where SEO goals are very important.
      An example of a simple RDFa code sample below shows how the new schema attribute "property" defines a term based on an external schema and the "inner HTML" text defines its value in the RDFa world. There are more resources online to cover all the nuances of this attribute and how it is best used. But I cannot recommend it at this time as an important tool in designing your HTML5 elements, unless you are designing a very large public-facing web application that would benefit from data parser support beyond the standard web browser:
      
      <h3 property="http://purl.org/dc/terms/title">Some Title</h3>
      <span property="http://purl.org/dc/terms/created">2021-12-20</span>
      


    HTML5 "Best Practices"

    Rules for Well-Formed HTML5

    Hypertext Markup Language (HTML) is the language of the World Wide Web. HTML has been around since 1990 and was invented by a British computer scientist named Sir Tim Berners-Lee. In fact, you can still view his first HTML website online! The general HTML markup language has not changed much since 1990. I have been coding in it since 1998, and since those early days have fallen in love with its simple, reliable, easy-to-use language (as have millions). Of all the dozen or more advanced languages and frameworks I have used over the years as a software engineer, HTML is still my favorite!

    Here in 2022, HTML5 is the newest markup language for creating web pages on the Internet. It has been around since 2008, but was not widely adopted until after 2010. HTML5 is based on HTML4, and has enriched the older standard with new elements and features. Since its conception, however, HTML5 has moved in a slightly different direction from what I call the "original HTML". HTML5 has in fact become a looser form of the earlier HTML markup languages. For starters, it is no longer aligned with SGML (the language for defining standard markup languages). Nor does HTML5 follow standardized markup rules as it did in the past two decades since its invention. After 2010, the organizations that now manage HTML5 have decided to abandon stricter standards and move forward with what I call a "vendor-based model" for how HTML should be interpreted. That has meant increased flexibility under its new "Living Standard" for browser makers. But the price paid, in my opinion, has been a disconnect from "good" coding practices of the past by many new web developers using new HTML5.

    It is true that HTML5 no longer has any connection to its older and more mature cousins: HTML4, XHTML, and XML. HTML5 now accepts a wide range of coding conventions, mistakes, errors, sub-standards, and styles. The browsers and parsers today that implement it have followed that "free-form" idea and are all stuck in an unending state of partially implementing the latest flavor of HTML5. It is a very forgiving language. But as a result, HTML5 is no longer well-formed, will not validate, nor does it follow older, standardized markup rules. The doctype declaration for HTML5, for example, no longer even needs a true "Document Type Definition" (DTD). Even the "quirksmode" concept of modern browsers flipping from "standards mode" to a quirks rendering mode is quite vague. This means the HTML5 coding "standard" is really a stripped down version of what HTML4 and XHTML1.0 transitional used to be. And that is why in HTML5 we have returned to "tag soup".

    But in its defense, modern HTML5 has been designed in such a way to allow a more "open" interpretation, and to allow a wider range of old and new conventions to be adopted and accepted across many devices, browsers, industries, and users. Many say that kind of flexibility is a good idea. But long term, I disagree. Forgiving coding standards without any enforced rules just allow bad or lazy coding practices to creep in. Already some new developers online are now advocating for a very proprietary, older, subversive "standard" of HTML markup that returns the language back to a non-standard, older, sloppier markup format most of us last used (and abandoned) in 1998 with HTML 4.1. The web will now be an even bigger patchwork quilt of broken HTML if we all allow it to go backwards and support poor markup conventions. All this may bode well for a more "adaptive", forgiving, human-centric web. It means struggles later for the machine-driven AI, "no code", or automated web of the future.

    But there is hope! For starters, you do not have to use HTML5 the way it was "recommended", or even use HTML5 at all! There is now a "polyglot" form of HTML5 called XHTML5 that follows stricter coding strategies, but which supports nearly all HTML5 elements. You can still use old XHTML transitional, XHTML strict, and even old HTML4, if you like. Coding in the XML-compliant versions do require well-formed markup, which also means they automatically work in sloppier HTML5, should you switch. The problem is that the reverse is not always true. Many of these antiquated coding "recommendations" used by HTML5 may support a greater variety of markup practices used online, but they would never support any of the more robust and reliable XML practices used in these other formats.

    The fact remains that HTML5 is what is hip, cool, and popular at the moment. And so that is what we should all adopt for building web applications on the World Wide Web. But, just because HTML5 has consistency flaws does not mean your HTML5 code has to follow bad coding practices. HTML5 is very forgiving, right? That means web developers and designers can adopt HTML5 as their primary web coding language but still follow "good" markup practices, if they like. HTML5 markup can follow "well-formed" XML markup practices and cleaner XML conventions, for example. It just isn't required to. But why would you do that when you can use ugly, sloppy HTML and get away with your "tag soup"? The answer is simple:

    By following the stricter XML markup standards in your HTML code, your HTML5 web pages can now be backward and forward compatible with XHTML5, XHTML1.1, XML, and even old HTML 3.2 or HTML 4.1. It can be nearly 100% cross-browser compatible with all these old and evolving newer standards all at once!

    There will always be markup in your HTML that is not 100% compatible with every language standard. But you can get close if not all the way there if you follow a few simple rules. That is at the heart of what "HTML5 Best Practices" means. But achieving that means hard work, erasing your bad assumptions, then re-learning all over again the RIGHT ways to build web sites in HTML. There are other reasons for you to follow more standardized XML-based markup rules in your HTML. The main one is so you deliver to modern browsers a fast and easily parsed HTML for the DOM tree (Document Object Model) that rendering and layout engines in browsers will inevitably build and display millions of times. Knowing that, why deliver sloppy markup to all those visitors? With cleaner code, rendering engines can build "Render Trees" faster in the DOM, generate faster layouts, and paint the viewport quicker, more reliably, and more efficiently using XML-based, standardized HTML. The user's browsers just run better! In addition, your ECMAScript "flavor-of-the-month" API can also parse, deliver, and read your HTML better with fewer errors or hiccups if the markup is clean, well decorated with attributes, consistent, and follows solid XML conventions. Some applications now read, write, and dynamically parse HTML pages as XML data, or even store them as XML in a database then recreate HTML from this data. Generating sloppy HTML from data that was not compatible with XML in the first place and that had to be "interpreted" or stripped of errors first, would make no sense, right? Why not build clean HTML from good HTML and return better HTML?

    I am not talking about perfection here, or even trying to validate your HTML in some way here. But the evidence is clear. Why not start off learning how to code HTML5 the RIGHT WAY using XML-compatible conventions? That is one of the MAIN REASONS for this tutorial....to teach you the right way to code. If the markup is clean and well-formed, as all XML is, then you will have zero issues with any of the things listed above, and your HTML will work well in XML or XHTML, or in future browsers using future HTML standards should you have to convert it. But coding in good, future-proof HTML means going BACK to older HTML conventions for answers, and forgetting current usage trends and ideas written about online today. Much of the articles written today about web technologies like HTML simply reinvent a wheel that was never broken!

    So, to start coding in good, clean, standardized HTML that is XML-compliant, simply follow my "Rules for Well-Formed HTML5" below. It will get you 99% of the way there!


    Rules for Well-Formed HTML5

    1. ALWAYS use lowercase tags in your HTML5 markup! This is the most important rule of all.

      DO THIS <input />
      NOT THIS <Input /> or <INPUT />

    2. Always use lowercase names for elements, attribute names and values, id's, files, CSS classes, paths, etc., unless it is a special script name. Remember, CSS is case-insensitive, but many HTML elements attribute names, like 'id' names and 'class' names are case-sensitive! So always go lower case to avoid problems!! The case of your names especially affects JavaScript variable names, so those can be cased as needed. Example: "Demo" is not the same as "demo" in ECMAScript variable and method names. I realize scripting frameworks today now use "camelCasing" (example: myMethodName) and other forms that do not follow older case rules. Those can be whatever you like. In terms of file names, many files in frameworks like .NET or on LINUX SERVERS are case-sensitive, too. So, mixed case file names could cause issues. Example: "London.jpg" is not the same as "london.jpg" on UNIX or LINUX, but is the same on most servers, Windows, or in browsers. UNIX also has been known to treat the domain parts of URL's with case-sensitivity. Also, many older browsers (like IE2 and IE3) treated CSS classes with case-sensitivity. That means if you use mixed-case CSS class names some browser would apply them where you did not intend! So assume everything is case-sensitive and stick with your own rules! I still would stick with lowercase text in your HTML tags, attribute names, and CSS until those case standards require changes in your code to support special API's or other 3rd party products.

      DO THIS <img id="myimage1" class="myclass" src="myimage.jpg" alt="My Image" />
      NOT THIS <Img Id="MyImage1" class="MyClass" SRC="MYIMAGE.jpg" Alt="MY IMAGE" />

    3. Avoid use of hyphens ("-"), double underscores ("__"), spaces (" "), numerical-first names ("1myclass"), and non-ASCII characters in all HTML attribute values, CSS names, paths, etc.. There are too many cases to cover where those items fail in various browsers and scenarios. But one example is older IE3 browsers where hyphens ("my-class") on CSS names will not work. Avoid all those special cases that could fail and stick with single underscore ("my_class"), instead. They look the same and can be creatively combined to cover all types of web page systems.

      DO THIS <a id="myanchorid2" class="myclass" href="http://mywebsite.com/mypath/" />
      NOT THIS <a id="2myanchorid" class="my-class" href="http://mywebsite.com/my path/" />

    4. ALWAYS use double quotes around attribute values in HTML elements ("..."), not single ('...'). In the "old days" it was ok to not use quotes around HTML attributes if the value included only alphanumeric values and no spaces, like this (title=hello). Not anymore! So, always quote your attributes in HTML5 to avoid a parser failing to read your values. If you have JavaScript inside, you can use single quotes with substrings inside. The exception to this is special CSS cases inside style sheets that use @import rules or background-image URL's which often use single quotes. Note that quotes in HTML attributes and JavaScript can be safely repeated over and over if you have complex strings within strings within strings using escapes: alert("John said 'What is the \"Truth\"'");
      A typical "best practices" example of quotes in element attributes using scripts is the following:

      DO THIS <a href="http://..." onclick="MyMethod('my string');" />

    5. Always explicitly define values in all attributes, and avoid ALL attribute minimization, despite HTML5 recommendations to the contrary. In elements like input controls, avoid the shorthand attributes. Don't rely on HTML5-recommended shorthand attributes like this as they are not XML-compliant and some may just fail in certain browsers:

      DO THIS <input checked="checked" />
      NOT THIS <input checked />

    6. ALWAYS close all element tags with a matching ending tag or a space plus forward slash. Empty or "void elements" must still end them with " /" so they are XML-compliant. HTML5 now says so-called "void" elements (like <source>) must never have an end tag, regardless. Do not add an end tag, but do add the " /" value. Many older browsers, like Netscape, misinterpreted any ending without a space before "/", so always include the space. Don't accept elements that do not have either an end tag or an explicit " /" at the end, otherwise they are not XML-compliant. Many young HTML designers today regularly fail to close many elements in HTML now simply because the markup rules are not consistent:

      DO THIS <img />
      NOT THIS <img> or <img/> or <img></img>

    7. ALWAYS use plain ASCII supported characters when possible in your HTML5 elements, which is anything alpha-numeric in the basic 128-ASCII character set or that is accepted in a standard browser URI without URL-encoding. This would generally be (a-z, A-Z, 0-9) and a few special characters (-._~). Characters (:/?#[]@!$&'()*+,;=) can be used but are problematic as many define query string delimiters and have to be escaped. So I would avoid all of those. In general, avoid special characters within or above the 128 character set inside your elements. This avoids the need for escaping of unicode characters or other issues. HTML5 is now UTF-8 compliant by default, so your page content will support over a million characters. But inside a typical URL or HTML page they may not accept those higher order characters without special escape characters, character references, or entities. Do not trust your browser as the final word as older agents might not support UTF-8. If you must use them, you can add character references as mentioned, which are special escaped characters starting with an ampersand, which follows XML encoding rules. An example of that is shown below:

      <a href="#" title="&copy; My Copyright, 2022" >My anchor title uses a copyright entity</a>
      My anchor title uses a copyright entity

    8. ALWAYS make sure all your HTML elements are XML-compatible and Consistent. Always pick the right form of an HTML5 element to use in your pages and consistently stick with it! Use that form across all your future projects as well, regardless of what your peers are using. Below is a perfect "case" example of GOOD HTML5 practices I have followed for over 20 years! Always use the <br /> form of the "break" element. This ending "/" with preceding space makes it backwards compatible with HTML4, HTML5, XHTML, XHTML5, XHTML1.1 strict, and is 100% XML-compatible and HTML5-compatible, as well:

      DO THIS <br />
      NOT THIS <br>, <br/>, or <br></br>

    9. ALL HTML documents must be well-formed and properly nested All HTML elements must be placed within the <html> root element, be nested properly in other elements, and have matching node start and end names for a document to be well-formed. Note: This is not the same as a "valid" document, which means the document follows the rules set in the applied HTML5 DOCTYPE in the header of your page. This just makes sure your HTML is not "tag soup" with mixtures of errors and blunders that break how HTML elements nest inside other elements.

      DO THIS <p><span></span></p>
      NOT THIS <p><span></p></span>

    10. ALWAYS use the richest and fullest attribute set you can in your HTML. By decorating your elements with the RIGHT attributes you supply the browser, the user, the search engines, the JavaScript, screen readers, applications, and even the server with all the "goodies" they need to interpret, interact, and respond accurately to your web page. Those groups then can interface with your web application and the information it provides with the interaction you expect from them. The "three-way connection" between the server, HTML, and the user is then maximized. Below is one example of the rich attributes an HTML element can have that affect many different groups in different ways:

      DO THIS <a href="https://mitchellstokely.com/" id="myanchor1" title="This is a Link to my Web Page in a New Tab" rel="noreferrer nofollow noopener" tabindex="0" target="_blank" aria-label="Internal Page Link">My Web Page</a>
      My Web Page

      NOT THIS <a href="#">My Web Page</a>
      My Web Page

    11. ALWAYS give all your important elements a unique "id" value! Many web developers complain about the use of "id" attributes and argue they don't use them, or do not need them until in a panic using JavaScript or CSS, they suddenly need one at the last minute. This is bad practice. In fact, there are so many cases for using "id" attributes on HTML elements, I cannot list them all. A few are: "id" allows easy access to a specific HTML element by JavaScript, high selectivity weight when used to assign a CSS style rule, access as a quick bookmark from an anchor links, access to paired elements by ARIA "aria-labelledby" attributes, and support by XHTML over the use of "name", which is not supported. The list goes on a on! The fact does remain that some older browsers did not support "id" for say bookmarks. Also, form fields never use "id" when they send data to the server. They use "name". For all these reasons I always use BOTH, and match the two with the same value. See below. Just remember to always use "id" with a matching "name" when you do, and all your web pages will be fully functional forever!

      DO THIS <div id="message1" name="message1">This block-level element has a unique id and name, so can be easily accessed as a bookmark, accessed via CSS, or manipulated by a script!</div>

      NOT THIS <div name="message1">This block-level element has no unique id, so cannot be assigned a CSS style, accessed as a bookmark, nor manipulated by a script so easily.</div>

    12. ALWAYS use Absolute Paths, not Relative Paths in all your HTML. Many new web developers have started to adopt these new, shoddy relative path systems in their HTML, CSS, JavaScript API's, and software systems that make updating and managing code paths difficult. They run the risk of failing in numerous ways, and add unnecessary complexity to simple web applications. You should AVOID relative paths as they often fail in older browsers when using paths in CSS and HTML. CSS was a perfect example where relative paths failed. But they also make maintenance of code extremely convoluted and difficult. When you use absolute paths, all paths are based off the web root, and allow you to see the true path to the files in question. With relative paths, its a mess as you can never know where the path starts and if the path up and down the folder tree is correct. Is the path to the file relative to the HTML file, some arbitrary virtual application path, the 'base' element path, or some artificially constructed application path? Relative paths can fail if the path does not know either the source or the destination, both of which can change and break relative paths quickly. There are just too many ways relative paths can break. Absolute paths always start at the web root and dive directly to the source, avoiding the need to know the start of the path. The web root is always the start in absolute paths. In the past, some older browsers like Netscape and IE3 would break if relative CSS paths were used. The one case for using relative paths is if you plan to have a website with multiple virtual applications that will move around under the same domain. In that one case, relative paths would allow you in most cases to move a website folder of files high, lower, or horizontally in an application and all the paths work. But absolute paths offer you the ability to move applications when you use server paths generated dynamically. Because all the paths start at the root, the server could easily inject a single root path for all images, styles, and scripts used in the project so that moving them is dynamically updating on the server via a single application path. Thats not possible with relative paths, which are all different. So, stay with absolute paths always, and avoid relative ones.

      Even a famous web designer, J. Zeldman, agrees with me:
      "Absolute URLs are more reliable than relative URLs because they don't break if file locations change; for instance, if "/events.html" moves to "/events/ index.html", the absolute reference to "/content/logo.gif" will still work. Also, absolute URLs help avoid a CSS bug in some old browsers that misunderstand relative file references in style sheets."


      USE ABSOLUTE PATHS LIKE THIS: "/css/theme1/styles.css"

      DO NOT USE RELATIVE PATHS LIKE THIS: "../../theme1/styles.css"

    13. ALWAYS use HTML elements that are widely supported in as many older browsers as possible and avoid most newer specialized HTML5 markup and tags that are not supported. (I cover this issue extensively in the sections below.) This is a no-brainer, and shows sensitivity to people whose browsers would fail to interpret your HTML layouts or content correctly. Often, this does not mean creating elaborate alternative HTML, polyfills, or running huge script libraries with fixes like Modernizr, but enabling older browsers to display your content adequately with bare-bones HTML, letting your layouts degrade gracefully in these older agents. This is now called "Progressive Web Design". In the old days we just called it good practice! Sensitive HTML designers must refrain from using the "latest and greatest" HTML5 tricks just to support fancy layout designs when needing to assist users with older browsers. In addition, JavaScript "polyfills" and other JavaScripted fixes that pollute the user agent with huge file downloads, JavaScript libraries, and additional CPU processing in order to add fixes to the browser's DOM are not good solutions in HTML, and are not recommended. "KISS", or "Keep it Simple Stupid", was the recommendation 20 years ago. It still applies today!

    My Complete HTML5 Template

    Below is a complete HTML5 template you can use that has all the recommended elements and attributes needed to build a good web page. This is a great starter template that you can cut-and-paste into any HTML5 web project knowing it will always work well in many browsers, old and new. This one has many good features for full cross-browser support in numerous browser versions and types, including full support for the latest and greatest HTML features used in more modern HTML5 browsers. (The elements shown are all discussed in detail in my HTML5 element section above.) This code below is well-formatted and coded in lower case text, is XHTML5/XHTML/XML friendly, includes all code needed to support CSS and JavaScript, and even has alerts for those browsers that do not support styles and scripting. What is best about this template is it required no JavaScript to create any of these features! It is pure HTML! You will need to add custom HTML page elements to this template under 'body', add custom server paths and files, add your external style sheets, and any JavaScript code or file paths needed. You will need to apply custom CSS to this template. It includes many hidden "gems" you will see in the code below that you will want to hide, show, or customize using CSS.

    Copy-and-Paste the Code Below to Create A Complete Web Page in HTML5



    NEW HTML5 Template with My Added Cross-Browser "Grid" Code

    If you want my HTML5 template with my new HTML flexible layout and cross-browser "grid" code built in (see "Final Cross-Browser Layout Grid Example"), I have added the integrated code for all that below. It includes the HTML5 template, layout, and complete grid system. It also includes a semantic-friendly "menu" in the header you can use. Just cut-and-paste the code below into a blank HTML page and you have it all! Just be sure to customize and style it as you like. This code is also mobile-friendly ad will collapse for smaller device screens. Note: The CSS for the "grid" and "menu" is inside embedded style blocks in the code below, which you can move into your style sheet, if you like.

    The huge advantage to using this code block below, is it not only gives you a powerful, pre-built HTML5 web page, but it comes with a complete, expanding web page layout using the new CSS "grid" property, that supports not just desktop browsers, but compacts its layout for mobile ones, as well. You can easily customize it as you like. It also includes HTML5 and partial CSS grid support for older browsers, like old Internet Explorer, with alert messaging and stacked layouts if they fail to understand the new CSS3 "grid" property. Using the code base below will give you a powerful head start in building a solid, cutting edge HTML5 page that works well in newer browsers, but which has basic support for many older ones, as well.

    Now you can get the CSS Cascading Style Sheet system behind this web page! Download my Universal CSS Framework at GitHub!

    Do NOT use Embedded CSS Style Sheets!

    Already in 2022, I am seeing web developers embrace Angular and React CSS designs, which by default inject horrible "embedded" CSS style sheet blocks into the head of every web page they compile. This means they download, compile, then spit out into the browser's DOM and memory non-cached style sheets into every page (and on every new visit to the domain) when they could have used a single linked style sheet that is cached and used for styling thousands of web pages and views.

    I wanted to show you what embedded CSS looks like below so you can avoid it. Some young developers incorrectly call "embedded" CSS an "inline" style sheet when its correct name is an "internal" style sheet. I sometimes drop internal CSS into a page like this when I'm building styles that will be moved to linked sheets later. It is a temporary home for my styles. In this web page I have added a few internal styles that only this page will ever see or use. That is a case where its ok to be lazy as I have demonstrations here where I have to add CSS I demo. But on large web project, after I'm done, I will erase these embedded style blocks completely from the 'head' of my page and add them to my linked style sheet. Its very easy to maintain all your CSS via linked files this way. The advantages are huge!

    "Linked" Style Sheets are Superior! A linked CSS file will be downloaded and cached one time and for days or weeks by the user's browser, saving the server and the user extra calls to the server as well as reprocessing time. Linked CSS files are associated with one website's domain and/or subdomain by the browser, so caching and use of its style sheet applies to every page a user visits under that URL. The styles persist in styling layouts and text no matter where a user goes in the site or what pages they view. As the user surfs the site it will use the cached style sheet stored in the browser's file cache, pulling it from its store on the user's computer as needed and storing it in memory. The browser then paints the render tree using the cached CSS file when laying out the various websites HTML pages and structures.

    "Embedded" or "Internal" styles are always downloaded per page and are gone when the user leaves the site (unless the page itself is cached). That means they have to be reloaded with each page view in the website. In a traditional web site, embedded CSS is often downloaded over and over again with every call to the server for each page this way, so it is quite wasteful. Often sites repeat the same styles between pages so total bandwidth used is very bandwidth heavy using these embedded style solutions. Linked style sheets saves your site huge bandwidth costs, not to mention savings in time-to-deliver, since pulling a linked sheet from the server, one time, then from a user's cache every other time is much faster than pulling a web page with embedded CSS over the wire from the server each time. Linked sheets won't be reloaded on each visit or page view if caching is enabled, where web pages which change with content will force the styles attached to be reloaded using embedded styles. Linked styles can also apply to thousands of web pages, where embedded CSS applies to one.

    In Google's Angular API, that model is not always used the same way. But components and modules in these JavaScripted API's that store embedded CSS must compile and then repeat the same CSS in various modules that could have been shared via one master sheet. In Angular's case, a download of the same JavaScript modules would also contain the same CSS, forcing a fresh download of those styles every refresh or visit of the browser to the domain. It is simply a CPU and memory hog downloading, storing, and displaying page-level CSS this way! Caching CSS via a link is just so much more efficient.


    Always use linked style sheets like this one!
    <link media="screen" rel="stylesheet" type="text/css" href="styles.css" />


    Below is what NOT to do. Angular and many JavaScript API's apply embedded styles below to their dynamically-created HTML pages. Never use embedded CSS blocks like this unless you are ok customizing CSS on a page-by-page basis.

    Every Web Page needs a "h1" Heading Tag!

    Every web page needs an "h1" heading at the very top of the page. It defines the purpose and content of the page to search engines and screen readers. It has powerful influence over how pages are indexed by search engines. It can be placed either above the navigation in the 'header' element or inside the 'main' or 'section' elements as a page title. The 'h1' element should be your choice, as it represents the top level heading element, with smaller headings and content after it.

    Because many modern web pages do not always use heading elements in their navigation due to design issues (enlarged title text) you should use CSS to change its placement and design. One strategy is to make your 'h1' title text your header's default home link. Some designer's wrap the header logo inside the "h1" element. But the 'h1' text should be specific to your page's content. So, my recommendation is to place this link inside the main page area inside 'main' or 'section' elements.

    Search and the H1 Element: If you really want your HTML to tell Google or other search engines what your web page content is about, you want to match the meta tag 'title' text with your 'h1' text title text so they are in sync. Search engines love this! As a matter of fact, search engines are designed to read either your meta tag 'title' or your 'h1' when determining a search entry for your page. So count on your 'h1' text showing up in search engines! It is one more reason to make sure you use the 'h1' reliably.

    ARIA Accessibility: In the example below, I have also added ARIA accessibility features that further connects the heading with the HTML semantic layout structure. The "aria-labelledby=mainheading" attribute below connects a page's 'section' element and document with the 'h1' heading element, allowing screen readers to associate the web page document features with its top-level title. This is an ARIA accessibility feature and helps screen readers know what the section does as defined by the header element. As above, linking the 'title', the 'h1' heading, and accessibility labels aligns your pages meaning and purpose with viewers, search engines, and screen readers all at once!

    Using Headings

    Headings are used by search engines to identify content and to decide important content sections in pages. Use headings to help users and search engines determine "document structure and content" of a page and its subject. Search engines will read the text in a heading and give it importance if not use it for search titles in cases where the meta tag title is absent or not sufficient. Below are the 6 heading title tags and the relative spacing you can expect when using them. In general us "h1" for the top of your page and lower numbered headings for subtitles. I have put background colors on these only so you can see the line spacing used for headings. Remember, use headings ("h1" primarily) with rich keywords that match both your meta tag "title" and "description" tags, as well as the keyword-rich text content of your web page. This affects positive search engine rankings in all your pages, when done correctly.
    Note: In ARIA you do not need to add the role of "heading" (which identifies a subsection heading of the page) as screen readers know what the "h" elements represent. Because the "h1" heading element identifies the tag as a heading element, these types of ARIA roles are really not needed. I would only use the 'role' attribute if you used a non-standard element for a text heading. (see my HTML5 element list on "h1" headings for more details.

    Header 1

    Header 2

    Header 3

    Header 4

    Header 5
    Header 6

    Why Should You Replace 'B' and 'I' With 'STRONG' and 'EM' Elements?

    HTML uses elements like "b" (bold) and "i" (italic) for formatting text. Formatting elements were designed to display special types of text visually. But some say its now better to use 'strong' rather than "b", and 'em' rather than "i". Leaving these elements unformatted and changing them with CSS is also fine. But by using 'strong' and 'em', you are letting the user's browser or user settings determine format while identifying important semantic content to search engines and screen readers. Search engines will give emphasis to tags like "strong" and "em" as they imply something beyond visual formatting as those elements add special importance to plain text. Note: Using CSS, I like to format "strong text" exactly as "bold text" using 'font-weight'. But I apply "font-weight:bolder" so that strong text is relative to what formatting exists, bolder not just bold.

    Bold text - Bold with no importance
    Important text - The Strong element defines strong text, with added semantic "strong" importance beyond bold formatting.

    Italic text - Italic with no emphasis
    Emphasized text - Like italic and like strong, the Emphasize element and adds importance to normal text beyond italics formatting

    Use of Blockquote and Quoted Text

    Use 'blockquote' for larger quote "blocks" without the curly quotation marks, and 'q' for inline, shorter quotes with the curly quotation marks added. I generally believe this set of tags is typically not needed unless you are doing formal article writing, news stories, or where you are taking information from a source that is not your own. Most young people I have noticed use quotations excessively online when paraphrasing is just as acceptable.


    Use the "q" tag for short quoted text (Note that browsers insert curly quotations around quoted text here):

    My old teacher used to tell me, Build a future where people live in harmony with nature.


    For longer quotes use "blockquote". (Note these are not quoted with curly quotes but indented). Like with the <ins> element, the 'cite' attribute is needed if your content comes from another online source. This prevents accusations of plagiarism!

    The World Wildlife Fund has said the following:

    For 50 years, WWF has been protecting the future of nature. The world's leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United States and close to 5 million globally.


    Use Horizontal Rules (hr) when Separating Content

    "Horizontal rules" are an old HTML trick that is still useful in all modern browsers. Use horizontal rules for separating content. It is just that simple! The original horizontal rule originally was created as a way to replicate the small separations found inside an article or inside a book novel's chapter where the scene often breaks away to a different one and a marker or rule is added to tell the reader of the sudden change. The same can apply to web pages. But the horizontal rule concept has gradually expanded from simple literary concerns to separation between lots of different types of content online. Notice the space plus forward slash in the 'hr' element below. I highly recommend you use this XML-compatible version. It is not required but backwards compatible with XHTML, as well. As noted in all my HTML5 designs, the rule is also friendly with search engines who also will identify a separation of content and ideas when it finds a horizontal rule.

    Content here...


    Different content follows a horizontal rule...

    The Two Main Types of Buttons in HTML

    With HTML5 now, you can turn many elements and images into click-able buttons. We will not cover that concept here as in nearly all cases, using HTML5's native, semantically friendly 'button' and 'input' elements should cover all your button needs. Keep that fact in mind if you start to get creative and try and define your own buttons in HTML. Now let us proceed...

    There are two main types of buttons in HTML. Most web developers forget this fact. There is the 'button' element and the 'input' element. I have styled the two types the same inside my custom "reset" style sheet so they look the same.


    <button id="buttonexample1" name="buttonexample1" type="submit" aria-label="Submit" title="My Cool Button" tabindex="0">My Button</button>


    <input id="inputbuttonexample1" name="inputbuttonexample1" type="submit" value="My Button" aria-label="Submit" title="My Other Cool Button" tabindex="0" />


    The 'button' element is always a "button". The 'input' element is the second type of "button" and can be a button or a non-button. It is a web form control but has many other sub-types besides the "button type". Both elements use a 'type' attribute to define what type of button they are. But the 'button' element is ALWAYS a button regardless of its type. Confused yet? It gets better.

    Both 'button' and 'input' elements share the same button 'type' attribute and can have one of these three types: 'button', 'submit', and 'reset'. Without the 'type' attribute, the 'button' element is a "submit" button by default, while the 'input' element is a 'text' input control by default (non-button). The 'submit' type is the ONLY type that will post all form field input data to the server. More on that later. The plain "button" or "reset" types do not. The plain "button" type never does anything and requires JavaScript or other scripting to respond to any user clicks or events. Besides its three button types, 'input' element can have a fourth button type called 'image' which allows it to use an image as a button. The "image" input button type performs like a "submit" button. More on that later. The only real difference between the 'button' and 'input' elements as buttons is the fact the 'button' element allows HTML elements between its tags, while the 'input' does not. And so the 'button' element allows a richer set of design possibilities, where the 'input' element only allows text on its button using the 'value' attribute, or with an image using the "image type". This means 'button' elements can be styled to look visually more appealing as HTML can be added between the start and end button tag set. The two types of buttons possible are shown below using the 'button' and 'input' elements with their various 'types'. Example:

    'button' elements can have rich HTML for its button text and design...

    <button aria-label="Submit">Some <strong style="color:blue;">HTML</strong> here...</button>

    ...while 'input' does not and is stuck with its 'value' attribute text...

    <input type="button" aria-label="Submit" value="My Button Text" />

    The "Image" Button: As mentioned, the "image" button type for 'input' elements does allow you to use an image for a button, but a background image in CSS could also be applied. Remember image 'input' buttons are also submit buttons. Because both 'button' and 'input' controls can have images in some form they essentially work the same:

    <input type="image" aria-label="Submit" src="css/default/content/import_excel_button.gif" alt="Image Button" title="I am an Image Button!" tabindex="0" aria-label="Button" />

    However, you can now create buttons from ANY element! Using CSS and the ability to create images or anchor elements or even divs as buttons now, there is no longer a preference in terms of which element to use when creating buttons. But it is still best semantically to use the 'button' or 'input' elements for all your buttons. There are some minor visual layout and value submission bugs in old IE6 and IE8 browsers using the 'button' element. But today in modern browsers, those issues no longer exist. Most developers still prefer using the 'input' with "submit" type to post form input data to the server. The 'input' is also a member of a larger family of matching form controls, so fits better as a button with most traditional form control designs.

    BUTTON STYLES: Keep in mind you can style these as you like with beveled or raised surfaces, colors, images, etc. Here we are just focused on their elements as markup and the semantic meaning their button-nature implies, not the myriad of CSS designs possible. The 'button' element's default UA designs by default traditionally had a raised or beveled look in many older browsers with a gray background to help identify it as a true button element apart from a generic input control. In fact all buttons are NOT part of HTML itself but considered "replacement" elements or "objects" controlled by the operating system. That is why Macintosh browser buttons always look so different from Windows ones, or phone buttons, etc. I like the old gray Windows looking buttons from long ago. Some newer browsers still style it that way, but others replaced it with a more modern look. Again, the operating system has a big influence. Bootstrap and other style sheet systems have flattened some default button designs through their "reboot" sheets. I generally do not like those styles. Note: In CSS, often adding a "border" CSS style to a button will trigger the button to abandon the raised button-like default OS styling and flatten the button to look more like HTML elements. Weird, huh?

    HTML5 STYLING: In addition, be aware that HTML5 now allows you to apply more CSS pseudo-classes to buttons. They also trigger in most modern browsers new events you can capture and control, like colored "outlines" on rollover or other custom features like different "states" of 'inputs' and 'button' elements. These include special events like when a button is hovered, focused, valid, invalid, active, or disabled. The best design choices for these two elements is to simply place simple formatted text, border, rounded corners, and raised effects to them as needed and utilize the more widely supported pseudo-classes in CSS to style their backgrounds, outlines, or raised effects (I have a fully styled example below in the "form" HTML5 example).

    BUTTON ATTRIBUTES: There is a rich set of attributes on buttons, which I have outlined in the "HTML5 Element List" above. But here are a few "gotchas" and "best practices" on attributes. If you leave off the 'type' attribute on the 'button' element, the 'button' without a 'type' attribute defaults to the "submit" type. That means when clicked, they will post all form data in the page to the server by default. So keep that in mind. The other button 'types' for both 'input' and 'button', "button" and "reset", do NOT submit data to the server, as mentioned above. "Reset" clears all user form control values from all forms in a given parent 'form' element. The "button" type does nothing until you assign some type of scripting or event response to their click events. "submit" is the dominant type for 'input' and 'button' "buttons" and so you will use it in nearly all your HTML5 pages to submit data to the server. The other "gotcha" is when you have multiple forms of inputs in a single page. Be sure you add the "form" attribute with the name of the form the submit type button will post to the server. In addition, all submit buttons and their parent forms by default submit forms as a "GET" rather than a "POST". This means, when pressed, if you have not set the "formmethod=post" attribute on the 'form' element (recommended) or the 'button'/'input' then all form name-values pairs from the input controls are sent via the url as query strings rather the host header which is slightly more secure. I will cover more of this info in the "HTML5 Element List" above.

    New Forms of HTML5 Buttons: With the advent of newer JavaScript API's, WebAPI and REST events in web projects, and JavaScripted SAP's (single-page-applications), many buttons are now created using anchor elements and onclick events the web designer controls and captures. The form data is then dynamically processed in the browser or client and sent to the server using XMLHTTPRequest objects in JavaScript, rather than trusting the natural server POST capabilities of the native "submit button" itself. In addition, in HTML5 you can turn any element like images or links into buttons. Many element can now have a 'type' value of 'button" or 'submit', as well, which behave like a submit button. Adding JavaScripted event capture to your pages and these new non-button elements means you as designer now have more control over how and where buttons in the web page submit data. But these are all "illusions" of the original, native browser button itself. Even though I too have built these JavaScript systems and enjoy the freedom to do so, I still recommend you use the 'input' or 'button' for all your button events for semantic reasons and as a fallback in case scripts are disabled or you need to support user-agents that do not support click events on non-traditional button elements. The 'input' and 'button' controls still tell users and browsers what elements control submission events. Helping developers and browsers understand which elements are real "buttons", rather than assigning obscure HTML elements as buttons, has larger impacts on how semantically-friendly web pages perform with screen readers and the blind, as well. Therefore, I recommend you stay with the more traditional elements when creating buttons and reconsider using these JavaScript API's in the future, as they distort the original purpose of the web browser submit button and will never be as semantically relevant and as important to the Web as plain HTML5 elements.

    * For more detail on button attributes and features see the "HTML5 Element List" or my HTML5 form example.

    The Mystery of Line-Heights Revealed!

    "line-height" in CSS style sheets has often messed with HTML layouts. Most young web developers fail to understand line-heights and how they affect HTML layouts. So, I thought I would cover those briefly below.

    Let's cut to chase on line-heights. Most text in HTML is displayed as a font-family and font-size, then given a "default" line height that most often matches its font and font-size. These three items give text its essential display in the space of the typical HTML web page. Without them it would not appear at all. In the example below, I have added simple text to a 'div' element. All I have added to the 'div' is a border. The font-family, font-size, and line-height are using the browser's default values. Notice that the font floats inside the box but has a strange but natural border at the top and bottom. This is created by the "line-height". I have set my web page's line-height to "1.5" for better reading. You can see that extra spacing below. That has created the small extra space above and below the text in the bordered 'div' box below. I went ahead and added it to the style of the element, as well, so you can verify it works.

    Line-Height Test
    <div style="margin:0;padding:0;border:1px solid #000;line-height:1.5;">Line-Height Test</div>

    Below, I've gone ahead and changed the above example. I have turned the font-size into pixels and the line-height explicitly assigned in pixels, so we can start to test a few things below. "font-size:16px" is the same as the default font-size in most browsers for most fonts set at the default medium size.

    "line-height" can be either a number or a unit, like "px" mentioned above. There is a big different between the two, however. When using the numeric version, line-height is inherited first from a parent element, then calculated based on the element's own font-size, which could also be inherited. That is the opposite of line-height in say "em", "%", or "px" where line-height is first calculated from the parent, then applied to the child.

    When "line-height" is defined as a number, "1" is the same value in pixels as the font in pixel size. So "font-size:16px" when assigned as line-height of "1" has a "line-height:16px". You can also use "em" but I do not recommend "em" for line-height as its corresponding font-size is always relative to the parent's value which can compound when inherited by child elements.

    You may ask, what is the DEFAULT line-height, if not "1"? Strangely enough, the default "line-height" value is NOT "1" but varies by font family, size, height, and browsers. Using the keyword "normal" returns the line-height to its default or natural value. Some estimate the default or "normal" is around a numerical value of "1.14", which is more of an average of most font line-heights. It often varies, because some fonts come with elaborate glyphs or accents that stretch far above the capital letters. This default value is only applied when you use "line-height:normal". As a general rule "normal" is good when you want to reset back to the font's natural "line-height", though no one can tell you what that translates to in pixels or numerical values! I believe using "1" is still safe for controlling stricter compressed line-heights on most fonts, though in some cases that value for line-height causes some minor bleed over of text in their containers. Most designers now apply larger line-heights than "1", like 1.2, 1.5, etc for readability anyway, which exceeds the natural line-heights. They are safe to use this way when larger. However, as we will see, larger and larger line-heights still push text blocks outside many container blocks!

    Below, I have now added a "16px" line-height (same as "1") to this new example, which overwrites my web page's larger "1.5" value. You can see how that's collapsed the white space around the text now, yet keeps some spacing for text accents on capital letters. For some browsers, the bottom text might still break out of the parent container by a pixel or two using "line-height:1". If this is an issue, use "normal" again.

    Line-Height Test
    <div style="font-size:16px;margin:0;padding:0;border:1px solid #000;line-height:16px;">Line-Height Test</div>

    How Line-Height Works

    The spacing in "line-height" actually is pretty strange. It acts like a "box" around the text, creating space much like a block-level element, starting from the middle of the text, expanding above and below it. But it also acts like a "float" in CSS in that it can break out of any parent block that holds it. We will see that next. Below is an example of a new text block using the same 'div' text as above but with a few changes to the line-height. Here, I have set "line-height" to "0". I have also set the parent to "height:16px", the same as the line-height, and added a gray background so you can see how a font's line-height affects the text as it gets smaller or larger than the parent's height.

    Notice that the text below at "line-height:0" has moved up into the box and now sits halfway above the gray box's top boundary. With "line-height:0" the text moves up to the top edge of the 'div', yet oddly sits partially above it. It appears that as the line-height collapses to zero, that the text moves up in its parent container until its middle-axis sits just below the top of its container. This shows that the text exists independent of the container block, and that the text's anchor or reference point in space begins at the mid-point of its text height. Therefore, line-height creates "space" for the text to exist in the parent box but creating space above and below the middle axis of the text block. It does not, however, control the appearance of the text by hiding it when "0", as you might expect. It simply expands space around the text so the text can float inside block-level elements. The text still doesn't break out of the container, however. But its "line-height" does control how and where it positions itself inside its parent container.


    Line-Height Zero Test
    <div style="height:16px;background:gray;font-size:16px;line-height:0;margin:0;padding:0;border:none;">Line-Height Zero Test</div>

    Let's now expand on what we just showed. "line-height" now is easy to understand. It appears to simply create space around text starting with its middle-axis, going above and below that point, so text is placed or "floats" inside this imaginary box. Because line-height space exists simply for the text space and is independent of parent block space, it can hold itself in block-level parent elements or break out of it like a float. You can see that effect below. I have added various increases in line-heights to the example below. Notice as the line-height increases the text moves back into the parent box, then breaks out again and pushes below it. Knowing how line-height works, you can now understand its "weirdness" when text breaks out of your carefully designed boxes.

    line-height:0

    line-height:1px

    line-height:8px

    line-height:16px

    line-height:32px

    line-height:64px

    Below is the code:


    Normal Line-Height

    The above examples occur because we have set the "height" on the 'div' to a set pixel value, along with line-height settings smaller or larger than the space needed to fill the 'div' parent's 16px height. This is one more reason to NEVER USE PIXELS IN WEB PAGE LAYOUTS when defining web pages as ANY change to font-sizes or line-heights could cause text to break out of pixel-based web designs. Now, an easy fix to the above "weirdness" is to first of all, set all parent containers of text to "height:auto", or set height to elements to "em" units which will scale as the text scales in size. Fonts start out with the same size as the user's default font-size, using "em". This allows line-height to increase and stay inside the 'div' parent container, in most cases. The important thing to realize here is that "line-height" acts very much like a block-level element, creates space for text to exist, and can break out of block-level elements. Now that you know these facts, you can safely define line-heights in your pages and fully understand the consequences if you increase or decrease their values in parent blocks. Below is an example of a good line-height design where I have simply set "height:auto" so the height always expands as line-height expands and "line-height:normal", which matches ideal font line-height to whatever font-family and font-size is assigned to the text. Using "auto" and "normal" means our text will NEVER break out of a container and always use the preferred dimensions as set by the end-user. I also like to use "font-size:medium" in all my web pages, which tells the page to always start with the user's preferred or default medium font size (whatever size they chose becomes the "medium". Using "line-height:normal" with this user-centric "font-size:meaning" CSS property, means your web pages are not only 100% scalable by font and line-height, but they zoom as the user chooses while "honoring" the user's chosen font settings in the browser.

    Normal Line-Height Text
    <div style="height:auto;background:#ddd;font-size:16px;line-height:normal;margin:0;padding:0;border:none;">Normal Line-Height Text</div>

    Use the 'pre' element for Preformatted Text

    Use the 'pre' element for preformatted text and to preserve whitespace and display text EXACTLY as it is entered or formatted. Note: This is NOT the same as the 'code' element, however, which is designed to display and semantically mark text as computer code. 'pre' elements can be quite useful, however, when combined with code, as they convey the idea of code, but also code that is carefully formatted like all code usually is. For that reason many websites will wrap a 'pre' around a 'code' element, or set a 'textarea' block to a 'pre' CSS style to simulate a block of carefully formatted, monospace styled, coding text.

    Use the 'pre' tag to preserve whitespace, font type, and font size formatting:

            My Bonnie lies over the ocean.
    
            My Bonnie lies over the sea.
    
            My Bonnie lies over the ocean.
    
            Oh, bring back my Bonnie to me.
    

    Use the 'pre' tag with 'code' element together to show off cool computer code exactly as it is typed! Note: I had to "escape" the greater than and less than HTML code below for this to work.

    
        <select name="cars">
            <option value="volvo">Volvo</option>
            <option value="fiat">Fiat</option>
            <option value="audi">Audi</option>
        </select>
    

    As a side trick, I like to use the <textarea> element to hold code samples instead, as shown above, as I don't have to escape any HTML I drop into it. ( I am using this trick in this web page!). This one uses a plain unstyled 'textarea' tag set, but you can add more font styling to it, as needed. Copy the code below to recreate the textarea "code box" shown above:

    
    <textarea spellcheck="false">
      <select name="cars">
        <option value="volvo">Volvo</option>
        <option value="fiat">Fiat</option>
        <option value="audi">Audi</option>
      </select>
    </textarea>
    

    Don't Forget to Add the 'title' Attribute to your HTML Elements

    Most new web developers forget to add important 'title' or "tooltip" attributes to their click-able or important elements. The 'title' attribute acts like a mouse rollover and should be added to every link, image, or multimedia element you create to tell search engines, users, and special parsers what the element does. I even include them on form fields and inputs and buttons in my HTML. Often images are ok with just the 'alt' attribute. But I often add a descriptive value to 'title' attributes on images so users know what the image is about in case 'alt' is not shown. Links need 'title' values as well, so users know where the link goes before it is clicked. I often tell users on rollover where the link goes. You can even add 'title' to special Angular elements that have complex interactive features so on mouseover users know what the feature does and how to interact with it. The 'title' attribute then allows all your page elements to passively help users identify what that element does before it is clicked. 'title' is easily the most underrated HTML feature ever invented!

    Rollover this link to see the Title

    TabIndex and Autofocus in HTML

    You can see the "tabindex=0" attribute added to this html element below. "tabindex=0" assigned to an element adds it to the global index list created by the browser. You can also set specific tabindex values and create your own custom tab order. This is frequently done in form inputs a user fills out in a specific order. Setting "tabindex=1" would start a user at a specific control and works like 'autofocus'. It controls where users go to in a page initially. "tabindex=-1" removes an element from the tabindex set by the browser and is great for removing items from a strict list of form fields that you want a user to follow, while skipping over ones you do not. I add "tabindex=-1" to 'disabled' and 'readonly' input form field types, links, as well as 'reset' or other buttons I don't want data entry people to ever tab onto. Add the "autofocus=autofocus" attribute to immediately take them to a specific item regardless of tabindex. When added you will be taken to the input below immediately and see the blinking cursor in the input below.

    We use "tabindex" numbers to control how users move through large complex forms when hitting the tab key or completing forms. But without these a user will usually follow an order the browser assigns by default. Often, however, without tabindex the browser will tab through other fields, like images that may or may not be interactive. Tabindex allows you to control what is part of that browser tab index. Without 'tabindex' or 'autofocus' you would have to set tabindex on every form item for it to focus on the first one. So use 'autofocus' to start a user on a specific button or field, then add and 'tabindex=0' to all the form fields users can tab naturally through using the tab order set by the browser.

    For complex forms add specific tabindex numerical values to control how they move through your fields. Note that 'autofocus' does shift the user to a specific item in Firefox, Chrome, IE, and Safari, but might not work in older browsers. Important: When using tabindex for input fields it is always best to wrap input fields in a form tag below. This is good practice as you can have multiple form elements per page in all versions of HTML where the tab index might shift. Note: IE 10 and older do not support tabindex values, nor does Opera 10 or older. In old HTML4, the tabindex attribute was only relevant for elements that could receive focus, including 'a', 'button', 'input', 'object', 'select', and 'textarea'. In HTML5, tabindex is available to any element that can receive focus. That is one more reason to consider applying 'tabindex' numeric values explicitly on form fields and buttons rather than trusting the browser to decide using "tabindex=0".

    Below is the code:

    Using CDATA to Make Your HTML XML-Friendly

    Code inside 'style' and 'script' elements has special meaning in HTML and HTML5. Anything added inside those tags is interpreted as "character data", or in XML-language, "CDATA". This means, unlike normal elements, text inside those elements is never parsed as markup. If it did, it could break your website. You could accidentally type something with an ampersand or a left or right bracket as used in HTML tags and it would break!

    Often HTML5 developers don't care if their websites support XML or XHTML. It should work only in HTML5. But there are those of us that love the fact our websites get "as close as possible" to XML and XHTML. Why? Because it means your site is easily copied into many technologies and is easily parsed into XML if you needed that ability. In some cases, XML-friendly markup is parsed faster and more JavaScript-friendly, as well. Some say, well, HTML is "tag soup" anyway, so who cares. Others have shown how ending tags, as XML generates, creates special issues in HTML. I am of the opinion that XML-friendly is always the way to go in your HTML markup design, regardless of those special cases.

    To address these issues in our special 'style' and 'script' elements, you need to realize XML and XHTML browser parsers will NOT see the content in those elements as CDATA by default. You must add CDATA rules to your HTML to make them XML-friendly. Otherwise, anything that contains special HTML markup characters will fail. If you copied your 'style' or 'script' elements into an XHTML page as is, the XML parser would try and interpret your CSS and JavaScript as markup and blow up without the extra CDATA section added. HTML5 already reads the content inside 'style' and 'script' tags as CDATA (character data). You only need to add the CDATA block if you want your HTML5 page to be compatible with XHTML and XML. Otherwise, they read the 'style' and 'script' tag content as markup. Because XML and XHTML parsers reads everything inside elements as potentially more markup, adding CDATA prevents certain characters from being interpreted as XML or other types of character references.

    XML and valid XHTML (application/xhtml+xml) will read the 'style' and 'script' element content as PCDATA, meaning the contents are parsed as markup and potentially break with special characters. The purpose of adding extra CDATA sections isn't to fix anything in HTML but make your pages cross-compatible with XML-related parsers and agents. If you add these new CDATA markers into these tags for XML support, most major HTML5 browsers will fail when they parse those tags as they are already using CDATA rules behind the scenes. So added CDATA blocks have to be commented out for those agents with special "hacks".

    So how do you combine all that so your HTML5 is XML-friendly in 'style' and 'script' elements? And should you care?

    In the early days of HTML, we used to use some very simple techniques in our 'style' and 'script' elements hide code from browsers that did not understand CSS and/or JavaScript. Going back to the 1990's, CSS always allowed you to place HTML comments after the <style> element to hide CSS text from non-CSS browsers (IE 1-2 and Netscape 1-3). So we simply hid code from them using plain HTML comments, like so. Supporting CSS browsers would ignore the comments as these tags read them as CDATA, or plain character text, not HTML, while non-supporting browsers read everything inside them as normal HTML, so understood the HTML comments:

    
    <style type="text/css"> 
        <!--
            body {background: green;}
        -->
    </style>
    

    JavaScript had the same problem. Many browsers, like IE 1-3.01 and Netscape 1-1.4, did not fully support JavaScript (or JScript), so we had to hide scripts for those browsers as well using HTML comments, like so:

    
    <script type="text/javascript"> 
        <!--
            alert('hello world');
        //-->
    </script>
    

    When XHTML1.0 and XML parsing came on the scene after 2001, however, we had a new problem. Because JavaScript could contain some XML reserved characters, like & or < or >, any scripts containing that code would create a validation error in XML parsers, like XHTML. The reason was the same as described above for CSS: These browsers did not consider code inside 'style' and 'script' tags as CDATA, or character data. That means those offending characters were read as HTML, so would blow up in XHTML. To fix this issue in JavaScript, we simply added a CDATA section inside the comments to make sure XHTML could interpret the scripts as JavaScript, just not read the reserved XML characters as HTML:

    
    <script type="text/javascript"> 
        //<!--[CDATA[
            alert('hello world');
        //]]-->
    </script>
    

    You would think this final code fix would solve all our problems. But it has not. It works well in most browsers, but some HTML5 and XHTML5 browsers could misinterpret this code, as could a mix of older browsers and XML parsers with various levels of support for scripts and styles in various combinations. In some cases you needed to hide the code completely from XML parsers, and in others you needed to hide CDATA markers which are redundant in modern browsers who already interpret the tags as CDATA.

    So, what is the best solution today, to address all these problems? I am a purest here and like my HTML5 content to still be XML/XHTML-friendly, regardless of what markup recommendation I am using. I also like my pages to work in browsers that know CSS and older browsers that do not. So I have added two solutions below to support all those scenarios and which will display your styles and scripts in modern browsers without errors. My solution below is something you can safely paste into your 'style' and 'script' tags and keep using CSS and JavaScript exactly as you have before knowing its completely XML-friendly!

    `

    My solution below will do the following:

    • Supports all CSS and JavaScript as normal in newer HTML5 browsers which already read your code as CDATA.
    • Supports XML or XHTML parsers so they wrap CDATA markers around your 'style' and 'script' content. Makes those tags and their code 100% XML-friendly.
    • BONUS: Supports older browsers that do NOT support CSS or JavaScript (c. < 1996) by commenting out your code if the browser does not support CSS or JavaScript comments.

    Notes on Code Below: In HTML5, html comment markers ("<!--" and "-->") are treated like CDATA by default inside style and script elements, so are completely ignored (comment tags do nothing in 'style' and 'script' elements). After ignoring comments and applying CSS and JavaScript comments, the top and bottom lines in the code blocks below are hidden in newer browsers and do not interfere with your CSS or JavaScript code. Some older browsers do not understand CSS or JavaScript code, but do recognize html comment markers. And so, these old browsers comment out all the CSS and JavaScript within the 'style' and 'script' elements below if they fail to know CSS comments (/**/) or JavaScript comments (//). The html commented code blocks are removed and the "<![CDATA[/*>" remains as an empty unknown element to them (unrecognized elements in HTML are always ignored). Finally, XHTML and XML parsers also recognize the html comment markers correctly, but also know the CSS and JavaScript comment codes. The final parsed block wraps a CDATA rule set ("<![CDATA[...]]>") around all styles and script code, applying any CSS or JavaScript comments as normal, then running the remaining uncommented styles or scripts inside the CDATA block as usual.

    Simply paste the two code blocks below into your web page and replace the 'style' and 'script' elements you currently use. This code solution thus solves all three scenarios and will make your HTML page one step closer to being 100% XML-friendly!


    Style Element with New CDATA Section


    Script Element with New CDATA Section

    How to Trigger Javascript Events without Following a Link?

    With JavaScript now dominating the browser world, you may find yourself capturing 'anchor' links or the button's "submit" events in JavaScript, then ignoring the hyperlink or button's URL to the Internet. This is often used to allow user's to press a button or link and have JavaScript process the event or do something with the data before sending it to the server. Maybe you want to record a user clicking a link before you send them away from your website to an outside URL. Maybe you want the "submit" button and the form field data to be parsed, validated, then sent to a REST service using Javascript instead of posting via the browser to the server directly?

    Often this "hijacking" of the form submission by JavaScript is semantically a bad design idea. But you can allow this as long as you account for people that have JavaScript disabled. Those people should be allowed to at least post to the server or come back to the same page or another page with a message if the event fails for them. So, how do you support your JavaScript methods and event capture, but stop users from linking off in the first place. How do you do that but support non-scripting browsers?

    There are actually several tricks you can use to accomplish this strange feat!

    In the case of anchor elements, using "return false;" inside your "onclick" event on the 'a' element allows you to keep the anchor 'href' URL in cases where you want a safe "fallback" hyperlink for browsers that have JavaScript disabled or where scripts are not supported in the user agent (1-5% of user's now). You can use the anchor "#" sign as the value for the 'href' URL, an empty string, or a special URL for the href should your script fail. Note that you must use an 'href' attribute in all cases so screen readers know it is a hyperlink. Removing the 'href' attribute is another option, many say. But removing the 'href' attribute on an 'a' element removes the ability of the element to perform as a hyperlink. So that option is moot here. Without an 'href' on an anchor means the anchor is no longer a hyperlink and just an HTML tag with a click event on it that is captured. Bad idea!

    Below are three examples that will work to allow JavaScript to capture the click event and perform some action, followed by "return false;", which disables the ability of the link to function. JavaScript controls that click event now. If a browser did not support scripting, or a screen reader or other agent for the blind was used, then the script might be disabled but the anchor's 'href' URL still function anyway without destroying the user's experience. In this case, an empty ("") or anchor ("#") would route the user back to the same page. In the case of a special URL added (as I have done below) a hyperlink to process data or explain an error with a message is possible now, should the script fail. In all three versions below, the JavaScript alert box is allowed to fire, then "return false;" disables the hyperlink. But should scripting be disabled, the 'href' hyperlinks below would all fire ok and take the user somewhere by default. This is a nice fallback design that is cross-browser friendly!

    Notice clicking any of the links below pulls up the JavaScript alert box but does not go anywhere after that.


    <a href="" onclick="alert('hello world!');return false;">My Disabled Link</a>
    My Disabled Link

    <a href="#" onclick="alert('hello world!');return false;">My Disabled Link</a>
    My Disabled Link

    <a href="MyFallbackURL.html" onclick="alert('hello world!');return false;">My Disabled Link</a>
    My Disabled Link

    Below is a popular trick used to disable hypertext links using a script. This trick only works when JavaScript is enabled in the browser. A script called "javascript:void(0)" is now added inside the href attribute below. This new script is ignored as a URL address but disables the hypertext link from working. This trick works because JavaScript has hijacked processing of the "href" URL value while returning an empty value. "javascript:" is a pseudo URL command and tells the browser to intercept all code processed after the colon and process it as script rather than as a URL string. This allows you to run various kinds of scripts when a link is clicked rather than routing off to a URL. As you may or may not know, JavaScript functions always return a value. If they have no value they return 'undefined'. "void()" does the same thing but forces an empty script response back to the browser when the link is clicked by the user. So using "void()" allows you to run a script that does nothing, stops all return values from any JavaScript run in the attribute, and disables all page navigation using the link. This makes this trick different from the empty URL's above that still allow the browser to process the href attribute and whatever URL resource that does or does not appear there.


    <a href="javascript:void(0);" onclick="alert('hello world!');">My Disabled Link</a>
    My Disabled Link

    Note: All these tricks can be applied to 'button' and 'input' "submit" type buttons, as well. These tricks do not just disable submission of form data but allow you a safer fallback pattern for older Javascript-disabled browsers to use when scripts do not work and the click events need to be processed naturally by the browser.

    How to Hide HTML5 Elements and Content using CSS

    "Hiding" things in HTML and CSS confuses most developers. There are really three different ways to "hide" or "remove" items in web pages: Remove their "visibility", remove the item visually and physically from the page, and lastly, you can move something off the screen entirely.

    Before talk about hiding things, let us talk briefly about the browser's Document Object Model. When your server sends elements to the browser, its parser and render engine build a tree of elements in memory and then paints them to the browser's web page viewport from its DOM or "Document Object Model" tree. Any element you remove entirely from the HTML you send to the browser is obviously not part of that DOM tree. That is usually the best way to hide anything, right?

    Generally, when a developer says they want to "hide" something they are saying that they do want the HTML elements they sent to the browser to be displayed there and take up space, but just not be visible...temporarily. But that crosses into a gray area. Often, when you hide something, it is part of the DOM tree, just not visible on the screen. In that situation the item takes up space, but is invisible. But there are other times where you want the item to be both invisible and also not exist at all in the page...to not be part of the DOM tree of the browser, temporarily. Lastly, there are times you want the item to be visible and part of the page's tree and structure, just not be available to be seen and accessed on the page by a certain type of user or browser. Let's look at example of how to handle all these different scenarios.

    Below is an example of how to visibly hide something that is still part of the DOM and inside the viewport, normally, and which still takes up space. Often a developer wants to use the item in scripts or to take up space but just wants to hide its visual aspects only. We use 'visibility:hidden' in CSS to do that. Note: We avoided using this element years ago as many older browsers didn't fully support it. It was not supported till IE4. But IE 4-7 still have issues with 'visibility' inheritance such that their child elements are often still shown when you apply "visibility:hidden" to a parent container. However, in modern browsers and IE8+ you will not have those issues, so 'visibility' today is a viable solution. Note that "visibility" is an inherited property unlike "display", so its children can override the parent's setting.


    Using the "visibility:hidden" style on the box below, its inner text exists in the page and the DOM, but is visually hidden. Notice that the outlined box still reserves space for the hidden text, though it is hidden visually. Use this technique to maintain space for the item, but just hide it visually. Also note, if children of the element still wanted to be seen they could override the parent's "hidden" value and still be seen.

    hidden text



    Below is an example of how to both hide something visually but also physically (though often temporarily). This technique removes an item from the painted DOM view completely, so it is hidden visually and physically just like it never existed. Keep in mind when you do this, the item's space in the page is also removed. Use this if you temporarily want to remove an item from the page's DOM tree, completely. We use 'display:none' in CSS to do that. Note: "display:none" is by far the most popular way to "hide" HTML elements and blocks of content. "display:none" has the widest support in even the oldest of browsers going back to Internet Explorer 4! But beware of one bug I found. IE (all versions 1-6) and old Mozilla browsers would download all "hidden images" inside blocks with "display:none" hidden. The correct standard is NOT to download hidden material on these hidden blocks until display changes to any other non-hidden type. Netscape 4 series also did not support "display:none", so we had to use "visibility: hidden" or "visibility: false". So, plan on this weird prospect in some browsers. But otherwise, display:none" takes its block of content, and all its children, out of the DOM. What most developers do not known is it also hides the item by removing it from the painted DOM tree of the web page so it no longer takes up space, as well. It removes it completely from the page. However, the item still exists in the pages unpainted tree, so most scripts can and do still access these types of "removed" items to "unhide" them by setting them to "display:block" or "display:inline" as a toggled item. So, they do exist in the DOM, just not the visual tree format created from it. Note that "display" is not an inherited property unlike "visibility", so its children cannot override the parent's setting.

    WARNING! One of the very scary aspects of the use of "display:none" in form field elements (like 'input') is the fact that any form field with "display:none" is NOT sent to the server when the form is submitted! Keep this in mind when using "display:none" as it is a way of also blocking elements from being sent or parsed by the browser that might normally appear in POST data or read by outside 3rd party applications. That is one reason why "disabled" or "readonly" form field attributes were invented. So keep that in mind. You can control what fields are seen and POSTED better through attributes than showing and removing blocks of content with CSS.


    Using the "display:none" style below, this text and its space no longer exists in the page but is removed completely. Notice the block holding the text is completely collapsed like it never exists. The item has been temporarily removed from the painted DOM tree.

    hidden text



    Finally, below is an example of how to hide something completely from view for all browsers and users, but not affect its visibility or placement in the actual web page or structure of the DOM. This technique simply hides specific elements or blocks of content by moving them far offscreen. We have used this trick to keep an object that a screen reader with no CSS support would need to display at the top of a page for accessibility reasons, but for general public viewing should never see. We often want certain non-visual HTML elements to remain as part of our pages and the DOM, but not take up real state in the page. We often have content we want hidden to suddenly appear for certain types of people. Screen readers used by the blind is one such example. But how do you do that?

    "position:absolute" does just that by moving a block of content out of the "page flow" and offscreen. In the example below the 'template' element is not a feature that should ever appear as a visual element in the page, yet should remain a functional element holding content, if needed. So I often move such elements way offscreen to hide them completely from the user. But I don't want such elements stripped out of the page completely by "display:none". Hiding it through CSS 'visibility' would really not make sense either as its not a visible element in HTML5 browsers, anyway. But older browser could try and fill the page display with its content as they don't know what this new HTML5 <template> element is. So this is a perfect candidate for hiding something through "positioning". Other examples of when to use this technique are accessibility features like "Skip To Content" links at the top of a page you want the blind whose browsers don't read CSS to access but not your other users to ever see in your pages.

    New in HTML5: Finally, something different! I have not used this technique much due to limited IE support. But you can now use the "hidden" HTML5 attribute to hide most elements in your web page now. Adding "hidden" as an attribute to an element means the tag and its content is part of the DOM and source, but is visually hidden from the viewer. It works just like CSS "display:none". Notice I added the XML-compatible version of 'hidden' with a value, as in "hidden='hidden'". "Hidden" appears to have wide support in many browsers today in 2022, including IE11 and Edge browsers. But beware, Internet Explorer 10 and earlier do NOT support the 'hidden' attribute., which might cause problems when hiding critical things they must not ever see. That is why I prefer the CSS options above using "visibility:hidden" and "display:none", which have much wider support in all older and newer browsers alike.


    Using the "hidden" attribute below performs just like "display:none". Notice the box has collapsed when the item is hidden.


    Spell checking in HTML5

    This is one of the "additive" features I enjoy about HTML5, as it simply adds value to your HTML without punishing older browsers who do not have this feature. You can now use the "spellcheck" HTML5 attribute to tell the browser to enable its native spellcheck feature (if one exists) for an element. Adding "spellcheck='true'" as an attribute to an element means the tag and its content is checked for spelling. "Spellcheck" appears to have wide support in many browsers, including IE11 and Edge browsers. However, older browsers would not recognize it. That is why I would use it as an add-on, not as a required feature. If you end up needing mandatory spell checking for input, then consider a JavaScripted solution instead.


    Try typing several words in the input box below. Misspell something in the text and see if your browser supports spell checking. A wavey line should appear under a word which you can right-click to choose an alternate word option from a popup list. This is not generated by a script, add-on, or even HTML. Your browser should come with this feature enabled, naturally. Note: It is rare to use the "spellcheck" attribute on 'input' elements. It is more common to add this attribute on 'textarea'. But I have added the feature below for demonstration purposes only.



    The Mystery of Collapsing Margins in HTML

    Every developer should know how and why margins magically merge between certain elements in HTML. It is not intuitive but important you know how and why margins collapse. The "collapsing margin" has been around since the birth of CSS in the mid-1990's. Its interpretation by browsers has been spotty, however, confusing what should have been a consistent implementation. But the rules for how neighboring margins are merged has always been a confusing topic, even for me. I am still discovering weird things in browsers today that are not consistent. That is why its always helpful to review some basic ideas about margins, as the way they merge and collapse is important in HTML.

    In HTML in the so-called "CSS Box Model", a margin is an invisible boundary you can add to any element so that a space is created between them. This has four directions, top, right, bottom, and left. In CSS you can use the "margin" property to represent the four margin areas: "margin-top", "margin-right", "margin-bottom", and "margin-left", or a shorthand version simply called "margin". (You can Google the types of units and spaces you can create using "margin"). But when combining vertical stacks of elements with margins, in CSS2 they are designed to collapse or "merge" into one unified new margin. Why would they do this?

    The reason is simple: In the early days of the Web, the "web page" was mostly designed to support documents and text displays patterned after published books and journals such that text spacing was simulated in HTML and CSS designs. To do that, combining two blocks of text having upper and lower padding needed to be reduced to match the same spacing of text as paragraphs in books. To do this, "margin collapsing" was invented in CSS.

    In HTML and CSS, the top and bottom margins of blocks are often combined into a single margin whose size is the largest of their individual margins (or just one of them, if they are equal). This is the basis for the behavior known as "margin collapsing". So the bottom of one paragraph text margin or block would be combined with the top of another, the large height winning and used as the default margin between them. The largest margin essentially pulls the smaller margin up into it so it is ignored. This is the basis for how top and bottom margins now combine in HTML and CSS today. Margin collapsing does this combining and collapsing mechanism to prevent repetition. This might seem counter intuitive but its design allows styling of numerous blocks of content without double-spacing between them, instead using single spacing to match how book text might perform naturally in the publishing world.

    Important: Padding and borders on block elements do not collapse ever or follow these rules! They are always honored and NOT combined, as they are always a part of the blocks's total dimensions.

    It turns out margin collapsing rules go a bit deeper than the main rule mentioned above. So, I'm am listing the rules on margin collapsing in HTML below:

    Margin Collapsing Rules

    1. The margins of adjacent siblings with margins always collapse into one shared margin. The largest margin between them is always used.
    2. If a block-level parent and its child elements both have margins, and there is content outside the parent with margins, and there is NO border, padding, or content on the parent (or between the parent and its children), the parent's margins collapse, and the first "margin collapse" rules apply between the parent's children and any outside content. Essentially this means the margins between parent and adjacent "sibling" elements and their content are collapsed into one, the larger winning as before. Otherwise, they are maintained and margin collapse rules apply between parent and outside content as normal. In the former scenario, margins of a child block could end up outside its parent container whether or not the parent's margin is zero or not.
    3. On empty blocks where there is NO border, padding, or content, the first "margin collapse" rule applies and the margins of adjacent "sibling" elements and their content are collapsed into one.
    4. Floats and positioned elements never collapse adjacent margins in HTML.

    Let's now look at some examples...

    In the Rule #1 example below, I am showing two paragraphs without margins and then two with bottom and top margins that collapse. In the second part, the bottom of the top paragraph's margin has merged with the top margin of the second one. The margins collapse and the largest margin is used. In the nested examples below, the 'div' parent block holds child paragraphs which have top and bottom margins, as does the parent "div". These all would merge with top and bottom paragraphs outside the "div" parent normally, except the 'div' wrapper contains a border in the first instance, applying rule #2 above. We could have added text or a padding as well on the "div" to trigger the exact same scenario where its margins are honored. In the second example, because the "div" has no border or content, the child paragraphs push outside this parent and merge with the outer two top and bottom paragraphs and form one unified margin between them. Note that borders on paragraphs don't affect merging of margins as they don't have child elements with margins in this test.

    Two paragraphs with NO margins are shown below...

    The bottom margin of this paragraph is collapsed with the one below to form a single shared margin of 1em.

    The top margin of this paragraph is collapsed with the one above to form a single shared margin of 1em.


    Now, let's add margins to our paragraphs...

    The bottom margin of this paragraph is larger (2em) than the one below so it "wins" and is used as the shared margin between the two.

    The top margin of this paragraph with a 1em margin is collapsed with the one above to form a single shared margin of 2em.

    Below is the code for the example above...

    <p style="margin:0em 0em 2em 0em;background-color:green;">The bottom margin of this paragraph is larger (2em) than the one below so it "wins" and is used as the shared margin between the two.</p>
    <p style="margin: 1em 0em 0em 0em;background-color:lightblue;">The top margin of this paragraph with a 1em margin is collapsed with the one above to form a single shared margin of 2em.</p>

    Nested Margin Test: Now let's test Rule #2 above and how paragraphs with margins act inside a parent 'div' also with margins. Below, notice a "div" parent with child paragraphs has a blue border (plus margins). Based on Rule #2 above, because of this blue border, the margins of its children do not collapse with the outside paragraph's margin, but are maintained inside. The div's outer margin is still merged with the top and bottom outer paragraph margins, as normal. But its child paragraphs retain their own margins internally. The rules for collapsing margins say this blue border triggers margins to NOT collapse between the parent "div", its children, and any outside paragraphs. Only the div's margins have collapsed with the two outside paragraphs margins.

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text


    Another Nested Margin Test: Now let's remove the blue border and see how margin's collapse between the outside paragraphs, the div, and its inside paragraphs. Below, notice the "div" parent has NO border or content, even though it has margins. Its own margins have now collapsed to zero. The margins of its children are then merged with the outer paragraphs around its parent "div" so they now all stack with even margins. Margins have all merged. This shows how the "published text model" dominates how margins perform in HTML and why you must be aware of how and why this happens as you design content in HTML.

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text

    text text text text text text text text text text text text text text text text text text text text text text text

    The reason this strange "margin collapsing" feature of HTML works this way is simple: HTML is trying to use margins to make text look like it does in old books. HTML does this by controlling how text paragraphs space lines of text, and with empty spaces between text, it has to assume the reader does not want to see extra spaces or margins between them. Now you know how and why HTML margins perform the way they do!

    Why Do my Web Pages Take So Long To Download?

    As quoted from Mozilla (https://developer.mozilla.org)...

    Between 2011 and 2019, the median resource weight increased from ~100KB to ~400KB for desktop and ~50KB to ~350KB for mobile. While Image size has increased from ~250KB to ~900KB on desktop and ~100KB to ~850KB on mobile.

    Why is that? The two reason are BLOATED JavaScript API's and new developers not understanding how to compress huge images they create for websites. The bottleneck slowing web page rendering is not "blocking" files like CSS, because most browser only allow 6 parallel connections to the server, anyway. The blocking mechanism is rise the past 10 years in HUGE SCRIPTING LIBRARIES AND IMAGE FILE SIZES!

    We learned how to compress images like gif's using "Web Safe" 216 color palettes (created by Netscape) and LOSSY photo compress by image programs like Adobe's "ImageReady" 20 years ago. Developers today have completely forgotten how to do that. So instead, they've created bloated JavaScript and huge images that are never compressed or ever use reduced image palettes. It is sad we have failed to mentor the tech youth of today as the Internet has gone backwards by about 10-15 years as a result. Imagine how fast the Web would run today if the millions of images used today were coreectly compressed? Besides, bandwidth costs big bucks!

    Also, most phones and new monitors have "HD resolution", which means the dot per inch is no longer 72 dpi on macs, or 96 dpi on Windows, as in the old days. Resolutions are not approaching 500 ppi (pixels per inch) on many mobile phones. Because web image now look tinier and tinier on these devices, the manufacturers have come up with their own "pixel" called a "device pixel" which is some percentage of the CSS or browser pixel. This ranges from 1:2 to 1:4, which means they take whatever image dimensions in pixels you set in your style sheets and recalculate it to larger numbers on their devices and screens so your image fits correctly. In addition, many users increase font sizes or zoom, the latter which increases pixel sizes yet again. The end result is, you often have to create multiple images.....one set for traditional desktops and another for these high resolution screen, like we see on iPhones today.

    FILE DOWNLOADS THAT "BLOCK" ARE NOT A PROBLEM: Many developers today online are wasting huge amounts of time doing "pre-loading" of modules, preprocessing CSS, minimizing, creating scripted external file blocking tricks, compressing CSS and scripts, and using asynchronous calls to the server to try and squeeze out milliseconds of download time, when HUGE JavaScript payloads is the still the central problem in slow web pages in modern web pages today! Until they remove these inflated scripting libraries they shove into the browser (1.5 Megabytes of JavaScript on average with this new API's according to the Web Dictionary), nothing will improve. Until they realize sending 3 megabytes of scripts is wasteful and unnecessary when displaying a few lines of text for a reader to consume, nothing will improve in their web page delays and designs online.

    Lastly, you want to consider using the new media image and video formats in HTML5 for those new browsers that support them and regular images for everyone else. The new "WebP" media type for images, for example, use a superior compression algorithm to assist in giving users faster image download times. The one issue is that older browsers won't know these new types. But the new "image" architecture I describe in this tutorial works well with fallback image designs using the new 'picture' element to help old and new browsers pick the type they recognize.

    I better way to help you is to offer a new paradigm shift AWAY from Angular and React and BACK to lite-client architectures. This means going back 20 years to the ORIGINAL server-based web architecture we used to have, which they abandoned. Mobile phones really need this simpler server-based architecture anyway, and would benefit from the tinier downloads of scripts and images sent to them. So without going into details, if you want to increase the speed of all your web applications, my recommendations are:

    1. REMOVE all JavaScript/ECMAScript API's and Frameworks from your web application architecture UNLESS its an internal web project only that is customized for internal workers. This will drastically reduce the average 1-5 Megabytes these gigantic JavaScript API's create. Stay with JQuery but remove Angular, React, Node, Modernizr and many others. That will shave off several Megabytes of code alone shoved into the user's browsers.
    2. COMPRESS all images. There are too many applications to list that will help you do this. I like Adobe's products as they've been around for over 30 years! They are the experts. Also, understand the different between an image;s resolution, the pixel dimensions you give it in CSS, and its physical dimensions. You don't need to create a gigantic 12 inch by 12 inch image at 300 dpi, if you will resize it to 50 pixels by 50 pixels and its displayed on a desktop browser with 96 dpi resolution.
    3. Use smaller script payloads like JQuery for form validation only, and avoid larger, 3rd party, ECMAScript downloads.
    4. Use my recommended, clean, XML-compatible HTML5 listed in this article.
    5. Move video to streaming services, iframes, or embedded format. You can also set "preload=metadata" to delay video. Also, try and stay away from "on-demand" or video you download from your server. That is never a true stream over a protocol, but a lazy form of streaming over HTTP, downloads to the users device, and is often poorly negotiated by the video player using the user's available bandwidth.
    6. Stay away from all animations, Flash, or 3rd party products.
    7. Stay away Modernizr, SASS, LESS, Polyfills, or anything that adds extra steps, extra compression, extra work, and extra software, as it not only adds extra development times but more dependencies and issues in browsers. The so-called time savings offered by these products is minimal compared to the huge JavaScript libraries required to run them or install them in the client. Example, if your CSS is only 20 kilobytes, but your JavaScript libraries are 5 megabytes, why waste time minimizing CSS or worrying about blocking file downloads caused by CSS links when your scripts are what is delaying page rendering. Even using lazy loading, preloading, and other tricks like Google Angular tries to do will not make up for the load times and delays in rendering the DOM or other media. Its a waste of bandwidth!

    How to Control Floats in HTML Pages

    Floating blocks (using a simple CSS property on a 'div' element like so: div.myclass {float: left;}) was and still is a common way to create what are called "flexible layouts" (so-called "responsive" web page design). In a "floating layout" technique, 'div' blocks with content are assigned the CSS float property and allowed to stack horizontally next to each other as the browser's window width increases. Below is a simple example of a floating layout:

    my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content

    my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content

    my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content

    Honestly, we started building these types of floating and non-floating layouts almost two decades ago (c. 2000) and never considered them anything special. Browsers starting with Internet Explorer 4 supported floats and allowed us to start using them to build powerful layout designs. But floats remained buggy for years after that, including in Netscape 4, IE 4-6, Mozilla 5, and Opera 3. To address these issues, we designed cross-browser CSS sheets that addressed all these issues, including IE6 and its quirksmode and standard versions.

    But those tricks were then lost but to be "re-discovered" by the new generation today who seem to have made it harder on themselves by not learning from the past. There is nothing new here to learn in articles online about floating layouts and "hacks" to control them but a reinvention of the same wheel built 20 years prior. But let's talk about all of those solutions and the original problem with floats again, as well as "flexible layouts", in general. I promise to give you a nice, rich set of choices on how to use and end floating layouts correctly that you can easily cut-and-paste into your web projects.

    Despite the promise of flex and grids, those new CSS-driven techniques are still not fully supported by many browsers, even now in 2022. This still means "floating layouts" will be around for many years. But I will discuss flex and grids elsewhere in this page to give you a full set of options when laying out your web pages, as I do like the newer alternatives.

    Floating "divs" as a layout technique is still a viable way to design web pages in HTML. If you choose to use floats (or a 3rd party product like Bootstrap's float-based layouts) keep in mind that a floating block's major purpose was by design to float images over multiple stacked text blocks in a "book page design". Floats were never intended for web page layouts. The floated items (often images) were created to stack up and over text blocks so the text under them could flow around them like traditional book designs do. This had been the norm for book design in the Western World for hundreds of years, btw. Web designers did not invent this. This idea of using floating blocks for images and text was a good idea initially, but meant the parent block-level element that held floats would have to collapse to zero height so text blocks could move up and under floats without gaps. Unfortunately, in using floats for layout structures that idea meant it was difficult to "end" a float set when the floated layout ended and a non-float followed after it. That is the problem you see below. The white content box actually sits in a separate parent 'div' from the one wrapped around the two floating ones. It should start on its own line as a block-level element, but it doesn't.

    my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content

    my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content my content

    Why am I floating up here???




    To fix this problem, web designers after 2001 started looking for ways to extend the parent element around the floats and contain them so when the parent ended a new block of content, free of floats, could begin. Keep in mind this is using floats in a non-traditional way. Floating content was never meant to manage exotic layouts in the first place. They were simply our next best option besides tables, which after 2000 most designers decided would never be semantically correct for layouts. Tables are used for tabular data, not layouts. So tables were abandoned long ago as layout tools. (That is why it is odd to see some young developers today returning to using tables to control layouts in 2022. We stopped doing that 20 years ago!)

    These bizarre issues surrounding floats created HUGE cross-browser bugs and struggles in browsers of the past using flexible layouts (i.e. Internet Explorer 6). To fix this issue, most HTML designers either added "clear:both" to a lone "clearing div" at the bottom of the float or wrapped the float blocks in a parent that had certain styles that both contained and ended the parent container correctly. I have articulated various solutions below so you can try them all. There are many more you can Google that designers have created that also work. Browser support for these tricks vary, however, so be sure to test.

    The floating layout examples below use colored boxes that sit side by side and stretch as the width of the browser changes (try it). This is a common layout structure. But notice the boxes below are contained inside a parent "div" that wraps around their changing dimensions (gray background) that has collapsed. This is generally what is expected for floats, initially, as the parent was designed to hold an unlimited set of text blocks and floating images inside that allowed text to move around them. In the old days of using floats for layouts, we debated whether such a container that wrapped around these floating objects for the sake of layout was even semantically valid. We resolved that by simply giving these "div" containers an 'id' attribute with a name like "wrapper" or "shell" so we knew what their strange structures represented. (So if you see those names in older website code, now you know why they exist.) Their purpose was simply to "wrap" around or contain floating layouts in older browsers for layout purposes only. That technique is still used today.

    Wrapping floats in a parent container that ends the "float box" correctly allows them to move safely within a block-level element without overflowing into the content below. The examples that follow below fix this issue by ending the float and applying various CSS styles to the parent 'div' element that wraps around them and encapsulates them.


    Below is a float whose parent does NOT contain them but the 'p' block-level element after them has used a simple "clear:both" style to start itself AFTER the floated block and end the floating problem. This still does not extend the gray wrapper parent 'div' around it's floating children, however. That remains the problem:

    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

    This text now starts after the floats correctly on a new line because this text's 'p' element uses "style=clear:both" to clear everything before and after it.



    The second and third fixes below finally solve the issue completely by putting CSS styles directly on the float container that forces the parent's box to wrap around its floating children and end the float. Look at how the gray parent box wraps correctly around its floating children. These have various levels of older browser support but work reliably in newer browsers. The last solution is my favorite and uses a "clearing div". It works 100% of the time in all browsers, old and new, and doesn't rely on any CSS "hacks". Its one disadvantage is you must manually drop in a line of HTML at the end of your float box.


    Below is a float whose parent correctly contains its child floating blocks by using "overflow:auto" on its style, which now allows the parent to wrap around its child floats and non-float content. Note that "overflow" doesn't work in some browsers, or is very buggy. These problems still exist in IE 1-6, Mozilla 1-5, Netscape 4,and Opera 1-3.6. All later browsers recognize it, however. But using this property could create a scrollbar every time in these older browsers when using "overflow:auto". So be careful!

    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

    This text now starts outside the floats correctly because the float parent above has wrapped itself correctly around its child floats and ended the float block using "overflow:auto".



    Below is a float whose parent does contain its child floating blocks by using a special CSS "hack" class on its style, which now allows it to wrap around its child floats and non-float content to begin after it. This solution relies on a couple special CSS2 ":after" and "content:" tricks that work in nearly all modern browsers. However, its weakness is some older browsers will not support it, including Internet Explorer 1-5, Opera 1-3.6, and others as they do not support those newer CSS rules This trick may have minor issues like spacing problems after the floats in a few browsers like Opera version 1-6 and old Firefox 3.5, as well. (I have not tested it recently in those versions) Note: You will see a version of this ":after" clearing fix in most websites today (2022). Use this for a CSS-only fix that is guaranteed to cover over most browsers out there today, understanding that older Internet Explorer browser will not support this CSS.

    This "hack" relies on the following CSS class and "hack":

    <style>
      .clearfix:after {
      display: block;
      height: 0;
      clear: both;
      visibility: hidden;
      content: " ";/* place this last in case it blows up in non-supporting browsers like IE3-5 */
      }
      .clearfix {
      *height: 1%;/* only IE 7 or less see this */
      }
    </style>

    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

    This text now starts outside the floats correctly because the float parent above has wrapped itself correctly around its child floats and ended the float block using the CSS pseudo-class ":after" hack mentioned above.



    My Favorite Float Clearing Solution

    Below is my favorite solution for clearing floats simply because it is so reliable. This is a very old clearing trick that has the advantage that it works in all old and new browsers going back to the 1990's including browsers built today. It ends the float reliably and consistently using a simple "clearing div" element at the bottom with very simple CSS styles applied. I like to create a small CSS class for this and apply it to the clearing div below. In the past I have used "clearing divs" reliably like this, which even worked in old IE5.5, 6, and IE5 for Macs. Despite the added HTML element, this is generally a superior solution as it works so well and doesn't require complicated ":after" pseudo-elements or CSS hacks, which some browser don't recognize. This version also gives the HTML web page builder complete control of when to end the block.

    Internet Explorer Bugs: IE5 needs a style of "clear:both" on the "clearing div" below. If you add any other styles they trigger "hasLayout" in IE which gives the div dimensions and creates an extra vertical space at the bottom. This you cannot remove if you use any other style. IE7 conflicts with IE5 here as it has dimensions but needs a value like "height:0" added to its styles so its dimension collapses. But adding this value triggers "hasLayout" again in IE5, creating a space in its clearing div again. The solution is adding a simple HTML comment between the clearing div tags which triggers the "div" space to collapse after the floats in IE7, but does not affect IE5. Result? Both collapse now after the floats, as expected.

    * Note: As reliable as this solution is, modern developers have two criticisms of it: First, it is not semantic, meaning the tiny "div" element used adds unnecessary HTML that has no purpose. That is true, but not a big issue, as the 'div' is hidden visually and has no content. Notice I have also given it an ARIA role of "none" so screen readers will ignore it completely. Second, they say its cumbersome to implement as now requires you paste HTML into your page versus a CSS fix that is easier to manage. That is also true, except the odd fact you had to manually add floating 'divs' to create your layout in the first place, so why not add one more? The ":after" pseudo-element actually adds non-semantic empty content (a space) to the HTML DOM tree, anyway! My argument in preferring to use the old-fashioned "clearing div" here is the fact it is so reliable and requires no CSS on the parent element. You will never have a browser fail to implement it. It also does not pollute your CSS with convoluted CSS "hacks". But in the end, I say, "pick your poison!"


    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

    This text now starts outside the floats correctly because the float parent contains the clearing element using a simple "div" element with simple clearing styles applied.


    Now for Something New in HTML5!

    Good news! There is a new float feature called "display:flow-root" that solves all our float problems in 2022! Meaning: You don’t have to use clearfix hacks! Just add this CSS property to a class on the parent element that contains your floats and it will clear them at the end for you! The bad news it isn't widely supported by browsers yet :( But I thought I would add this if you plan to start using this new CSS property. My recommendation is you use BOTH this new property on your float parent element AND keep using your float clearing solution as before. Eventually your property will be supported and you can safely remove any CSS "hacks" or your clearing div from your HTML. Meaning: You don’t have to use clearfix hacks once its supported. Keep in mind that browser support is still dismal. Below are the browsers that still do NOT support this property. Basically, only the newest browsers minus Internet Explorer support its use.

    Non-support of the new CSS parent float property "display:flow-root" in modern browsers is as follows:

    • NO support in any browser created prior to 2017
    • NO IE1-11 support
    • NO early Trident Edge, Opera Mini, UC Android, Baido, or KaiOS browser support
    • NO Chrome 57 or less support
    • NO Firefox 52 or less support
    • NO Safari 12 or less support

    Warning: For now, always combine this new CSS property fix with older "clearing fixes" because lack of browser support.


    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

    If your browser supports "display:flow-root" this text lies outside the floats correctly. This new feature as mentioned has limited browser support in 2022, however.


    My point here is not to argue for a specific float clearing solution, or condemn this solution or that, but give you the options with their true flaws and benefits and you choose what works best for you. This more comprehensive example has helped me to see how and why floats do what they do and how to end them correctly when using the non-traditional floating layout.

    The New 'data-' HTML5 Attribute

    The new 'data-' attribute in HTML5 is a powerful way to store text values inside attributes in any HTML element in your web page. They are essentially custom attributes you can name and use as you like! You can then add text values or "data" to them without worrying how the browser will interpret them or change your elements. They will not. So why use them?

    To use them in an HTML element simply prefix your attribute with the word 'data-' followed by whatever text string you like (<img data-how-does-my-cat-feel="My Cat Loves Me!" />). You can create multiple attributes of custom data on a single attribute. The 'data-' attribute is then used to store this custom data inside your HTML elements separate from the server. It is also private to the web page or application. They are ignored by browsers and do not change your elements design or function, but available for screen readers when they interpret the meaning of elements blind people cannot see. They also are a powerful way to store custom data associated with HTML and cache data used by JavaScript or other applications running in the page. You may see this technique is often used by Razer and Angular frameworks to tell scripts what to do with various elements separate from its content, toggle visual elements on and off, manage large tables of changing data, etc.

    In the past we often used "id" for this technique, but it was not enough. The data stored this way using this new attribute can now be used to control visual design data, properties of the element, raw database information, or be used to temporarily store data in your page you change on the fly that is helpful when a database is not available. Below is an example of how to use multiple "data-" attributes this way. But always keep in mind, you can create any text-named attributes you like using 'data-' on any HTML element as long as you precede your attribute name with the "data-" prefix. Also, the attribute name should not contain any uppercase letters and must be at least one character long after the prefix "data-". Otherwise, the 'data-' attribute value can be any string you like, even hyphenated ones.

    Note: As mentioned, most new and old web browsers ignore element attributes with "data-" as a prefix. So, these are very safe to use and easily accessible via JavaScript. It is one more reason to always use 'id' attributes (as I have mentioned) to uniquely identify important web page elements with data. The one bug in using 'data-' is the fact they will not be XHTML-compliant in some user agents and could prevent page validation using XHTML. But we are in HTML5, right? So for now, I recommend you still use them.

    This text has many data attributes assigned to it that a script could manipulate or use to change the design, columns of data, etc.

    The New WAI-ARIA HTML5 Accessibility Attributes

    The new WAI-ARIA recommendations in 2022 require semantic information about widgets, structures, and behaviors be assigned to HTML elements in order to allow assistive technologies to convey appropriate information to persons with disabilities. ARIA ('Accessible Rich Internet Applications') attributes add the semantics to HTML5 elements needed to bring a modern website up to assistive and accessibility standards.

    Unfortunately, many of the new HEAVY client-side technologies kids today are building - thick JavaScript API's like Angular or React - have damaged accessibility for screen readers and other user agents that help the blind read web content. Due to manipulation of the DOM by scripts with non-conforming HTML or dynamic HTML updates, these API's create pages that are not seen by many readers.

    To address these problems the "WAI-ARIA" accessibility standards were created to allow web designers the ability to add attributes to HTML5 elements and give alternative user agents like screen readers more information. For example, you can add "aria-" and "role" attributes to elements that tell screen readers what elements do, their roles, their states, or when a live scripted update has occurred. However, that will not fix the damage done to the web using these heavy client-side technologies, in my opinion. ARIA has merely put a band-aid on the problem.

    I have included a sample of elements with roles and aria attributes listed below to get you started. As of 2022, support for these various attributes varies by user agent. You should be able to safely add them to your HTML, however, knowing they will NOT affect you normal web page views on phones and on desktop browsers.

    These ARIA attributes come in two main "types": "role" and "aria-". The 'role' attribute must fit a specific WAI-ARIA text string. "aria-" is used for accessibility and must also fit a specific WAI-ARIA text string type following by a supported value. The 'aria-' attribute itself comes in two sub-types: Property type that is unchanging and State which changes based on user interaction. I will not cover those in detail here, simply because support by screen readers is so variable at the moment. But I will give you some solid examples of how I use ARIA and how to apply basic ARIA attributes to your HTML. You can Google them for more information online.

    Here is a sample of major structural "Landmark Roles" you can apply to your structural layout HTML. They are predefined already in most browsers for the new HTML5 tags. That means when you use those new HTML5 elements, they imply these 'roles', so are optional. That is how ARIA really works...in most cases a screen reader will deduce your HTML and its content and purpose as long as you follow traditional HTML tag use. The farther you stray from that the more important use of 'role' and 'aria-' become! However, I feel its good practice to use them anyway.

    HTML5 Landmark Roles You Can Use
    HTML Landmark Role HTML5 Element They Represent
    role="banner" <header>
    role="complementary" <aside>
    role="contentinfo" <footer>

    These attributes listed above become available for screen readers when they interpret the meaning of elements and read the attributes and their values. Most modern web browsers will ignore them. Note: The 'aria-' and 'role' attributes are supported in 80-90% of browsers in 2022. You do no not add ARIA "role" attribute for many HTML elements, now, like 'input' that uses "text" type, 'img', etc. as most screen readers deduce the correct role, anyway. The idea is not to fill your pages with every HTML element defined in ARIA, but to fill in non-traditional HTML with assistive attributes. Below are some examples to demonstrate that.


    Menus using ARIA

    Here is a primitive navigation menu decorated with ARIA attributes to assist screen readers. Note the use of "menu" and "menuitem" here. Note: We do not add role="navigation" to the "nav" element as it is redundant and most readers will identify the "nav" element as "navigation".


    Form Control Elements using ARIA

    Here is an example of how I use ARIA in some sample form input elements. Most screen readers will discover the correct meaning of your inputs naturally. The 'form' element, or the 'input' element with "checkbox", "radio", or "text" for 'type' will be known by most screen readers, so do not really need ARIA roles. Use of newer HTML5 custom input types, however, might not be known, so need extra help. All button elements default to a "submit" button type when the 'type' attribute is left off so must be conveyed to screen readers as buttons using ARIA. Custom "state" ARIA is optional on form controls (example "aria-pressed" or aria-checked="true") should be updated by JavaScript if used. The only other 'input' element "types" I may add roles for in practice are custom element 'input' 'types' like "email", "password", "number", "search", etc., or 'button' and 'input' elements that use 'types for "reset", "image", or "file". The latter might not be described as buttons and confuse a reader when engaged. Below I've gone ahead and added full ARIA attributes to the form control elements below so you can see how that is done.

    Form Fields





    Images using ARIA

    Images are especially problematic for the blind. Most designers that correctly apply 'alt', 'title', and captions on web page images naturally assist screen readers interpret images correctly. Adding ARIA attributes just makes sure your images are fully expressed in many types of screen readers. An ARIA role isn't always needed on the elements below, however, as both 'figure' and 'img' elements are self-describing to most readers. Note that here, 'aria-labelledby' tells the viewer that the figure's text label is provided by the text in 'figcaption'. This is helpful in simplifying what a screen reader needs in describing the image and the elements that are associated with it.

    image:National Weather Map
    An oldNOAA 2004 Weather Map!

    Below is a good example of what you must supply to screen readers if you use "non-traditional" image wrappers and descriptions. Here the 'div' element and 'p' element have created a custom caption that visually looks close to the previous example. But in this case the designer needs a very long text description of the image that goes beyond what an image caption supplies. In that scenario the 'div' and 'p' elements are alien to the screen reader. So you need to associate them to the image, logically, using a full ARIA role and label setting to assist a screen reader that otherwise might not associate the image with those HTML elements

    image:National Weather Map

    Larger description of my image and why I posted such an old weather image. Maybe I need to see what weather was happening in 2004?



    HTML Structures with ARIA

    One of the BEST places to use ARIA in assisting screen readers is in your HTML layout structure (the top-level HTML that organizes your web page). This is how I designed this page, in fact. Review the code below and check out how I have given the main structures of my web page an 'id', a 'role', and an ARIA label. I have also connected my 'section' of content to the 'region' role and then assigned its label to the 'h1' heading element. This allows a screen reader to quickly identify the page's main content and get right to your content quickly. It also makes your HTML layout structure easily identifiable by JavaScript API's and more easily manipulated, if needed. As mentioned, most readers will derive the correct 'role' of your HTML from these new HTML5 element names, like 'header', so are often redundant.by I like to use them in case an older HTML4 screen reader still struggles with my content.


    HTML Links and Live Data using ARIA

    Most HTML anchor elements in your web page are identifiable by screen readers based on their element type so do not need roles. Anchors are one example. If you use any non-traditional element as a link then it does need the "role=link". The anchor element 'a' always implies that semantically.

    In general, I do not yet use the new ARIA "state" types like 'aria-live'. Many of these attributes are still not fully supported in screen readers. Others require immediate JavaScript updates to the 'aria-' attributes you add so screen readers see what has changed as the scripts manipulate the HTML and DOM dynamically. If you are using heavy JavaScript API's, like Angular, for example, then identifying much of your content as "live" as you change those areas on-the-fly is critical to screen readers. In those cases you might need to design and build a dynamic "ARIA state service" to apply ARIA "state" to HTML elements as you download and change the data. Below is just a starter example of what a "live" ARIA attribute set might look like. The rabbit hole goes much deeper from there!


    Link Example #1: This link does not need an ARIA role

    Link Example #2: Note: This button actually links to a web page. So it does need an ARIA role as it is not a typical hyperlink element.


    Changes to dynamic content by JavaScript needs to convey that to screen readers on a block-level and atomic level. Using 'aria-live' helps. 'aria-atomic' tells the screen reader to only update the element if something has changed inside it, not the larger parent block that contains it.

    A Random quote: JavaScript might insert live data here using an XMLHTTPRequest request call. But the screen reader would not know it has been updated unless its flagged as a "live" content element.




    "Best Practices" Using ARIA Attributes in 2022

    As mentioned, support for ARIA is still evolving today, so use ARIA attributes sparingly unless you are targeting and testing your website in a live screen reader of your choice. I am certain in that case your ARIA attribute designs will radically change and need to be beefed up. But my suggestions above will at least start you down the path of making your site ARIA-friendly. Below are a few "Best Practices" to follow when using ARIA.

    Many new HTML5 elements such as 'nav', 'article', 'main', and others have default implicit ARIA roles assigned and so do not always need explicit identifying attributes (like role="article", for example). So adding "roles" to those elements is optional. But this rule also applies to most HTML you use. A good screen reader will know what you intended by the HTML choices you make. The problem is many developers do not always follow standard HTML "Best Practices" or element design, so in many cases, adding ARIA is important. This goes back to why I recommend clean and fully attributed HTML that is XML-compatible. I still add ARIA to all my top-level HTML elements and then "sprinkle" additional attributes in child elements where I feel it might help. The exception is "aria-label" and "aria-labelledby" which really are useful in telling a reader what your element does or contains. But do not overdo that. Keep the text in those labels short and sweet!

    Use the ARIA "role=group" attribute for any generic element that wraps around a series of children that are all related but where the element and its content will not need to be indexed by the reader as part of its critical text content. For example, a 'div' element that holds a series of links or images would be a good choice for 'role=group'. 'group' tells readers not to index that content and that the grouped media is part of a "user interface object", not as text content. So the defined blocks will generally not be added to a "Table of Contents" a screen reader generates about your pages. So be cautious in what is defined as a 'group' role.

    Use "aria-label" to give a textual description of what the element's content says or represents. But limit labels to major structural features, buttons, text blocks, menus, and links only, when possible.

    Use "role=presentation" for any structural 'div' or element in your HTML that represents "layout", design, or presentation only. This tells screen readers to ignore large blocks of images, headers, designs, and other features in your web page that are only there to form a layout or visual design element in your web page.

    Because images and other elements are usually self-identified as such in screen readers, you do not need to assign images the ARIA "role=img" or "aria-label". The 'alt' and 'title' attributes, plus the 'figcaption' element, when used, will give screen readers all the information they need about your images.

    Avoid "implied" ARIA roles on MOST HTML5 elements as most are implied by the tag. Example: ARIA and screen readers know a 'tr' is a table row, as they do 'video' is a movie, etc. This means most HTML elements will have NO ARIA role applied. Those that do, usually are needed to describe a generic HTML element like 'a'. 'li', or 'div' that is holds special data or performs like a table, link, menu, or other feature and so need "role=menuitem", etc. to help screen readers identify their purpose beyond their ARIA generic or "none" element role.

    You should still avoid dynamically creating JavaScripted custom HTML or objects that have no real semantic meaning or content value. If you are creating your HTML dynamically be sure you decorate them with ARIA attributes so they give readers some understanding of what they do and why they suddenly appeared.

    How to Display Images in HTML

    It is important you style images correctly! Images, or 'img' elements, are actually "replaced" or embedded content in the browser window, meaning they are not connected to HTML but added as controls into the page by the browser (often from image controls connected to the operating system). For that reason, like 'select', the 'file' input type, and 'textarea' elements, they cannot always be styled by CSS. In older browsers, controlling images in an 'img' tag was sometimes difficult. However, 'img' elements have over the years been more "stylable" than say the 'select' replaced element in browsers.

    There are several tricks you should always remember when designing images. Let's cover them now.

    Image 'width' and 'height' Attributes: Today in 2022, most designers now set "width" and "height" on an image using CSS style sheets, not using HTML attributes on the 'img' tag. In the old days, we did the opposite and always added width and height using the 'img' element's natural width/height attributes. We often scaled those values up or down numerically in size as needed. This then precluded the need for CSS to change those values. The browsers back then would then honor and interpret those attributes values exactly as is and resize the image accordingly.

    <img src="myimage.jpg" alt="image:My Image" title="my cool image" width="250" height="100" /

    Today, with HTML5, that width/height HTMl 'img' attribute design has changed and in a subtle way most web developers fail to understand. Adding CSS image size overrules 'img' attributes as they have always done, such that 'width' and 'height' image attributes were always considered fallback sizes. In HTML5, however, image element 'width' and 'height' attributes are not interpreted that way in modern browsers. Prior to HTML5, image 'width' and 'height' attributes were used to define both the space for the image in the design and the actual width and height of the image. HTML5's current working group then came out and said, "The dimension attributes are not intended to be used to stretch the image". This then changed how width and height would be interpreted in browsers today.

    It turns out that you must still use the 'width' and 'height' 'img' attributes to define the placeholder for the image in your HTML block, but now must use CSS to control the images final width and height. If you do not use either, the browsers will still try and figure out the right dimensions or actual size of the image, but often will pull the images native width and height to calculate an 'aspect ratio'. One of the "weird" aspects of this shift is that you cannot always "stretch" a image larger or smaller from its true size using width and height attributes, as before, as such 'img' attributes are now "hints" in HTML5 as to what the interpreted final width and height of the image will be, not concrete values to be honored. The browsers now use your 'img' values, the CSS values, and the actual image's dimensions to "calculate" its final dimensions, then creates a style representing this value. It does not honor your 'img' attribute sizes. I will now show you proof of this below:

    HTML5 Does Not Honor the Image Element Attributes 'width' and 'height': Below I have added an image with its 'width' and 'height' attributes "resized" to a custom value of 510 x 400 pixels, twice the actual size of the image which is really 255 x 200. I have also added a JavaScript popup alert box so you can see what value the script actually pulls for the image's width value. In addition, I have added a class that clears out the styles on the image using all:revert to see if the script pulls the same width and height even after clearing any custom styles applied.

    Here is the HTML I created for the image below. Notice, I set its custom 'width' and 'height' and added a simple JavaScript trick to pull its width from the image element. Now, click image to get the width!

    <img id="imageresized" src="www.jpg" width="510" height="400" alt="" onclick="JavaScript: alert(this.width);" />

    Why is the 'width' on the image '255' when my width attribute says '510'! Why does JavaScript report it is changed to '255'? The reason is the HTML5 browsers ignore your dimensions now and "calculate" the dimensions it thinks you want! These dimensions are from the actual images width and height, not the larger ones you added to the 'img' tag.

    What is worse, all Internet Explorer browsers (IE1-11) will honor your original attribute dimensions and 'width' will be "510" in those browsers, the value you expect. Again, this shift is from HTML standards groups who have shifted the meaning of image attributes, calculated aspect-ratios, and their affect on final image dimensions.


    In this case, erasing the styles on the image using "all:revert" erased the "calculated" styles the browser first made. It then recalculated the dimensions again using the actual image dimensions, not the custom ones you originally told it to use on the 'img' tag. What's happened is the new HTML5 standards have asked vendors to no longer honor the width and height attributes, but "calculate" the new width and height based on "hints" to get an aspect-ratio and then create width and height in CSS in memory from that calculation. In other words, the 'width' and 'height' attributes should be used to describe the source file, not how you the designer want it displayed. When I used "all:revert" to reset the styles, I destroy the calculated value that overwrites the HTML attributes, so even JavaScript pulled the wrong value! But the browser erased the 'img' attribute width and height values I originally set, simply because they are "hints" now. So my width and height are gone!! In other words, in HTML5 now, you cannot retrieve the ORIGINAL 'width' and 'height' attribute values you set as they have been used as "hints" only. Crazy!!

    The actual purpose of the 'width' and 'height' attribute values, according to the new HTML5 specification, is to inform the browser of the actual, intrinsic width (in CSS pixels) of the image file itself, not set its dimensions. For that reason, I recommend you ALWAYS set 'width' and 'height' 'img' attributes to THE ACTUAL WIDTH AND HEIGHT OF THE IMAGE ITSELF, as that is how it will be interpreted in most cases by default before you style it. Old IE browsers will still honor those "stretched dimensions on images as is and stretch the image based on those attribute values if they are different from the norm. But newer browsers are not allowed to do that now, and will reset them back to the images native values, regardless of attribute values. If you want to customize image size, you now must do that using CSS and a class, not using width and height attributes, as in the old days. The browser in HTML5 has removed it and re-interpreted it to a CSS custom value. If you want to "stretch" your image you are stuck with CSS now, which now is the only way to override the browser's "interpretation" of 'width' and 'height' set on images. Below we will look at how to create "stretchable" images that override that new HTML5 feature and which are "responsive" as needed.

    Should I still set Width and Height in the Image Tag? Yes! It is still important you set 'width' and 'height' attributes today in images in all your web pages, as those attributes tell the browser's parser and "RenderTree" to reserve a space for images in the document tree (DOM) at those sizes in the unpainted viewport layout as the images download to the browser. Doing so, the user can start reading content without the layout shifting on them or the page refreshing or repainting the viewport. Otherwise, the layout shifts as the image downloads, moving content around. This happens a lot with floating images in text blocks. For that reason, I always recommend you put width and height on the image, but simply use the images native (actual) width and height (right click an image and choose "Properties" then the "Details" tab in Windows to see its actual size).

    The 'alt' Attribute: The 'alt' attribute is a text "replacement" for the image when it is slow to appear, fails to appear, or not viewable by the blind in a screen reader. 'alt' text should describe the image if the image contains information that is important to a screen reader. If the image is wrapped in an anchor (a hyperlink) the 'alt' text should explain where the link goes if the image is clicked. You can also use an alt="" blank value if the image is only for decoration. This tells screen readers the image is not important and if its missing, no placeholder will create a empty image box. I like to use the following format for the 'alt' attribute: "alt=image:a short description here" if the image is non-presentational (like a photograph) as it tells me the placeholder was for an image, not video or other media, and what it represents. I also like to place a slight gray background behind my images, which allows you to see the 'alt' textual placeholder in the block as the image downloads. As mentioned, the 'alt' attribute is also vital to screen readers.

    The 'title' Attribute: Always give your images 'title' attribute text, especially if click-able or inside a link. This allows users to rollover an image to see where it goes or what it represents. DO NOT DUPLICATE the 'title' attribute with 'alt' text, however, as screen readers may repeat the same text when reading those attributes. (I used to make that mistake as a developer). Never use just "image" for text in either attribute, but give it a description that's unique. Use of "longdesc" with a URI link was once used alongside 'title' to provide a link to more detailed information about the image. But this attribute is now either experimental or deprecated. Most use the new 'figcaption' feature to describe the image.

    Adding Rich Captions to Images: The 'figure' and 'figcaption' elements are now used by modern browsers to wrap around images and add captions beneath images in HTML5. The 'figure' element warps around the image and the "figcaption" usually appears under it with text describing the image. Most photographs or article images should carry more visual information in the 'img' element as well as the 'figure'. In the sample below, I demonstrate an 'img' element with a full suite of attributes that assist users with screen readers, 'title' rollover text, and a 'alt' placeholder text as the image downloads or if its missing. Other attributes assist the image in other ways. The 'figure' element has formatting that enhances the frame of the image in the article, and the 'figcaption' allows us to place a nice caption on the image. Notice the image has its native width and height attributes added. This allows the "render tree" in the browser to reserve space for the image in the viewport as it downloads. It prevents the layout from shifting when the final image appears in the element. By default in HTML5, as mentioned already, browsers only use these 'width' and 'height' values as "hints". So, going forward its better to place the actual dimensions in those attributes, rather than large or smaller ones as its likely the browser will default to the actual dimensions, anyway. Finally, adding ARIA-friendly attributes connects these elements more closely to the image. But notice I have not overdone it! An good example of how best to code HTML images is below.

    image:World Wide Web
    This is the World Wide Web!


    Sometimes designers want images with even greater descriptions. For larger image descriptions use this format below with a 'div'. This is also compatible with WAI-ARIA accessibility standards, which will read and associate your container 'div' and your 'p' description with the image. Notice the "role=img" added to the 'div' element to associate that element with the image and caption grouping. Since the 'div' element, unlike 'figure', is not normally associated with an image, this helps the screen reader identify the div container as part of the image. Below is a ARIA-friendly version of that idea.

    image:World Wide Web

    longer description longer description longer description longer description longer description longer description longer description longer description longer description longer description longer description longer description longer description longer description longer description longer description.




    The JavaScript 'onerror' Event in Images: If an image is not found or missing, you have a choice: Either let the browser show a broken error image and hopefully your 'alt' attribute text replacement, or use JavaScript to degrade gracefully and hide the error. You can use a trick like this: "onerror=this.onerror=null; this.remove()" when an image is missing, corrupted, or slow to download. The latter removes the broken image and the image itself that's missing and would show nothing, removing the image box. If you don't want to do anything when a missing error occurs but show the 'alt' text in a box, call this simpler version: "onerror=this.onerror=null;". If you want a "default" image, do this: "onerror=this.onerror=null; this.src='default.jpg" and add a new default replacement image. Below is how the code looks:

    <img src="myimage.jpg" alt="image:My Image" onerror="this.onerror=null;this.src='default.jpg" /

    Responsive Image Sizing: In HTML5 in 2022, "responsive design" is all the rage. But we have been developing and using responsive design concepts in websites since 2001! Below is an example of a more modern "responsive" image size that stretches to fill the viewport. Actually, it stretches to fill the parent container that controls its size. The parent 'div' has a style with "width:100%". Notice I removed the images width and height attributes so the browser defaults to the actual images native size initially before it recalculates the new image size. I recommend you do that only on images and media where you want the image to fill a flexible parent box. The image now honors the more "reflexive" CSS sizing added directly on the image. So, I've set its width to 100% of the container's width. Leaving height "auto" allows the aspect ration of the image to stay the same, the height changing as the width changes. As the browser window shrinks or grows in size, the container div's width changes and the child image changes with it to fill the new size. This is a powerful way to control image sizes in CSS that responds to the various sizes of newer viewports on different devices like iPhones and tablets where both the device and its orientation now change. Images in this scenario would stretch to fill that void. This concept also works naturally in old browsers like Internet Explorer, too!

    image:www

    Note: More advanced responsive design techniques are now used in HTML5 where specific image sizes and resolutions are downloaded using media queries as the size of the viewport changes. This allows your site to download specific media targeted to a specific viewport or resolution on a device. The disadvantage is of course, you are downloading multiple images now, when one can be easily resized. In some scenarios, like phone web applications, this idea becomes more critical, however. (See the "srcset" attribute section below or go to my "picture" section for more advanced image source download techniques like this). Along this vein of thought, for years I have designed all my websites with "print-friendly" versions. To accommodate that, I always download a 300dpi high resolution logo image as a replacement for the web logo version for my users when they print a web page in one of my sites. This allows printed pages to print beautiful high DPI versions of images your website when printing.

    The Best Way to Constrain Images to One Shared Size So, what if you have an image, but need it to be a different size than its normal one? Obviously, you would use CSS to do that. But what if you had multiple images with unknown height or width, but wanted them to all be "constrained" to one width or height along one dimensions? This is a common practice in HTML where photos are downloaded and replaced into a block-level element. There is a right and wrong way to handle this. Below, is a set of images, where the width is always the same but as new images are used to replace the image (via scripts) the height is flexible. Notice this also makes sure if images have differing "aspect-ratios" those are strictly maintained. This technique below does not require newer HTML5 CSS tricks and so works in old and new browsers reliably. Note: I always give images their true explicit width and height, now that HTML5 demands it. I then override that with a CSS style.




    New "srcset" Attribute: Another form of responsive design is to deliver several images in various sizes to viewers based on the viewport. Typically we do this by media queries showing and hiding larger blocks of HTML and images. But if you had multiple versions of say a company logo at different size, you could switch the image out with the new image. To do that you can use the new "srcset" attribute in the 'img' element. The "srcset" allows you to list multiple images to download based on viewport widths. Below is an example where "1px" and "2px" represent a "device-pixel-ratio" often set by the device on high resolution screens like smart phones. Often devices use such high resolution screens that web sites and images created at a regular dimension (96 pixels per 1 inch, the default for 1x) look too small. So they redistribute a typical image and website dimensions into 2 pixels or more on their devices. "2px" below means you can safely deliver an image the same size but twice the resolution to that device. I personally think multiple image calls to the server for multiple images is wasteful here, but in some cases (photography) a high definition image delivered to a "2x" or "3x" device is quite a powerful presentation on those HD screens. Of course, cross-browser issues arise with this technique. No Internet Explorer browser supports this attribute and Opera-mini fails to implement this on mobile devices. But you can count on the 'src' image attribute still working in all browsers, so I support this as a "best practices" HTML5 option. Note the various alternative images below with their respective "device pixel" support or "maximum widths" needed to trigger their download and display on any give viewport width. The default here is always the "small.jpeg" image.

    <img id="photo3" src="small.jpg" srcset="small.jpg 1x, large.jpg 2x" />

    <img id="photo3" src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w"" />

    Using Background Images: Background images are becoming more popular. In the past, we traditionally only used these when needing "tiled" web page wallpaper backdrops or under headers at the top of web pages. If used to show visual queues like photographs in pages, it creates a problem. The issue with background images is background images are not part of the page layout so "semantically" not viable. Screen readers certainly would not have a way to know about these visual queues like they would traditional images in 'img' tags with 'alt' attributes.

    This means that there is no traditional image element to represent them in the HTML, which can cause a mismatch between the visual and the structural meaning in your website. This makes interpretation by various user agents for the blind very difficult. And so, I generally do NOT recognize the 'srcset' attribute on images as a good choice for image placement in websites unless its a presentation-only choice and tiled in the background. Some developers will argue it solves how images fill layout spaces, which the 'img' element can at times struggle to do. They then create complex polyfill solutions or padding hacks to simulate this in older browsers. But I argue back, so what is the real reason to use these? There are always alternative ways to doing things in CSS and HTML. Images using the 'img' tag still represent "best practices" in image use. However, if you want a clean example of how to use background images that is cross-browser compatible, I've created a 'div' container below with a background image example for you.

    Below is an example of "responsive" design using background images. Notice, the block-level element below has a set height, but it's width is flexible. The background image uses a new property "background-size:contain" which tells modern browsers to always honor the actual aspect-ration of the image regardless of the parent container's dimensions. The photo will not distort but shrink in proportion to the container, even though it might not fill it completely along some dimensions, as the browser window changes. The blue background color shows that missing background space.

    Cross-browser problems in Background Images: Because only IE9 and greater support "background-size", older IE browsers will not stretch the image from its original size to fill the parent container as expected. IE 5-8, for example, will show the image in its original size regardless of the containers dimensions. Another problem in older agents is the fact that using these empty containers without content causes the container to collapse. In IE8 you will see this problem. So an empty image "spacer" has been added to prop up its height for IE version 1-8. There are "hacks" to address the background image size problem in older browsers, but as always, my strategy in CSS and HTML layouts isn't to fix these visual issues, but let these browsers show what they can, and degrade gracefully.




    New Base64 Images : Sending Images as Encoded Bytes

    Just prior to HTML5, web browsers introduced the ability to accept media files and images in "pre-encoded" byte streams directly pasted into HTML in a format called Base64. Without going too deep into what this encoding scheme means, its basically a way to truncate numbers into a smaller chunk of alphanumeric values that when read, represent the original byte codes for an image. Why would you do this type of things, say, for images? Well, not too long ago, some developers had the idea they could save HTTP calls to the server by sending the bit streams of images coded into the HTML of web pages. These extra connections happen in web browsers every time they pull down an image. By injecting the actual compressed byte code of the image into the browser (or into a CSS style sheet), they had the idea it might save thousands of calls to the server for websites that have lots of images (like icons or font glyphs). Not too long ago, browsers came with as few as 2 default open connections to the server, which at times meant delays waiting for images to download. These connections had to be shared with all kinds of other files as well, like HTML pages, scripts, media, etc. So, the Base64 image code was used to try and install image placers directly into the HTML.

    You can see what these long Base64 encoded text strings look like by viewing the code below for a simple 118 x 118 pixel image I created. To create the Base64 code below, you can utilize dozens of free services online that will extract this Base64 code for your images quickly. You can then paste it into the source for images, or as I have done, into a 'div' element as a background image using the new CSS3 "data" type:

    Test of Base64 Encoded Image Shown Below:


    * If you cut and paste the code below into your HTML page, you will recreate my exact image above in your web browser.

    For websites that had hundreds of small images in them, like icons or emoticons, this technique really worked well with Base64 injection, as you no longer needed to keep these images on the server. You could just send the browser the full library via scripts of hidden HTML blocks, and call then quickly with zero download time. The problem has been that often in larger images, Base64 encoding INCREASES the size of the image from the original. Browsers also cached images after the first download, so this idea because wasteful and consumed bandwidth, much like JavaScript API's do today. Avoiding the caching ability of web browsers is always a mistake and one of the serious flaws in kids today trying to invent new tricks and scripts that fail to utilize built-in features of web browsers used by the rest of us to advantage the past 20 years. In addition, with the advent of HTTP/2 and multiplexing, we no longer need to worry about downloaded files or connections. Browsers and servers have become incredibly efficient with managing connections and delivering hundreds of files quickly to the browser over the wire. In addition, up to 6 connections or more are the default pool of connections browser utilize today (instead of 2). So browsers no longer benefit as they once did with Base64 images. The other major issue is that older browsers that does not support CSS3 would not recognize the new "data" format for these new encoded background images, so would fail. This generally means any browser below Internet Explorer version 8 would fail, as they would not support Base64 encoded images. The advantage of using this newer technology (like many others invented the past decade) once again fails.

    But, if you have a website where you have lots of libraries of tiny image files, it might make sense and speed up download times when encoding them in Base64. But, it's unlikely to make a major difference in speed simply because many of those images will not be used when first displayed.

    The New Picture Element

    Before we talk about the new <picture> element, there are two new image formats you should be aware of that are coming in HTML5.

    The new Image Formats: JPEG 2000, JPEG XR, WebP, and AVIF: There isn't wide support for them yet. JPEG 2000 is not widely supported in web browsers, except for Safari. JPEG XR was only supported in Internet Explorer 9-11, so never adoptted by the other browsers. Two of the new image formats, WebP and AVIF, are proving in tests to be fast, highly compressed image types for the web that have promise! Combined with the new <picture> element, it's now possible in 2022 to expand upon the old 'img' element as "universal image holder" and use it to display new image alternatives on the web. These two new types will never replace the 'jpg', 'gif', 'png', and others, but just give us faster web image alternatives.

    The WebP format was introduced about 5 years ago (2015) by Google, but was not widely supported until 2020 when Apple's Safari OS browser adopted it. But sadly, it is still too soon to use it, in my opinion. AVIF support currently only includes the Chrome Webkit browser, but larger support is coming in the next few years, I am told. So, be prepared for a long browser support delay there, as well. In the mean time I'm sharing a possible HTML5 design using WebP for you below if you want to start using the <picture> element with WebP image types. You now have a nice picture structure you can start with.

    The <picture> Element In Action: Below is an example of the 'picture' element with three image types: 'webp', 'gif', and 'img'. If the first 'source' element is not recognized (WebP), the next source element is tried (GIF). In this case it normally would be another alternative like 'AVIF'. But here I have added a GIF image. If that image type fails in the browser or the 'source' element is not recognized, the JPG image is used in the 'img' element. I have added a new feature to this strategy that shows you additional possibilities. See the "media=(min-width: 800px)" in the second 'source' element. This says to use the GIF only if the user's viewport is 800 pixels or greater in width. If the user's browser window is reduced in size and the modern browser supports 'source', the GIF image is never displayed. If no source element or image type is recognized in the first two choices, the 'img' default JPG image is used. The browser will normally go through each 'source' tag, image type, and media query rule and try to download the WebP first. The 'source' element's 'srcset' attribute merely overrides the 'src' attribute of the 'img' tag at the bottom. They do not act as full 'img' tags, only source image alternatives to the 'img' tag. If the 'source' elements or their 'types' are not recognized, the 'img' 'src' image will be used instead. If the any of the three images are recognized as types, but fail to download their specific images, the 'img' element's 'alt' placeholder text is used as a fallback and appears in an image box as text. Notice the 'title' element is also shown on rollover of the image even if the WebP image source is picked. Any errors downloading images of any type will NOT trigger the picture element to "try" the next source image. That's an important distinction! This is an error on that image tag only and the 'alt' text and a blank image will be shown in those cases, not the default 'img' image.

    Additional Notes on 'picture' Element: Notice below I have created a nice 'alt' placeholder name when any of the images fail to download. All three image types above use this when they fail. The placeholder name of the image helps the user so they know what the image represents visually. Keep in mind, this multi-image design is a fallback for missing images or image errors on all three types, but not a way to handle 'source' tag and image type support.

    None of the Internet Explorer browsers support the new 'picture' element, unfortunately. But you can see how this system works in a non-supporting browser by opening up "Internet Explorer" as a browser and viewing the image below. IE doesn't know what WebP or 'source' elements are. In IE, the first two source images are never used, even though the GIF type is known by IE. This is because the two 'source' elements are not recognized by IE. Even when the browser window is reduced in size to trigger the media query in the first tag, the GIF is not shown in IE. Only the 'img' JPEG is shown, as again, IE doesn't support the 'source' element. In newer browsers that do support 'source', if the WebP is supported it is shown until the browser window size triggers it to look at the next source element. If source was known but not WebP, the GIF would be shown in all window sizes. The GIF image type here is shown as it is universally known to old and new browsers. This shows how you can mix and match both image types, sizes using media queries, and the default image for older browsers. It is up to you to use this new picture element and various sources for various window sizes creatively.

    If you see a "flowering tree" below, your browser supports the new WebP image format! If you reduce the browser window size and see the weather map, your browser supports WebP, but also the new media query in the source element. If you see the WWW image your browser does not support either the 'source' element or WebP. In the example below, older browsers will ignore the 'picture' and 'source' elements and read the 'img' element. Newer browsers will choose the WebP unless they still fail to support the new image format, but then will choose the WWW 'img' image like older browsers as fallback. So this solution is cross-browser compatible. The browser support is not available for many older browsers, but with picture's nice fallback mechanism, older browser would still receive the default 'img' image. This makes use of the 'picture' element for images a "best practices" HTML5 solution I approve of and which you can start using today! ARIA: Because images are usually self-identified as such in screen readers with 'alt' and 'title' supporting text, you do NOT need to assign your images ARIA roles and labels below.

    Note: This new 'picture' element below is wrapped by the new 'figure' and 'figcaption' elements just like 'img', 'video', and 'audio' elements in HTML5 now use. The 'picture' element itself does not display anything. It merely provides a context for its contained img element that enables it to choose from multiple URLs. The picture element is a "container" which provides multiple sources to its contained 'img' element. In that sense, remember that the 'img' element remains the primary conveyor of images, not 'picture'. Note: Older browsers (IE 4-8) see 'figcaption' as a new unrecognized HTML5 element. Older browsers that do not know these elements will default them to "display:inline", pushing caption text to the right of the image. You can use CSS to address this by adding "display:block" to the 'figcaption' and 'small' elements as I have done below, if you support these older browsers.

    image:My Picture
    "My Picture" [License],
    via Wikimedia Commons

    * Note: My host provider does not support "WebP" images I found out, so if no "flowering tree" WebP image appears, it is not the code but my host provider. :(



    How to Create a Cross-Browser Video in HTML5

    One the MOST important aspects of this tutorial is the practice of good cross-browser design. "Cross-browser" means many things. But in the HTML5 world it should mean making sure your HTML and page layouts work in as many OLDER browsers as possible! Too often, I see young web developers struggle with this concept and simply hack their way through the problem using gigantic JavaScript polyfills, Bootstrap, JQuery "hacks", IE conditionals, Modernizr, or some other circus trick. All fail miserably as good solutions simply because they rely on added layers and layers of scripts and DOM patches, creating convoluted "Frankenstein code" to solve what are very simple problems that older HTML4 and CSS2 used to solve.

    Its very easy to design HTML5 cross-browser solutions that work in multiple agents today. Why? Its been done already! Designing your multimedia displays in browsers with HTML need not be so complicated if you but look to what came before. The work of talented coders of 20 years ago already solved this problem for us!

    Let's now take a look at an example of cross-browser HTML video displays from the past. In the old days, we realized that the 'object' tag would always be a unique element used mostly by Internet Explorer and its ActiveX implementation. And we saw that the 'embed' element was not going away. It would grow in popularity in support of Netscape, IE for Mac, Mozilla, and many new browsers that were coming on board in those early days. The reason 'embed' was popular was simple. Most browsers, their plug-in architecture, and their scripting capabilities never fully adopted 'object' and had picked 'embed' as their primary HTML multimedia tag of choice from the start. And yet, IE 5.5 and then 6 had come to dominate the browser wars as the years passed by. IE was what mattered most. This meant that in the early days of multimedia players in browsers, we were stuck with a very bipolar environment as far as HTML and tag support of multimedia. To solve this problem, some clever old programmers designed a way to combine the two elements and create a fully cross-browser framework that supported the two multimedia HTML elements: <object> and <embed>.

    Below is a sample structure that was quite common back then. It is quite simple in how it works: The parent 'object' tag is read by Internet Explorer only, while the 'embed' child tag is read by all other browsers. The two tags support video display using a path to the video and various supporting parameters. This code design was quite powerful and supported IE as well as every other browser in displaying videos, audio, and Adobe Flash. Its use of 'object' and 'embed' work together in a "fallback pattern" that initially supports IE's ActiveX object control, then falls back to 'embed' and the common players and plugins supported by all the other non-Internet Explorer browsers. If neither tag is supported, it displays a simple "no support" text message. This example below used an Adobe Flash object that worked in nearly all web browsers, back then:

    <object
      classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
      codebase="
    http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#
    \version=6,0,40,0"
      name="mymovie"
      id="mymovie"
      width="300"
      height="200"
      data="flash.swf"
      type="application/x-shockwave-flash">
        <param name="movie" value="flash.swf" />
        <param name="type" value="application/x-shockwave-flash" />
        <param name="play" value="true" />
        <param name="loop" value="false" />
        <param name="quality" value="high" />
        <embed src="flash.swf"
          width"300"
          height="200"
          play="true"
          loop="false"
          quality="high"
          pluginspage="http://www.macromedia.com/go/getflashplayer">
        <noembed>Your browser does not support
    this media object found or the embed element.</noembed>
      </embed>
    </object>

    This HTML pattern was quite common in 2000 and up to around 2010 when HTML5 browsers came on the scene. We often just pasted this code into our HTML whenever we needed any kind of custom multimedia display, like video, and it worked cross-browser pretty well for years and years. Eventually we ran into the same problem we have today: Which media type does each of my users support? No one ever really knew as it changed constantly. As Microsoft Internet Explorer began to fade in popularity with its ActiveX dominance, this media situation got worse. With open source video, Quicktime Apple movies, and Flash, it was difficult to reliably send every browser and platform the video type they needed. The player support in browsers just got too complicated.This HTML pattern certainly helped solve the markup issues, though. The media support issues remain, even today. Around 2008 someone got the smart idea of avoiding all proprietary codices and dropping movies into a new Adobe Flash video format, creating "FLV" movies as a one-stop, fix-all, universal video playback solution. We then simply pushed are moves easily into the FLV format and HTML code above and it worked well, for a time. But as support for Adobe Flash died on mobile platforms (after 2012), it soon became apparent the "plugin model" for multimedia display would never work. And that is how we got to HTML5 and its "playerless" 'video' element support for multimedia today.

    It is 2022 now, and HTML5 is the newest rage. The HTML5 element for playing videos in a web page is the <video> element. The beauty of HTML5 and the 'video' element is the fact that the browser is now required to have all the tools to figure out how to play the video. They no longer have to install or download a plugin or player. In the old days, we used to rely on every browser on every device to figure out how and where to get a video media player. Often the operating system had final say, not just the browser. On Microsoft Windows it was easy...in their Internet Explorer they relied on ActiveX and Windows Media Player to embed a player in the browser and play the media. ActiveX often was pre-installed and had vast powers behind the scenes on Windows computers in how video and audio was played. The same went with the Flash Player. The operating system installed it. Other browsers used different players and different solutions. This meant modern browsers had to manage loads of players and strategies to support all the media out there. And so the 'object' and 'embed' dual solution above mattered. With the new 'video' element, it does not. Today, the player world is dead. In 2022, the HTML5 standards groups have asked modern browsers to support the HTML5 'video' and 'audio' elements natively to support movies and music in websites and web pages. The problem is, many still do not support a wide array of video codices.

    Video Support Problems

    The same problems remain concerning cross-browser media playback in 2022 using newer HTML5 browsers. In addition, what might work great in many newer HTML5 browsers will not work in older browsers, which do not know what the 'video' and 'audio' elements are, nor support the newer media types or codices. Many, like older Internet Explorer versions (1-8), still must fall back to using the old ActiveX controls using 'object'. Other browsers still need the old tags and old plug-ins to play media. My HTML solution below is just one idea for cross-browser support that offers you the best chance at a true HTML solution to the complexity of playing video on multiple platforms in multiple browsers and versions. You still will likely encounter issues. Keep in mind the list of problems and complexities you must address to get close to 100% support in legacy browsers is often beyond your control, independent of HTML. It touches on many different issues in media playback and codec support in browsers, old and new. But multimedia playback in web pages has gotten much better with the new HTML5 standard, since playback in HTML5 is now independent of plugins and downloadable players. Before I show you my coded solution, a couple of issues that still might block support in your browser tests are listed below:

    • Video support in HTML5 is still limited by browser support of specific media types, though less so than before (pre-2010). HTML5 using the 'video' element comes with built in support for a short list of media types (see below). These are highly dependent on web browsers and version, of course. The only supported HTML5 media formats supported are: MPEG-4, WEBM, and OGG. For older browsers that do not support HTML5 or those media types, support will depend on the user's operating system, computer, browser, browser version, player, player version, and media player. Support may be as simple as an update on that computer via a download or install of the media type's codec. HTML5 browsers, in general, should be free of media type updates and depend mostly on browser updates alone. Keep in mind, all older non-HTML5 browsers will require plugin and players, so support would be spotty on these newer media formats in those browsers. In those cases, you would need older video formats and need to install their parameters, codebase/codeid, plugin url's, etc in the 'object' and 'embed' elements below if you wanted to try and approach 100% video support in your web pages. You might have issues related to ActiveX being disabled in corporate environments for security reasons in IE 5-8, etc. The list goes on and on. But the complexity of all that is beyond the scope of this tutorial. Just keep in mind, for these reasons and more, there is no single combination of media codecs that works in all HTML5 browsers! You should plan to encode multiple video "types" for every video or audio you create, just to make a majority of viewers happy. But using HTML5-enabled browsers will get you your widest support. In the chart below, notice that the first three types are HTML5 supported (using the 'video' tag), but support still varies by browser or platform. The last three types, "MOV", "WMV", and "FLV" are older video formats that will not work in HTML5 without use of a player or plugin (using the 'object' or 'embed' tags). That is why I suggest you use my cross-browser video code below that contains the 'object' and 'embed' elements, which are still supported in HTML, by the way. Support for the video formats below is still very spotty on these last types, and constantly changing. I would stay with the top 3 HTML5 media types listed below. The last three might be good to try if you intend to support older browsers on a specific platform or device. Note that in the chart below, the first column lists the "codices" or video media "types" supported. Keep in mind these also come in various versions and that could impact support separate from the chart. The next four headings listed are browser versions and how they relate to each codec. The last two columns represent mobile devices or OS's, which might have multiple browsers and versions on them. As you can see, choosing one type of video to encode leaves large chunks of viewers in the dark as far as video. But encoding multiples, say the top three video types, gives you a decent viewership:

      HTML5 Native Video Support By Browser
      Codecs IE Firefox Safari Chrome Opera iPhone Android
      .ogg none 3.5+ none 4.0+ 11.5+ none none
      .mp4 9.0+ 35.0+ 3.2+ 4.0+ 25+ 3.2+ 4.4+
      .webm none 4.0+ 12.1+ 6.0+ 11.5+ 12.2+ 2.3+
      .mov plugin plugin plugin plugin plugin plugin plugin
      .wmv plugin plugin plugin plugin plugin plugin plugin
      .flv plugin plugin plugin plugin plugin plugin plugin
      .swf plugin plugin plugin plugin plugin plugin plugin
      .mpeg plugin plugin plugin plugin plugin plugin plugin
      .avi plugin plugin plugin plugin plugin plugin plugin
      .rm plugin plugin plugin plugin plugin plugin plugin


    • Outdated formats, like the original "Moving Pictures Expert Group" format (MPEG1 and MPEG2), AVI, WMV, Quicktime, Flash, or Real Media used to work in older browsers in 'object' elements and were very popular 20 years ago. Browsers often had the OS with pre-installed players for the file type or the browsers came with the players installed. But today, they are no longer supported in modern HTML5 browsers. In nearly all cases, only a specialized 3rd party plugin will now play them using the 'object' or 'embed' tag and the associated player. Some MP4 or OGG players built into modern browser could support some older version of each codec or its container. But do not count on it.
    • For non-HTML5 browsers, sometimes there is no downloadable plug-in available for that browser on that operating system for the media type you are playing. So a certain video will never be supported.
    • For non-HTML5 browsers, the wrong media player may have been installed or assigned to a media type on the user's computer that is wrong. I have seen this with .MOV movies on Windows, which often require the Quicktime player or just will not play at all. The reverse is true for Apple with Windows Media file types.
    • For non-HTML5 browsers on some devices, the media type may not be supported on that device to begin with! Example: .MOV or Quicktime movie downloads are often not supported on newer Android or Windows devices. So, IE or Chrome on some devices will not play them.
    • Also, keep in mind, the web server tells the browser the video type as a "hint" So, your web server may not be sending the right MIME type for that video type and must be added to the available types sent by the web server if it is missing.

    Ok, Show me the Cross-Browser HTML Video Solution! I will! Now that we have the "nasty" stuff out of the way, let's see what we can do to code a nice cross-browser HTML5 tag set to support a variety of old and new browsers. Instead of describing what the code does, just review the HTML architecture below and test the code with your own videos and with your own legacy browser testing strategies. The goal in this strategy again, is to support a wide range of old and new browser in a simple HTML solution you can cut-and-paste. My solution below combines three (3) different media "fallback" elements that support the following browsers and playback strategies:

    • An outer 'video' element in HTML5 wraps around the code and delivered first to all newer browsers (All modern browsers plus IE9-11)
    • The 'object' element is listed next after the 'source' options inside the 'video' element so older Internet Explorer browsers (versions 5-8) that require an ActiveX control can access the video
    • Lastly, the 'embed' element for older, non-Internet Explorer browsers is used and supports all other plug-in and players with video support (non-IE browser/Mac plug-ins that do not support HTML5)
    • If the 'embed' element fails a 'noembed' fall back text alert is displayed.

    My Cross-browser HTML5 Video Code Solution

    The code and sample video demo below has all the code you need to get started. This solution should work in a wide range of old and new browsers. Just paste in your own video file paths and media type values. Change the dimensions in the CSS inline styles, if you like. That's it! In the test below I am using 3 fallback video codecs of the same video to increase support across all browser types and versions: "MP4", "OGG", and "WMV". There may be minor issues in how some very old browser interpret various media types with non-support in some cases. The 'video' element below will first try to play the first two media types in HTML5 browsers. The 'object' and 'embed' elements contain an older "wmv" version of the video for Windows Media Player in older browsers on Windows computers as a fallback. You could enhance this "playback strategy" further by adding Apple's Quicktime ".mov" file to this list for people on Mac's. And if you really wanted to support 2000-2010 browsers, you could encode a Flash Video file and hope those older browsers still use the old Adobe Flash player. If you really truly care about 99.9% of video playback support, these types of strategies (plus my code) will get you there! Just do not get mired in the "latest and greatest" video encoding techniques online, or some open source coding tricks some kid online in web articles try and tell you work great, because they look good on their new laptops. Often what works for these developers fails miserably in numerous edge cases. What works best is honoring and working with a wide range of browsers, codecs, and users online, then implementing a testing strategy in these newer and older browsers to see what actually works.
    Just remember one thing: This new 'video' element in HTML5 is for HTML5 browsers and media only. The 'object' and 'embed' elements are there for everything else that won't play in these shiny new browsers, which includes all other browsers around the world going back 20+ years that still trigger calls to newer, or versioned, or long dead players and plugins when trying to play your videos. You may still deliver generic error messages to their browsers inside the video if none of the media types or video codec's below are supported by their specific browser or their type of device. Therefore, realize that this solution isn't going to solve all your video-viewing needs, just enhance your HTML markup so it supports as many new and old browsers as possible. That strategy will make your HTML website superior to anything anyone else is building inline over time with less complaints or bugs or issues compared to the developers stuck supporting a tiny range of the newest browsers and users out there.

    "Christmas Bubble Light" [License CC BY 3.0],
    via Wikimedia Commons


    The New CSS3 Grid System

    In HTML5 and CSS3, the new "grid" system now allows you to build website layout pages without having to use the older systems we used to use. This also includes its sister CSS layout tool "flex", which is new in 2017. The rule is use "grid" for larger layout systems and "flex" for smaller modular layouts within the page. Use both system when you want something beyond either static positioned layouts or which must replace "floating" block layouts that might have gotten too complex or inflexible. Keep in mind, CSS using simple floats and positioned elements still work best when you need them. In general, only use "grid" and "flex" when you need something that not only must adjust itself to the changing content inside it, but adjust itself to the subtle shifts that occur in devices like tablets or rotating monitors that change viewport space quickly and which need to move content boxes around to maximize their display. Note that "grid" and "flex" both use an HTML "parent-child" model with a container element that defines global characteristics and child elements which fill them. Both also use x-y axis lines or a bi-directional, 2-D layout structure to manage their flow of boxes within the larger container box.

    In the old days (2001), we developed powerful "negative margin layouts", positioned, and cross-browser floated "divs" to carefully construct cross-browser, flexible page layout pages. We built some really powerful positioned layouts that filled the viewport with a nice header, footer, and content panel. Using special negative margins we even got these to work well in broken box-model browsers like Internet Explorer 5.5 and 6! These designs could be fragile, however, and relied on a number of CSS hacks and tricks that risked breaking should someone untrained in CSS fail to implement them correctly.

    These older CSS page layout designs still work well today in web pages around the world and likely will for some time to come. I was even thinking of posting one in this tutorial. But then I realized, many new developers routinely reject older web designs in favor of JavaScripted solutions that don't require any direct knowledge or control over CSS and HTML. Some assume the latest and greatest will save them. Systems like Bootstrap or heavily JavaScripted Modernizr have created the illusion that their systems will always solve all your problems. Failing to learn CSS or understand how HTML layouts work has simply piled more code into our browsers to solve what used to be very simple layout problems using a tiny bit of code. Because I do not want to force something old that forces people to layer over them with more scripted solutions, in 2022 I have decided to take the middle-road and simply embrace HTML5 grids, and help you learn how to use them and their CSS in your web pages. You will feel more powerful knowing you do not need Bootstrap or Modernizr or JQuery to create a simple page layout. Besides, with "grids" and HTML5 finally starting to dominate the web development world, after 15 long years of using floats, I too have decided it is time to make the big leap towards grids!

    Improved Browser Support for Grids

    Using the new CSS grid system, we now have a new layout web page tool we can use with moderate support in a few older browsers. For example, even Internet Explorer 10-11 partially supports HTML5 grids using limited, proprietary, prefixed CSS properties (more on that later). But it appears in 2022 there is finally enough browser support in all major browsers to begin using grids. If you use a "progressive" CSS system, like my Universal CSS Framework, you wont be styling for browsers like Internet Explorer 1-7, anyway. Internet Explorer versions 8-11 would be your only holdup in using CSS3 grids in most cases. That means, IE 8 and 9 are the only real browsers left that need a layout alternative. IE9 supports HTML5 elements, but not grids, while IE8 support neither. It still may be important you deliver progressively degraded, non-grid, or float alternatives for these last troublesome browsers. But it's no longer a requirement using new "progressive" CSS designs that degrade HTML and CSS gracefully with limited layouts in older browsers like IE 1-9. Since most of these older browsers are rarely used now, we can provide a few with some simulated grid abilities, while giving others more block-level stacked content designs. Going forward we are then free to provide the newest browsers with full HTML5 grid solutions. In the last part of this article, I will touch on some of these cross-browser issues with full sets of sample code you can drop in your web projects that is fully supported in many of these browsers.

    Before we get started, let's talk about various aspects of grids.

    The grid is first defined by a concept called the "grid line". Grid lines cut across the width and height of a grid and separate columns and rows from each other. Grid lines start and end before and after the first and last columns and rows in your grid. And that starts the confusion. For starters, the columns and rows that hold content are often called "tracks". A grid track is the space between two grid lines. Around those tracks, grid lines start with the number "1", to the left of a column track or above the row track, and then numerically count forward as each line is added. Every column and row track starts with "1", but grid lines represents the line "before" the column or row itself. It doesn't represent the actual column or row number. So, if you later tell a column to span a range from line "1" to "2" it represents the bounded grid lines around tracks and will ONLY create one column. Why? Notice the 2nd grid line starts AFTER the first column's box. So, you are saying create one column, not two. Telling a grid to span two columns means you need to say, go from line "1" to line "3". See the visual below. Again, this is not intuitive, and one of the many confusing aspects of grid design, to me. Whoever designed CSS3 grids obviously made things harder for everyone. But now you know.

    image:Grid Lines

    In CSS3 grid systems, it is also not intuitive how a grid is designed or populated. Grid layouts on the surface excel at dividing a page and its content into major regions, but how that is actually implemented takes some practice. Like tables, grid layout enables an author to align elements into a giant rectangular block of columns and rows in a grid layout divided by lines like streets in a city. To create a grid, you will need both HTML and CSS. To get started, you first create a single HTML "div" element or container element to hold what are called child "divs" or "grid items". These children will be the cells that hold content in the grid. But this outer "div" is the parent grid element, and defines your grid by setting its "display:grid" property in CSS. This property can also be defined as "display:inline-grid" for more flexible layout placement that fits in with horizontal text content rather than vertical.

    In addition to the CSS "display:grid" property on the parent "div", you can also set the "grid-gap" property which defines the spacing between grid rows and columns. It works just like in an HTML table spacing setting. If you add background color to grid with gap spaces, its color shines through the gap. An example of using gaps might be "grid-gap: 2px 2px", which would tell a grid to create spaces between rows then columns with 2 pixels of space between each. "grid-gap: 1em 1em" is another version of adding gaps using text units. Using "em" or "rem" units as opposed to pixels is an ideal way to separate text or content blocks which will enlarge or shrink relative to the font-size set by the end-user in the browser. Pixels are static and ignore user settings, unlike "em" or relative font-size units, so I always use "em" units in my grids, instead. Even though "gaps" are helpful, I recommend you not use the grid gap properties as they are not supported by IE 10-11 and add extra dimensions to your grids you do not need. A better alternative is simply to use CSS padding inside your cells to separate content from neighboring cells. Below, I will still show some examples using gaps so you can see how they look and work.

    Beside a display value of "grid", a parent "div" also needs a "template" which determines the initial layout design of the grid. These template properties decide the initial numbers of rows allowed vertically and their height, and the number of columns horizontally and their width in the grid. This determines how "grid item" children that will populate the grid, and is considered an explicit grid setting. Because web browsers are always limited more by available width in the viewport (height can be scrolled), grids like everything else in the web world, rely on these critical "column" width and count settings. If you leave this "template" CSS property off the parent grid, the grid will by default have one column per row and its children stack like normal HTML blocks. So be sure to always define at least one template property for your rows and/or columns. A template example for columns is as follows: grid-template-columns: 10em 10em auto. This says to always allow room in your grid for at least 3 columns horizontally, 2 at a specific "em" or width of 10 character widths max, with the third column allowed to be a flexible cell stretched to fill the rest of the available width. Besides "em" units, you could use the new "rem" unit. It means to take the root element's font-size rather than the inherited parent's size. In both cases, the font-size is based on the chosen 'font-face' and is equal to the space of one "em dash" character for the given font in width. The last unit "auto" in CSS usually means fill the available space, don't overflow it, but use an amount no smaller than the given content. So, using "auto" in this case would mean this last column in our template would stretch to fill the remaining width of your grid but remain no smaller that the content it holds when collapsed.

    Lastly, each of our child "divs" is considered by the parent "div" grid to be a "grid item", as we mentioned above. These grid children are the cells that will fill our rows and columns in a grid. These cells are simple styled "div" elements, so have some backwards compatibility with older browsers who all know "div" elements. You can add as many of these grid items as you like, keeping in mind how and where they might populate the columns and rows you defined in the parent grid element. In this example below, we have not defined rows yet. So the grid auto-populated those for us. As you add more and more of these "grid items" inside your parent, they will fill the grid columns up horizontally first in your grid's first row by default, then drop down to the next row, filling each row like this with new grid items in columns as they go. I have created a sample grid below in HTML with the information discussed above so you can start to see how the HTML is designed. Note: I have added extra CSS styling to make our grid look presentable.


    <div style="width:100%;
        display:grid;
        grid-gap:2px 2px;
        background-color:#cce;
        border:1px solid #333399;
        grid-template-columns: 10em 10em auto;">
      <div style="background-color:#eef;padding:1em;">GridItem1</div>
      <div style="background-color:#eef;padding:1em;">GridItem2</div>
      <div style="background-color:#eef;padding:1em;">GridItem3</div>
      <div style="background-color:#eef;padding:1em;">GridItem4</div>
      <div style="background-color:#eef;padding:1em;">GridItem5</div>
      <div style="background-color:#eef;padding:1em;">GridItem6</div>
    </div>

    GridItem1
    GridItem2
    GridItem3
    GridItem4
    GridItem5
    GridItem6

    Keep in mind, if your grid item count does not finish filling a row it will have an empty place where cells should go and remain as an unfinished row. These "explicit" grids do not try and complete rows or columns unless you provide rules that allow them to fill them out in a predictable way (more on that later), or explicitly tell them as we have done in these early examples. This makes HTML5 grids very different than say the "grid" of an HTML table. I thought logically a grid would be a set of cells and blocks that fill a rectangle by default. But these "grid items" actually fill a grid more like a flowing set of floated blocks, much like our old floating layout systems. You can tell a grid to populate its cells vertically by stacking columns in a limited row count design. But in this example above, we are using the default which is horizontal columns placement. In more advanced grid designs, you can tell specific blocks to fill specific columns and rows, even extend cells across columns and rows. But that will come later in this tutorial.

    Below is another example of a grid using a few extra properties. This one has a set width using two columns in the final layout. This rigid design will push text content down the page as it grows but remains a rigid width. Note: As always, when it comes to grids or any CSS design, I like to use "em" text width and height relative units, as each display of your HTML and CSS will now grow based on the user's set font size on the device and browser, growing or shrinking to fit their viewport, font-size, and display preferences. This is always superior to pixels, which could expand or collapse to very small sizes based on the screen because of shifting "device pixel" ratios that change.

    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text


    The New Fractional Grid Unit ("fr")

    Many grid widths and height values on rows and columns can be set as "auto", which is the default, in most cases. Setting grid cell widths to "auto" tells a grid to collapse as small as possible when text allows but grow as big as possible, expanding the cell dimensions when needed without breaking out of its box. All CSS block-level elements work this way with "auto" dimensions. "Auto" is great for filling missing unknown widths in one column, for example, as content will not break out of the cell, but terrible when used to fill in unknown widths across multiple columns where space is shared. Why? The reason is simple. As soon as you add content to one "auto" width column the others collapse their widths to the smallest possible, as "auto" cells with content stretches to fill as much available space as it can find. Use "auto" dimensions that way if you don't care about collapsing column widths, but need a completely flexible layout grid. These cell dimensions can also be designed using hard-coded units, like pixels, and so use hard-coded values. But, I do not recommend it. Pixels are terrible solutions as most devices interpret pixels differently as far as screen width or height. With the new "device pixel" on HD screens you cannot rely on the amount of real estate a pixel-based column or row will fill in terms of physical real estate on a screen. As mentioned, I use "em" (use "rem" if ignoring older browser, IE 1-8). This way your units stretch based on the user's font size settings, not a hard-coded value.

    But there is a better way to set dimensions on columns using the new "fractional" unit for grids. It solves these issues. The new 'fr' unit represents a "fraction" of the total available space in the grid width and assigns fractions of the total available width to each column based on the sum of all fractional units combined. Example: If there are 3 columns defined and each has "1fr" assigned to it, the total width is "3fr". Each gets one third of the total width of the grid dimension (1fr or 33%). If on the other hand there are 3 columns where "2fr" is assigned the first column and "1fr" to the other two, we have a total of "4fr" units assigned. The "2fr" unit assigned to the first column would fill 50% of the space (2 of 4 fr units), and the other two would get 25% each. The 4fr units assigned is the same as: 50% + 25% + 25% = 100% width used. Now, let's look at a new grid example using those 3 fractional units.

    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text text text text text text text text text text


    Quick Discussion: In the example above, we see the "2fr 1fr 1fr" layout at work. But what if the first of the three columns had a width of "100px" and "1fr" was assigned to each of the other two columns, the first column would always be 100px in width and the other two columns would get 100% of the width left over in total width after subtracting the first 100px column width. The two "fr" columns would EXPAND to fill the growing width in the grid. This works very much like "%". I like "%" to stop "auto" columns from collapsing with no content, which they will do. But I recommend you use "fr" instead for a flexible layout that will not collapse based on content, versus using "auto" or "%" or "pixel. Only use "auto" if you need a single "auto" or flexible column to fill in the rest of a grid layout, or multiple "auto" columns if you do not care that they collapse to various shared widths based as various content in your grid cells. Use "fr" for a percentage of the available width regardless of the content inside and to prevent collapse. Of course, if you shove a giant image into a "1fr" column that is a member of many template columns, then you COULD break your shared layout sizes. Always use "fr" fractionals if you can. They are even supported in IE10-11 grids. Otherwise, if you think you could have content of unknown dimensions added to your grid columns, then use "auto".

    Using Grid Rows

    In the grid parent properties you can also use the "grid-template-rows" property to control how rows perform in your grid. Each value in the property represents a "row height" as columns represent width, with each item you add to the property representing one new row. Example, "grid-template-rows: 200px 100px" means two rows with the first row set to "200px" in height and the second row set to 100px. When you set explicit rows like this, no additional rows are supported or will be created. But if there are columns that overflow past your rows, all rows added because of the overflow collapse to "auto" for width and height. For this reason, if you use the "grid-template", "grid-template-columns", or "grid-template-rows" properties, remember you are using the EXPLICIT grid, not the implicit grid where the grid only has the rows and columns you define initially. There is some limited freedom with the grid object when adding more columns and rows like this using "template", if your "grid items" list grows or content changes. But if your grid items exceed the rows and columns needed in these explicit grids, you will see unexpected results. That is important, and is one of the things I do NOT like about CSS3/HTMN5 grids. They just were not thought through well enough in their design to be consistent and intuitive.

    But these kookier, more explicit grid systems do have fallback that kinda makes sense. Most grids do not know how many rows your multiple child "divs" or cells will fill so they have to either follow a rule you set or assume something else to hold the growing grid items list. How "grid-template-rows" is used to populate rows is still based on the number of grid items or "divs" you create. In the explicit grid, you must try and tell the grid how many rows or columns you need based on your grid item count. It really depends on how many cells you add, right? It could be a few or a few thousand! But setting only one or two row's height and not knowing how many rows you end up with or explicit grid items you may have means there is something inconsistent here with this property in how it must handle this contingency. For that reason, I recommend you NOT use "grid-template-rows" or set a row count or height. Just let your grids collapse to fill an "auto" row height as content grows, and let row count be implicit. Unless you know your EXACT grid item count or have a limited grid pattern you will use, its best to not use these template row properties at all.

    Content is almost always flexible and not fully known in web designs. If you are designing a static or rigid grid system and do know your row counts and final grid dimensions based on the number of child "divs" or cell count you added, then assuming you want say 3 rows max, you could add the following to your parent grid: "grid-template-rows: 5rem auto 5rem". This creates a grid with set top and bottom row heights but a middle row that fills the available page height as needed for growing textual content that fills the available height of the page. In this design, content in the middle section can safely expand vertically as content fills it. These heights on rows that have a hard-coded value like "5rem" or "100px" have one other nasty feature. If you have content in a cell that goes beyond its fixed dimensions (either height or width), there is a NASTY cell content overflow that happens where your text or image overflows its cell and spills into the next grid row or into the grid itself! You then have to add "overflow: scroll" or some other features to either hide or show the text that overflows the grid cell using scrollbars. Quite a nasty design! That is why, if you use the "grid-template-rows" feature, remember that adding "auto" here is your best friend as it will always expand to hold the content! By the way, if you added a 4th row value in your template after these first 3 rows, and there were no cells grid items to fill it, an empty row would still get created with no columns cells. This is why again, hard-coded row or column layouts and explicit grid systems depend on fixed grid item counts and known grid item content before you begin any grid designs.

    Let's now demonstrate one good use of the "grid-template-rows" explicit grid feature, anyway. One example of this type of row design might be a Header-Content-Footer web page layout design that needs a flexible content middle but with static header and footers. In that case, using "grid-template-rows: 10rem auto 10rem" format might be ideal in limiting your layout to three rows with a head and a footer, but using a stretchable middle row (main) set to "auto" row height. An example of a simple page layout grid with set grid items and row counts with spacing is shown below. Note the use of the "grid-template-columns" and "grid-template-rows" combined to set columns and row structures, plus new CSS styles on your grid items which controls how many columns it spans using the new "grid-row-start" and "grid-row-end" styles on the header and footer. I will let you look at these new rules in the HTML below to see how it works. Note: I am using "rem" units here instead. Because IE 1-8 does not support "rem" units but also does not support "grids", those browsers in this case would not use these CSS value settings anyway.

    Header
    menu
    content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content
    aside
    Footer


    As mentioned, when using explicit grid settings, if you set a hard-coded height or width on a row or column, and if your content needs more space, content will overflow its cell and break through the column or row by default! Bad idea! If that's your design you can add "overflow:auto" (as I have done above) to child cells which will create a scroll bar on the cell or on the parent grid if content flows through. Just remember, the "template" settings on the parent grid control basic grid track dimensions, initially, but your cells control the final space they need. Planning for cells and their "unknown" content is therefore very important. Always plan for content to grow. That is why your grid settings need to be as flexible as possible. Only outline a "starting layout" for your grid, with accommodations for when and how its content can break. Otherwise, your viewers later may be in for a surprise!

    Advanced Grid Features: Other than the "template" grid properties, everything else you add to a grid defines the 'explicit' grid, or what is actually filled into your initial layout. You have more fine-grained control over each cell, padding, border, and color. It is just a matter of what styles you apply. But there are other features of grids you cannot control. At first, you would assume a parent controls the grid layout of columns and rows. But as you will see in the samples below, that is not the case. It's important to understand that both the parent and child elements with their own styles and content work together in union with the parent to define the FINAL grid layout you will see on your web page. Using the "fr" units or "auto", and avoiding defining specific row heights initially, can help in starting out flexible and fluid as your grid grows to hold all kinds of HTML "stuff" you did not expect! As we will see below, however, there are many combinations of CSS settings that can alter grids or even distort grid columns and rows. So, if you learn anything about "grids" from me, remember this one rule: Grids can be changed by content and styles despite your carefully designed, grid settings! Most people on the Internet will not teach you that!

    You can add as many child "div" elements as you like inside the parent grid "div". But each cell can also have its own "item properties". As you add them, assuming you set your "grid-template-columns" property on the parent and don't add "grid" styles to these children, those "div" cells will stack first visually across the grid, horizontally filling the column in a row, then drop down, creating new rows as you add more cells. This may create some rows with missing columns, as you might not expect. That means the grid honors the column count horizontally over row counts expected. Again, this is another reason why in grids, it's not a good idea to try and anticipate row counts or row heights unless you have a strict layout with known content and child cells added. As mentioned, if you know the exact number of child "divs" you are adding in say a header-content-footer design, then yes you can safely define row heights and row numbers. Just remember, grids have to be flexible to deal with those times when you add some unknown cell count. And so grids manage that by creating partially filled rows of cells as more are added to the parent.

    Grid "Weirdness": As we mentioned, the parent 'div' generally defines the column limit, horizontally, not the row limit vertically, so that child elements can flexibly fill the row count set, as needed. But what if a child "div" decides it wants to extend across the columns in a row and go beyond say our 3 column layouts shown above? It turns out you can tell child 'divs' to extend beyond the parent's "grid-template-columns" property or defined column limit and create even MORE columns, breaking the horizontal design of the grid! In that case the grid's child cells can redefine a grid and go beyond its defined limit shown above in our 3 column grids and create 4 or more columns! The result of this change now has affected our elegant, evenly spaced "1fr 1fr 1fr" grid shown in the example below. It now adds a fourth column with an "auto" width default that has collapsed. This shows that you can not only ALTER a grid's design using its children, but change how default layouts act using child "grid item" properties by increasing rows, by adding more children, or by expand columns horizontally.

    All these examples were added to warn you about grids and the unexpected "possibilities" in grids you might not expect or accept that can happen if you do not design them carefully with deep knowledge of your web page's expected content, changes, and designs. Note: Below, I have added a new grid item property to the first cell: "grid-column: 1 / 5" to break this grid. This property is shorthand for the "grid-column-start" and "grid-column-end" properties. This value "1 / 5" says to start this cell at the first grid line and "span" it or end its width on the 5th grid line, basically saying to stretch the 1st column to 4 columns. This example shows how a single cell can break through a parent grid's column and row settings and redefine a new grid layout!

    This column spans the first row of 4 columns using the "grid-column" property and breaks through the parent's 3 column grid.
    cell
    cell
    cell
    cell
    Notice to the right there is no cell to fill in the gap. That is how grids work. They don't assume this cell should stretch >>



    The Amazing Flexible Grid

    Up until now we talked about more rigid and "explicit" grid designs with some weird things that can happen if your grid elements break out of or try and extend themselves beyond the parent's rigid assumed layouts. There are more flexible rules you can apply to "implicit" grids that let the grid figure out how to populate a grid in a more flexible way. This allows support of small screen devices like mobile phones, as well, which must adapt to changing widths with new layout rules. These "grid concepts" were new to me until I did more research, as the IDE's I use to write web pages did not support many of these features, nor was there decent examples on the Internet to help me. So, I hope these help you.

    For most of the examples below we will use the new CSS shorthand property called "grid". We are going to use some more advanced grid values with it below. All of the cells (or child "divs") below have no special grid properties applied. The parent "grid" property controls its design, as shown above each example, using more flexible grid properties.

    Below, is our typical rigid design. But this one uses the new "grid" shorthand CSS property. Here, we explicitly tell the grid we want two "auto" height sized rows filled with 5 cells all equal width. This is the old way of assigning this property as its rigid and doesn't allow the grid flexibility to decide how to populate rows and columns with the 10 grid items or child "divs" it holds. Note: Using "auto" prevents cells from overflowing their boxes and spilling into the next row. You will see that feature below with cell number 2 and its extra content.

    <div style="grid: auto auto / 1fr 1fr 1fr 1fr 1fr;">

    cell
    cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell

    Let's try a better way! In the example below, now use more advanced grid language that tells the grid how and when to populate its limited grid items. The new "grid: property defines rules for grids that apply to separate row and column properties ("rows / columns"). The left of the "/" applies to rows only, to the right controls columns only.

    In the example below, we now apply some new values to our CSS grid property. The first is the new "auto-flow" value. "auto-flow" is the most powerful "grid" value in flexible grid design. It controls how the algorithm for auto-placement of grid items works, specifying exactly how auto-placed items get flowed into the grid, either by rows horizontally or by columns vertically. This new rule in the example below tells the grid to take all the blocks and populate the grid horizontally in the first row. It also tells the grid to create as many rows as needed based on all the grid items available, taking each item and stacking them in order across the row horizontally until it is filled, then dropping down and creating a new row. This is different than setting explicit rows, as in earlier grid examples. "auto-flow" for columns works the same way, except instead of honoring rows it stacks items in he first column vertically first across all rows until each row is filled. Then they start a new column in the first row again. "auto-flow" can also have a value after it, like "auto-flow 100px" which would limit its height on every row created. But this is usually not a good idea as any content greater than the cells height allowed would overflow into either neighboring cells or into the bottom of the grid container. As mentioned, I usually add the "overflow:auto" CSS property to my grid container to prevent that. It will create scrollbars if needed on the grid to contain but show content in cells, which is better than hiding content. The "auto-flow" generally adds a default height of "auto" to rows and "auto" to width in columns so they will not break out of their cells. So understand that grids are designed to expand and grow as needed to hold content. This is more true of rows than columns when "auto" or "auto-flow" is used.

    Important: You CANNOT set "auto-flow" on both rows and columns. Why? The grid does not know if you meant to add a column or a row for that extra cell, so is conflicted! Will see an example of all this below.

    Next in the example below, lets look at the CSS grid container rule: "grid: autoflow/repeat(2, minmax(300px, 1fr))". This says to repeat columns as needed across rows as defined by "auto-flow" in the first section. This means use "auto-flow" to build dynamic rows as needed, then columns should start stacking horizontally, filling out rows in units until full, then creating new rows. Using "repeat(a,b)", the "a" section represents how many repeating items maximum to create. In this case it would be columns. The "2" means always create two columns max. You can also use "auto-fit", which would mean to use as many columns as possible. This would add flexibility to your grid, allowing the grid to decide, but would mean some rows are not filled with cells (remember we have 10 grid items in these examples). The "b" section of "repeat" sets the dimensions or our grid items, or in this case the "width" of columns in the rows. Many use a set width on pixels or em units, but we can use a new feature called "minmax" which allows you to set the minimum width a column should start at, then its maximum width it would allow. The same rule can be applied to rows, if needed. This can be in "pixels", "percent", "em", etc.. In the example below, we use a special "fr" or fractional unit. Thus, "minmax(300px, 1fr)" value says to start each column at 300px minimum width then grow it as large as needed to fill the space available, making sure each column in the row are equal or 1 fractional division of the total space divided among them. Cool, huh? This gives our grid the ability to grow as needed as content in our grid items changes, yet limited by the number of columns we set, which is 2. Again, this column limit is usually based on the number of "div" or child grid items we have. If we had 12 we could use odd or even numbers of column, for example, or our "auto-fit" feature. You will see that in an example after this one.

    <div style="grid: auto-flow / repeat(2, minmax(300px, 1fr));">

    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell

    New Mobile Phone Grid Designs using "auto-fit"

    The example below is the same as the one above, but in the column settings for "grid" in CSS we are using the new "auto-fit" value rather than a set "2" columns. "auto-fit" tells the grid to populate as many rows with as many columns as it needs, ignoring any set column or row counts. This means as the browser window narrows in size your column counts collapse and rows increase to fit the viewport. This is great for mobile phone web designs! Note: This will often create rows with empty cells if the number of grid items cannot be divided into odd or even numbers. Instead you can use a grid item count of child "divs" that is divisible by odd and even numbers like 6, 12, etc. so no matter how many columns small screens create it always fills each row with columns. I am using "12" grid items to demo that feature, below. Narrow your browser window and watch how the grid columns collapse gracefully to fit the width of the screen. Because "12" grid items can be divided up into rows of 2 or 3, its grid items will always fill a perfect square grid of some type. This is the most flexible of our grid designs using the new advanced flexible grid units! "auto-fit" also has the great ability to drop down multiple column layouts into fewer columns in the grid supporting mobile phone designs and narrow tablet screens. This means you do not need media query to control this feature. Its automatic! The other feature of "auto-fit" we you will see is the following: If your grid has extra rows or columns left over, it removes them completely, essentially setting their dimensions to zero.

    <div style="grid: auto-flow / repeat(auto-fit, minmax(300px, 1fr));">

    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell

    Below, I'm demonstrating a few more values for "grid" you can use. Here I am using set height on the first row (100px) with repeating ones after it set to 4 rows total. Notice we are still are using a set number of rows. In fact we are saying, "start with a single 100px row, then add new ones in batches of 3 all the same height". The first row has a set height of 100px, but the repeating ones share the same heights. This row count of "4" total is critical in holding all the grid items in columns. For columns, I am now using the rule, "/auto-flow 1fr" in the column section. This now tells the grid to take all the grid items and start populating the first columns across all 4 rows first, adding items in each row of the first column until filled, then start the second column on the next row. "1fr" means to let columns stretch and share the available width of each row as needed. Again, an implicit, more flexible design is used here. Note: A black space remains in this example. Thats intentional. Notice, I am using "4" rows, though I have "10" grid items. There are not enough grid items to populate these missing spaces. This shows how partial rows of items can be left empty. This might still be ideal for displaying photos where you don't know how many will fill the screen (the count is variable) but you need them to stack as closely as possible to fill the space available, creating new columns.Its important you see how grids here do not stretch columns to compensate in this design, but fill down into all 4 rows, first.

    <div style="grid: 100px repeat(3, 1fr) / auto-flow 1fr;">

    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell

    When Grids Fail

    In this grid example, I want to show you how grids can try and interpret your assumptions as best it can, but can also fail. Notice the empty space in the example below. You have told the grid you want one row with 100px height, but then one column with 200px width. There is a contradiction here. The grid cant determine if you want more than one column or row as you have 10 grid items, so it chose 10 rows, instead. Because columns are only allowed to fill 200px widths, but must honor the row first, there is empty column space left over that it cannot fill.

    <div style="grid: 100px / 200px;">

    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell

    Now I have added "auto-fit" to the row design in the same design above. The grid is still confused as to how many rows and columns to add. It's told to add a single 100px height rows but also must set a single 200px column. Adding "auto-fit" is a new feature. It says to fit everything in the grid but remove any extra space, rows, or columns that refuse to fill the grid. I could have added "auto-fit" to the column side of the property value and it would work the same in removing extra grid space and forcing all rows and columns to be filled DESPITE the base pixel settings I applied. Again, as above, the row rule is honored first in cases like this where it does not know whether to add extra rows or columns to hold all the grid item "divs". In this case, it still fills rows to hold the grid items vertically. But now, using "auto-fit", its erased any extra rows or row space not needed. I like "auto-fit" because it cleans up the mess we create!

    <div style="grid: auto-fit 100px / 200px;">

    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell
    cell

    Fit-Content

    Now for something completely different! Another cool grid property value I like is "fit-content()". Like "minmax()", new "fit-content(max)" allows you to set a max width on a column similar to "minmax(max-content, max(min-content, argument))", but where the minimum width is always the maximum available space, and where max is never greater than the maximum argument value. Since the max must be a value (not fr, max-content, etc), "fit-content(max)" works best if you want a cell to always fill available space up to a hard-coded max unit value. (Note: "fit-content" can be used with other CSS properties, like "width: fit-content" in CSS3 supporting browsers)

    Typically, most grids default to a width of "auto", which is a non-collapsing minimum default dimension in grid rows and columns. With "auto", content starts as a minimum value needed to hold content, but grows as needed, never breaking out of a column or row. "auto" is essentially the same as "minmax(min-content, max-content)" but using the minimum space. This default "auto" basically says start with the smallest dimension needed to hold available cell content. The problem with "auto" in grids is it always starts out cells with small dimensions, first. With multiple columns of text these "auto" cells often collapse even smaller, giving terribly small cell dimensions until their increasing content fills more and more space, expanding the shared cell space. "fr" or fractionals now improve that default space but shared width is not predictable. Dimensions like column width are even more unpredictable using "auto" if you are using a fluid design. To solve that, you can use "minmax()" as a way to contain columns width using minimum and maximum in a range that helps. But your columns often start with minimum dimensions that explode into maximums that you might still want reduced in certain situations.

    With "fit-content()", the cell's width stretches with the text content to fill the full "available size" of a cell, but allowing content in a cell to use more space up to a maximum width. "fit-content()" is essentially "fit-content(stretch)", but expressed below as "fit-content(maximum)". Unlike "minmax()", this max value must be a set unit value, not "fr" or other implied value. So, your cell must stop at some hard unit width value. For this reason, the "fit-content" design seems to work best where you have one or more "fit-content" flexible boxes with a "1fr" cell that will fill in the extra space. The example below demonstrates this feature with "em" unit maximums, which I prefer. "em" is a universally accepted font-unit that matches the relative font-size set by the user's browser. Notice, if we had used "auto" or "minmax" instead of "fit-content", the first cell would have likely collapsed to the smallest word in the cell rather than start to expand towards its max value as text is added.

    Note: IE1-11 does not support "fit-content". Instead, you can kinda simulate this feature on column widths using "minmax()" or "auto" combined with "fr" units. Note: Multiple cells may still expand much larger or collapse based on text size, however.

    <div style="grid-template-columns: fit-content(10em) fit-content(20em) 1fr;">

    cell cell cell
    cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell
    cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell cell

    A Note on "justify-content" and "align-content: If for some reason you create a grid parent with columns, but you use hard-coded values so that the width of the columns is less than the total width of the parent, but you still want those columns centered and spaced, you can use the 'justify-content' to align the "floating" cells inside horizontally and "align-content" to align the content vertically inside the grid parent block. This ONLY works if the container is larger than the total width of all the cells combined in a row (example: "grid-template-columns: 20rem 20rem 20rem"). The sample grid below has settings you can use in that case to center all the columns in a row automatically and equalize the spacing between their cells. Normally, the default is what you want for both these properties using grids, which is "justify-content:normal" the same as "justify-content:stretch", and "align-content" the same as "align-content:stretch". "stretch" means to distribute all items evenly with items "auto" sized to fill the container. There are more properties and more values you can use, many of which bleed over into "flex" properties (an alternative to "grid"). But for now, consider using the default grids created below with these defaults to get you started.

    Customizing Grids The Right Way: In this last section on grids I will touch on some minor customizations that make managing grids much easier. You can Google these ideas online, but I'm going to just add a few new CSS properties below to fine tune my last grid examples, so you start out on the right foot with a nice reliable template. I have tested these example, so they will work well in many website layouts.

    All Possible "Grid" Shorthand Combinations

    There are so many ways to use grid properties. Its overwhelming to me, too. But I thought I would list most of the major combinations below to help you. The "grid" CSS properties below are all shorthand properties that set all of the explicit and implicit grid properties in a single declaration. Often you may still combine them. For example, all of the "template" properties work best when used as separate properties. Or, you can simply use the shorthands to do everything, like "grid-template:" or "grid:". There are too many variations to list, but below I have outlined most of the various "grid" shorthands combinations you can use and what each feature of the grid they control.

    The "grid-area", "grid-row", and "grid-column" affect only the "grid items", not the overall rows and columns of the larger "grid container". So, set those only if you prefer to control the grid item-by-item, which I do not recommend. The [values] for rows or columns below can be, "fr", "px", "%", "auto", "auto-flow", "minmax(min, max)", or "repeat([count or "autofit"],[values])". Notice below that the more detailed shorthands get stacked progressively down into the larger ones below. If think of it that way, you will see that the first shorthand properties are just reused in the later ones. So, as you go down the list you will see the items defined at the top of the list can be fitted into the larger shorthand items below:

    (Use these for GRID ITEMS only)
    
    grid-area: [grid-row-start] / [grid-column-start] / ["span"] [grid-row-end] / ["span"][grid-column-end] | [area name]
    grid-row: [grid-row-start] / [grid-row-start]
    grid-column: [grid-column-start] / [grid-column-start]
    
    
    
    (Use these for GRID areas, rows, and columns)
    
    grid-template-areas: none;
    grid-template-rows: none;
    grid-template-columns: none;
    grid-template-areas: "area1 area2 area3"; (one phrase per row)
    grid-template-rows: [values];
    grid-template-columns: [values];
    grid-auto-rows: [auto size of each row];
    grid-auto-columns: [auto size of each column];
    
    
    
    
    (Use these for GRID shorthands for combined areas, rows, and columns)
    
    grid-template: none
    grid-template: [grid-template-rows] / [grid-template-columns]
    grid-template: [grid-template-areas]
    grid-template: [grid-template-areas] [grid-template-rows]
    grid-template: [grid-template-areas] [grid-template-rows / grid-template-column]
    
    
    
    
    (Use these for GRID shorthands for combined templates, areas, rows, and columns, plus "auto-flow")
    
    grid: none
    grid: [grid-template]
    grid: [grid-template-rows] / [auto-flow] [grid-auto-columns]
    grid: [auto-flow] [grid-auto-rows] / [grid-template-columns]
    

    Internet Explorer Grids

    Alert: Browser Support for Grids in Internet Explorer is still very Limited! Internet Explorer versions 1-9 will NOT support 'display:grid' and instead will display your grid in vertical blocks of stacked content. IE 10-11 will only support grids with special pre-fixed "-ms" styles (see below) that support a small subset of what the full-featured modern grids in CSS support. That means if you use grids, plan for limited IE support (often version 10 and 11 only) with some type of layout alternative for the others. In general, you should at least always stick with 'divs' for all your grid children so older IE browsers by default will return them to block-level stacked elements of content that is readable, should grids fail. Because I want full semantic HTML5 used in my grids, I have chosen to use the HTML5 structural elements anyway, like 'header', 'main', 'footer', etc. I also like to use CSS "fallback" properties in the grid to address IE-only styles - like hexadecimal colors for 'rgba' colors which IE 1-9 do not understand. or "em" alongside "rem" font style units, the later which IE 1-8 will not understand. If like me, you use a robust custom CSS style sheet system that hides styles from older browsers (like IE1-7, which mine does), and reduces them to plain white page content blocks, that then leaves you with only needing to support IE 8-11 when delivering a layout alternative to "grid" designs.

    Below is my IE 10-11 only version of grid in CSS that you can add to your grid systems that works in many Internet Explorer browsers, but falls back to simpler designs when the grid is not supported. This one does not use the modern HTML5 structural tags ("main", "header", etc.), however. Note: It happens to work good in modern browsers like Edge, Firefox, and Chrome. But, I recommend you use my final grid version show below this one, instead. It incorporates code into a better cross-browser version, than the IE example below, using HTML5 elements plus hacks om CSS for IE. But the code below will allow you to see a simple example of how IE interprets grid CSS rules.

    header
    main
    footer


    My Final Cross-Browser Layout Grid Example

    Below is an HTML Grid Example that has all the "goodies" you may need to create a robust grid system. I've added as many properties as possible to give you a solid prototype you can use that supports as many old and new browsers as possible with a grid. This universal grid design also fills the browser window, so your web page layout can fit into the grid and control the complete viewport of the browser. This HTML Grid example also uses a traditional "Page Layout" architecture but uses grid "area names" that match the new HTML5 structural elements ("header", "main", et.c) in the grid design. The named items in the template match area names in the children's elements, id's, and CSS selectors. This is a helpful design pattern that makes laying out a page and managing its CSS and HTML5 blocks simple and identifiable as far as what each cell block's role is in the page and grid.

    Grid "Goodies" in the Example Below Include:

    • A Complete Web Page Layout Template is shown below. Use this cross-browser layout grid system below to manage all your page designs. It is fully customizable, so you can add or remove header, footer, or other sections as needed.
    • Added full grid support in All Major Browsers, plus full grid support in Internet Explorer 10-11! Includes partial grid support in IE9 (float layout), with IE 1-8 browser degrading gracefully to white stacked block content. This wider CSS grid support allows your grids to now work in most of the modern browsers, degrading to plain stacked content for older browsers that support "div" blocks.
    • Added new HTML5 layout elements "main", "header", "footer", "aside", and "section", so the grid layout is semantically correct in HTML5 browsers!
    • Added full set of WPA-ARIA attributes on grid children so the grid supports screen readers and other viewers.
    • Added new "grid-template-areas" with simple area names. This new "area names" CSS grid property was added on the parent grid so its much easier to manage your page layout grid sections using area names. New area names define sections of your layout grid with names that match the HTML5 elements: 'header', 'footer', 'main', etc.
    • "overflow:auto" was added to both the parent container and each child item, so in the event content overflows at least users get scrollbars instead of content hidden or breaking through into other cells. It isn't pretty, but a necessary fallback mechanism.
    • I have added "box-sizing:border-box" to all grid "divs" which makes sure that all padding and borders are part of any width calculations used by modern CSS3 browsers.
    • "justify-content" and "align-content" were added to the parent grid container with "normal" which means fill the width and height with all available cell real estate, and stretch their boxes to fill that real estate. This is normally the default and what you want with grid layouts, but there are many more options you can try.
    • Some "fallback properties" in CSS selectors were added in cases where older IE browsers don't understand advanced HTML5/CSS3 properties or units and need to default to units they do understand.
    • Added a Mobile Version that collapses the left and right aside panels when viewing on small screens! One nice feature about grids is you can use "media queries" to move each cell around, hide them, reposition them, or replace them as needed in smaller screen devices. To do that, my grid now supports mobile devices using a CSS media query below to remove the "left" and "right" cells when the browser window is below 40em text units in size. Try it! When the media query triggers on a smaller screen, the "grid-template-areas" property is reset to a new design layout using the area names. You can also easily customize this to show and hide panels as you like. Radically different layouts are now possible with grids for different devices and viewports.
    • CSS Styles: I have moved all the CSS styles to a style element below so can customize them and then paste them into your own style sheet, as needed.
    • Added new FULL VIEWPORT feature that fills the browser screen 100% width and height! Using the new "grid-template-rows:5em 8fr minmax(5em,1fr)", in parent grid element allows grid layout to now fill available vertical and horizontal viewport space 100%. The "blue" grid box should always attempt to fill to 100% the maximum width and height of the screen when appearing alone in a new HTML web page.
    • Added new "Grid" Alert Box Triggered in Internet Explorer 1-9. A new alert box is triggered for IE 8-9 warning of non-support for grid layouts and to upgrade their browser to a newer HTML5 version. Because I use my Universal CSS Framework, IE 1-7 will not get these alerts and instead will receive a plain white, stacked, block-level content page.

    Header

    Main

    content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content

    Footer

    * Copy the CSS and HTML in the box below, then paste it into your web page to start using this universal cross-browser grid!

    The New CSS3 Flex System

    As mentioned above, "grid" and "flex" are two types of HTML5 layout systems that are closely related and often cross-over in terms of their functions. Use "grid" for larger layouts and "flex" for smaller ones. But often, they do the same thing. That is why I think they were poorly designed. But if you use them, because of their "cross-browser" issues in so many older browsers, I recommend you use them sparingly, or at least design alternative fallback designs for older browsers. I will try and show you code that does all that in this example, the same as I did in the above one for "grid". Simply cut-and-paste my code below, It has all the "goodies" to get you started!

    I will not go into too much discussion over the history or influences of "flex" as its too much to cover. But I will simply say that in my opinion, "flex" is just another "grid", but on a simpler scale. Where grids have much more granular control over every single row, column, and cell (like in a table), flex is more about control over boxes that float and stack along a single dimension based on available width or height. For that reason, flex boxes feel like more of a replacement for "floats" in CSS and HTML, which worked fine and can still be used (see my float article in this page). Floats still have huge support in ALL BROWSERS, old and new, going back over 20 years now. The point of using "flex" rather than "floats" is you now have more granular control over how a series of boxes grow and shrink to fill a space relative to each other. With floats you only had limited control of box sizes. You also don't have to worry about floated items overflowing their container or the page flow. But "flex" boxes and layouts are really only needed if you have parts of a page that need to expand or contract critical content. It usually means some need beyond "sexy web pages" that affect larger concerns, like how information is maximized. Imagine, for example, a person with a large tablet they carry around all day, working in an industry like cars, buildings, or planes, or order tracking, or inventory.....where parts of instructions, forms, or design in the viewport need to be expanded as these large tablets used by people are rotated, zoomed, or expanded hundreds of times a day to view critical information. You will then see where these types of "flex" layout changes really turn a traditional HTML website you might see on a desktop computer into more of a critical, highly "flexible" application used by thousands of people that rely on those pages to do their job. That is where this new technology may shine in the future if browser support solidifies.

    Cross-Browser Issues With Flex

    Just like with "grid", browser support of HTML5 and CSS3 features like "flex" are poor. It's only in recent years that support has increased enough in modern HTML5 browsers that flex can be used. The problem is, in the past decade there have been too many half-baked implementations of flex that have changed and so leave behind remnants of code that has changed several times! What is worse is support in Internet Explorer for flex is still poor.

    Flex Box Examples

    Because my "grid" article uses features very similar to "flex" boxes (and was so exhaustive), I feel like I need to give you guys a break and shorten this "flex" tutorial quite a bit. Instead of showing you all the flaws and the pieces that break in this new "flex" system, I am going to simply list the basic design of a few "flex" layouts I recommend with code samples and solutions you can copy as needed. Now, I'll cover the basics of "flex" designs and the CSS properties that control them.

    Flex Parent Container Values

    • "display:flex" - This defines a standard block level flex display on your flex container. It can also be "inline-flex" just like grid's "inline-grid", which allows your flex box to run horizontally like inline text sentences.
    • "flex-direction:row" - This determines what primary axis or direction the stacks of flex items take when filling in spaces in the flex box. The default is "row", which means flex items will fill a horizontal row from left to right. This value can also be "row-reverse", "column", "column-reverse".
    • "flex-wrap:wrap" - This determines if the stacks of flex items create a single row or are allowed to wrap down and create new rows as they fill available width. The default is "nowrap". Boxes or flex items will stack horizontal but not create a new row. This value can also be "wrap" or "wrap-reverse".
    • "flex-flow:row wrap" - This is just a shorthand for the above two rules. I have used that instead in the HTML below.
    • "justify-content:flex-start" - This property defines how flex items are aligned along the primary axis determined by the flex-direction property. This is usually horizontally. The default is "flex-start" where items are packed together closest to the start of the row or column in the upper left corner or based on the "flex-direction" setting. This value can also be "flex-end", "center", "space-between", "space-around", "space-evenly", "start", "end", "left", or "right", with extra values "safe" or "unsafe" added after. Adding "safe" says the flex items cannot be pushed offscreen after rendering spaces. Often the default is used, but granular alignments can be set.
    • "align-items:stretch" - This property defines how flex items are aligned along the opposing or secondary axis from the main one. This is usually vertically or how boxes fill individual row heights. If the main access is "rows", for example, then "align" affects the column axis alignment. Often they boxes collapse based on content. But by default, flex sets items to stretch or fill to equal length, which is one of the hallmarks of flex design. to enable this feature, "stretch" is the default value for "align-items", which means all boxes will stretch across both axis to fill all available length, attaining the same size. This value can also be "flex-start", "start", "self-start", "flex-end", "end", "self-end", "center", "first-baseline", "baseline", or "end-baseline" with extra values "safe" or "unsafe" added after. Adding "safe" says the flex items cannot be pushed offscreen after rendering spaces. Often the default is used, but granular alignments can be set.
    • "align-content:normal" - Like "align-items", this property works along the same secondary axis from the main one. But instead of affecting flex item boxes within rows, this affects the spacing or hidden lines between multiple rows of flex items (like the spacing between rows). "align-content:normal" is the default, which means all boxes are set as if no alignment was changed between rows. This value can also be "flex-start", "start", "flex-end", "end", "space-around", "space-evenly", or "stretch" with extra values "safe" or "unsafe" added after. Adding "safe" says the flex items cannot be pushed offscreen after rendering spaces. Often the default is used, but granular alignments can be set.

    Flex Child Item Values

    • "order:1" - This property only affects flex item children and defines the order this flex item will take. This feature allows you to customize the order of flex items in the parent container even when the physical HTML elements may be different. Note that the default is "0" meaning all items without this property would fall back to their physical html design order.
    • "flex-grow:0" - This property only affects flex item children and defines how much the flex item should increase in size along the primary axis as the viewport grows. Often all items are give an "integer" like "1" or "2", so they all expand equally in proportion or at twice the rate relative to others, etc. The default is "0" or no growth.
    • "flex-shrink:1" - This property only affects flex item children and is the opposite of "flex-grow" in that it defines how much the flex item should decrease in size along the primary axis as the viewport decreases. This would allow some items to get smaller faster than others. The default is "1" or maintaining a 1:1 ratio with no shrinkage.
    • "flex-basis:auto" - This property only affects flex item children and defines the default size of the item. It is based on any width or height assigned the flex item. "auto" is the default which usually forces the item to expand to fill a complete row or column. It can also be a percent, or absolute size, or "content" which means use the interior content for sizing. If set to "0" extra space is removed from the size calculation as the container dimension grows and spacing is distributed. I like to think of "flex-basis" as the "default starting size" along the primary axis, relative to the other flex items beside it, and from which it can grow in greater or lesser proportions using its grow and shrink properties.
    • "flex:" - This property only affects flex item children and defines a shorthand for the following above properties combined: "flex-grow" "flex shrink" "flex basis". The last two are optional. The default value for this property would be "0 1 auto" which says use "auto" for its starting width, which usually means fill a whole row. "0" means to not resize bigger from its starting size, and "1" says to not shrink but stay with its 1:1 starting ratio.
    • "align-self:auto" - This property only affects flex item children and defines alignment away from the default alignment of the flex item as set in the parent container using "align-items". The default is "auto" which is best kept as is, unless you need to move the one flex item away from its slot inside the flex box.
    • Note: Many of the above properties on "flex items" are not used and optional, as the defaults are common and some have poor support even in modern HTML5 browsers today. However, I would use "flex" and set the rates of growth, shrinkage, and default box sizes there.

    DON'T WORRY! If you couldn't follow all that listed above, I have "cut-and-paste code" below you can use, that has the most common property settings used.


    My Flex Box Cross-Browser Solution

    This flex box example below should have all the code needed to give you MAXIMUM cross-browser flex support, including fixes to allow "flex" to work in Internet Explorer 10-11, which is "buggy", and a range of partially implemented flex solutions that changed in browsers over the past decade. Using the CSS and HTML below will guarantee fixes in many of these outdated browsers. It also allows IE 1-9 which does not support "flex" to at least fall back to a simple stacked content box set, which is better than trying to apply JavaScripted polyfills or other floated "hacks".
    This sample code below shows a simple 3-box content design you can customize. If you are able to reduce your browser's viewport size, you will see how the middle box expands faster than the two outer boxes. When the browser gets small enough, the far right flex item drops down and fills the row beneath the other two, expanding to full width (I explain this in detail below).
    This is the real power of "flex" - its ability to naturally adjust its box sizes to all kinds of viewport conditions as well as apply matching heights with little if any need for media queries or other complicated CSS code changes. It also handles the horizontal positioning and floating of boxes very well with minimal code in CSS and HTML. This also demonstrates how much simpler "flex" is from "grid" designs, which can get very complicated. So use "flex" for your simpler layout issues.

    flex item 1 flex item 1 flex item 1
    flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2 flex item 2
    flex item 3 flex item 3 flex item 3



    Additional Notes

    Flex container should generally have no style or color. The gray outer box was styled to show you how flex boxes fill the parent container. But I would remove that feature, unless needed.

    Also in the code above, notice the wide array of "display" properties I added to the container "div" above. These are called web browser "prefixes" in CSS. This is used to address issues that remain with support in HTML5 browsers today and in the past that started to "partially" implement flex when it was still experimental. Because W3C recommendations were abandoned, that decision created a "mess" of broken standards and these unused prefixes and properties that current HTML5 browsers have either abandoned or still use. I recommend you add this extra "prefix" code into your CSS flex boxes, as I have done above, to make sure all the older HTML5 browsers understand flex going back 10-12 years. This is "bad sign" by browser vendors and shows how implementation of "display:flex" is still not fully supported in many modern browsers because they have refused to create an enforced standard much less follow one.

    Notice how I have set the two outer child flex items above to use "flex: 2 0 auto" but the inner one uses "flex: 3 .5 auto". What "auto" says is, for the flex item's starting size, use the div's set width/height dimensions. What the first number says is for "flex-growth" allow the flex item box to grow twice or three times its size relative to the others when the width of the viewport window increases in the browser. The "second or middle number represents "flex-shrink". When "1" or "0" it means not to ever shrink the box from its initial size as the viewport shrinks in size. Because the "middle" or center box has a slightly higher starting width, plus its first flex value is slightly larger, or "3", than the other two, it will start out larger and grow bigger as the browser viewport grows. As it shrinks, though, I have set it to ".5", so it will collapse down to match the other two sizes. The result is the three items will grow to fill the flex container as the window grows, but the middle column with the most text content will grow faster. As the browser window gets smaller, all three will shrink back to their original size, the middle one down to half, until they cannot all three fit in the row or width of the screen. Because of "flex-flow: row wrap", the flex item to the far right will then break off first and drop down to another row as the window gets smaller. But it will expand to fill that row as its "2" or "flex-grow" value is set to grow larger. Another technique you can use is the following: Instead of setting "auto" values to use the set width for the initial size, you could set "flex: 2 0 100%" and "flex: 3 .5 100%". This says all three should remain the same size but share the space, but when they drop to another row they stretch 100% to fill the next row. You could also add CSS "media queries" to collapse or hide any of these flex items for tiny mobile screens, say removing the left and right flex items and leaving the middle one, or change the "flex" values in CSS to get larger or small in different ways based on specific device viewport widths. But with flex, all that is now optional as it does a great job of dropping items in rows into new rows as the window changes size.

    You will notice that I didn't change the default "align-items: stretch" spacing values, and used the default value ("stretch"). The default makes sure all the boxes in the rows "stretch" to the same height in the row or whatever axis is used. This can be tweaked, so that instead of similar heights, the boxes stretch based on their content, or other alignments. Because of the default "stretch" setting in "align-items", the heights of the cells remain the same, which is one great feature of "flex" you cannot get using floats. I could change this, however, to say "flex-start", and these boxes could extend down their text content in an uneven line instead. As you play with various sizes and design layouts using flex, and start changing the various justify spaces and alignments and sizes of boxes, its flexibility in changing layout will become more important over time.

    We just need the HTML5 browsers to catch up and support more of "flex" in CSS.

    CSS Style Sheets for Flex: Be sure to paste in my style sheet code into your own website as is. It includes all the "crazy" cross-browser CSS prefixes needed, plus hacks for older browsers. These fixes will allow this solution to work in as many old and new browsers as possible, going forward, and takes care of most of the big issues you may find using flex in numerous browsers. Because "flex" was partially implemented by modern browsers without a real standard or true recommendation, it has created this mess of CSS needed to guarantee your flex boxes will work across many modern browsers used today and in the past decade.

    As always, my code choices reflect my concern and care for older browsers and a wider range of users, allowing your HTML websites to reach 99.99% of browser support with very little cross-browser testing needed. That means you can use my solutions knowing they work in a wider range of browsers and use your time for more important web building ventures. :)

    How to Force New HTML5 Elements to Work in Old Browsers

    One of the problems of HTML5 is the fact that new markup standards are often designed to work in new browsers but not degrade gracefully in older ones. HTML5 does a good job of limiting the number of new elements added to the HTML recommendations. Since 2010, there have been maybe two dozen or so elements added to browsers. Of these, only half have had wide adoption by newer browsers. For elements like <canvas>, <dialog>, <datalist>, and others, you do not need to worry as few browsers support them. And I recommend you avoid them. It is the popular HTML5 elements that remain you must worry about, as older browsers will fail trying to render them without additional help.

    Many older browsers, like Internet Explorer series 1-7 and Netscape 4 and 6 series are almost entirely dead. Yet, these browsers occasionally pop up in some places you might least expect. I remember in 2012 going to large corporate convention to present a new web application I built, to find to my horror their own projector tower in the corner of the room only used old Internet Explorer 6! Thank goodness, I had designed my XHTML and CSS to work well in the broken box model and "quirksmode" of IE6. So, my site ran perfectly! But it taught me not to assume the latest and greatest code is important, because in the real world it does! The fact is, not everyone has the latest and greatest web browser!

    The version of old web browsers you need to worry about vary. But in terms of supporting HTML5 elements your main focus should be on Internet Explorer 4-8, simply because between 1996 and 2010 these IE browsers completed dominated the browser market. Unfortunately, these browsers were born too early to ever know about HTML5, which really didn't get started until 2007, but was not fully implemented till some time after 2010. For that reason, these IE browsers will completely bomb when they encounter HTML5 layout elements because they simply do not know what they are. Other HTML5 browser issues will pop up in many older Gecko browsers, like early Mozilla and Firefox series, old Netscape 4 and 6 series, and nearly all desktop Safari browsers. I will not go into detail except to assume that any browser made prior to 2014 (year of first real major HTML5 implementation) will struggle with HTML5 elements. Often when an old browser finds a new element it does not recognize it defaults its CSS properties. Example: "display:block" is assigned to block-level elements. The list is extensive. But it cannot really restyle these unknown elements if it doesn't know what they are. It could assume they are text, not markup. So, that is what I will help you fix. My goal here is not to solve every complex issue in HTML and CSS for you below, but to give you a few tricks that will solve 90% of your issues and allow you to move forward quickly knowing you have tackled this very complex issue without Modernizr, Polyfills, or layers and layers of complicated scripting and CSS. I offer you two solution below to help fix issues in Internet Explorer 1-8 fast!

    Two Tricks to Fix HTML5 in Old IE Browsers

    • Insert Dummy HTML5 Elements using JavaScript - You guys know I hate JavaScript, but unfortunately this is the only real trick that will get all your HTML5 elements working in Internet Explorer 4-8. Know that IE 9-11 still do not recognize all the HTML5 elements, but often will know most of them. For example 'main' is still not recognized in IE 9-11. But because its an empty wrapper, it often still works ok if you set its CSS style to "display:block". It is the older IE 4-8 browsers that have larger issues with all HTML5 elements. If they do not recognize them, they will not allow their use. To force IE 4-8 to even render these elements, you first need to insert them into the Document Object Model (DOM) of your page using a special JavaScript trick. Add the script below into the head of your page and suddenly you can style and use any HTML5 tags listed in IE 4-8. I suggest you stick with just the "Section", "Grouping", and "Media" types and inject these into the IE browsers using a special conditional statement that only works in IE8 or less. Listed below are the HTML5 elements I recommend you focus on in supporting Internet Explorer with HTML5. You can add more to my list as needed. First, simply past the code below into the head> of your web page. This will install these elements into the memory of Internet Explorer 4-7 so that the HTML elements are now recognizable:
      
      <!--[if lt IE 9]>
      <script>
          document.createElement("header");
          document.createElement("nav");
          document.createElement("main");
          document.createElement("footer");
          document.createElement("section");
          document.createElement("article");
          document.createElement("aside");
          document.createElement("figure");
          document.createElement("figcaption");
          document.createElement("video");
          document.createElement("audio");
          document.createElement("picture");
          document.createElement("output");
          document.createElement("details");
          document.createElement("summary");
      </script>
      <![endif]-->
      
    • Isolate IE 1-7 Using CSS Style Sheet @import - I suggest you use my "@import" trick to hide all your newest CSS3 and other styles from all older IE browsers. My new "Universal CSS Framework" uses this technique. In fact, this tutorial uses this new CSS system, and allows me to hide more advanced styles from IE 1-7. I can then provide a progressive, simplistic CSS style sheet for IE 1-7 that allows my websites to appear as a simple, white, block-level pages for these older browsers and more advanced CSS for every browser created after that. Your newer browser users will get CSS3 or higher styles and layouts, while these older browsers get plain white linear designs.

      First, create a basic CSS style sheet for these older browsers ("OldBrowsers.css") which you add to your web page via a standard link (see below). In here, add any special styles for these older browsers including special styles for the new HTML5 elements you installed above. Note, after you run the script to insert dummy elements above, you will now find they are actually ready to be fully styled! Next, create a second style sheet that has the new "import" CSS rule that will hide your more advanced style sheet from IE 4-7 and a long list of other antiquated browsers (see below). Simply paste this CSS import rule EXACTLY as shown below, then add in a URL to your advanced CSS style sheet. Older IE browsers will only get the first linked sheet mentioned, and your newer browsers will read both sheets. But you can easily add styles in the advanced / imported sheet that will cascade over the first. IE 4-7 will never see the advanced / imported sheet. You can now safely ignore IE 4-7 forever in that sheet going forward using cutting-edge CSS styles knowing those old browsers will never see them. Your newer browser users will always get the import sheet, so that newer browsers going forward will always get the latest and greatest HTML5 designs and CSS layouts possible without breaking in IE 4-7!
      Note: You MUST use the @import rule EXACTLY as designed with text and spaces and use of the "all" type. This exact "import" format fails in a number of older browsers for various reason related not just to "import", but use of the "all" media type (IE does not understand "all" in @import), "url" removed from @import, and use of a single quoted URL string around the URL string (old Mac IE browsers fail with this). There are many versions of the "@import" styke sheet rule that enable older browsers. But this one generally is helpful in excluding the main browsers of the past, Internet Explorer 1-7.

      The @import Format Below Hides its Advanced Style Sheet from the Antiquated Browsers Listed

      @import 'AdvancedBrowsers.css' all;

      
      - Windows Internet Explorer 1-3
      - Windows Internet Explorer 4.x-7.x
      - Macintosh Internet Explorer 2-4.5
      - Macintosh Internet Explorer 5.x
      - Netscape 1-4.8
      - Opera 1-3.5
      - Konqueror 1-2.1
      - Windows Amaya 1-5.1
      - iCab 1-2
      - OmniWeb
      

      To Use this trick, first add two external style sheets links. The first "OldBrowsers.css" sheet should have IE 4-7 basic styles only. The idea is to give these older browsers very crude, simple, white page layouts of content (no grids, flex boxes, etc.).

      
      <link media="screen" rel="stylesheet" type="text/css" href="OldBrowsers.css" />
      <link media="screen" rel="stylesheet" type="text/css" href="Importer.css" />
      

      Second, add the following @import rule inside the "Importer.css" style sheet page above, and change the link below to your advanced browser style sheet. Be sure to add all your advanced CSS into this sheet, styles you would normally use in HTML5 and CSS3 compliant browsers.

      
      @import 'AdvancedBrowsers.css' all;
      

      That's it! You now can design simpler white pages with text for IE 4-7, but using HTML5 that works and styled for these older user agents. But, in your "imported" sheet you can safely do your advanced CSS layouts and designs you expect to work great in newer HTML5 browsers.

    Old ASP.NET WebForms

    Here is an example of how "web applications" used to be done 10 years ago using Microsoft ASP.NET WebForms. So, if you see this type of code in a web page or you are used to coding this way, this is NOT how more modern ASP.NET pages will work going forward using ASP.NET MVC CORE. This was first invented in 2002 and has been around for a long time. I like to post stuff like this to remind me of older technologies I once used that might still popup in company servers. Notice the old form with "runat=server" in the "form" element that told the server to process every element inside the form on the server. These strange "forms" always wrapped around every page's content in old WebForms ASP.NET, even if form controls were not present. It managed many parts of the page this way by using HTML's natural form HTTP post format, adding strange new features like hidden postback form fields filled with Viewstate data. Bad design! We often deleted these gigantic viewstate data strings from our projects and recreated the page control "state" manually in the codebehind page. If you see this "form" code below in any web project you might have inherited you should just know its old .NET Microsoft WebForms.

    As a Microsoft developer, I like to remember all the different languages and frameworks we used to use when constructing HTML in ASP.NET. Web development technologies have changed 5 times now in the past 20 years, believe it or not! My favorite Microsoft web technology is still a much older design called "ASP VBScript", the original interpreted language that we used to code in (c. 1998). Ironically, Razor Pages in new Microsoft CORE ASP.NET in 2022 is returning web development BACK to this older, simpler, HTML page code model in many ways! Strange. I guess what's old is new again! This proves technology often doesn't improve, but gets worse when we hire the wrong people to re-imagine it and abandon what once worked well. They erase the work of talented people without bothering to learn from them or the past, destroying what was once a great model used by millions of people. I cannot say the same for old WebForms, which in my opinion was written by the wrong people: Desktop Application developers, who did not bother to understand HTML or CSS, much less Web Standards in 2002. As a result, their 15 year old technology is now dying quickly on the vine. Its death proves my point.

    Anyway, below is some sample ASP.NET code:

    Character Encoding in HTML5

    HTML5 by default uses UTF-8 character encoding for all its markup and content. Thus, HTML5 uses Unicode number sets for all its characters. It supports over a millions unique characters, including all the languages of the world and more. But UTF-8 is the form of Unicode encoding used, and means all characters are translated into number sets and stored using an initial 8-bit memory block for each character. Think of Unicode as a giant sheet of numbers mapped to letters and characters and UTF-8 as the specific way those numbers are encoded or stored in memory. UTF-16, the standard encoding used by JavaScript (see next article below), encodes numbers starting with 2 bytes, or 16-bit sets going up to 4 bytes to encompass all the characters in Unicode. HTML5 and UTF-8 uses the same basic system, but starts with a single byte and can go up to 2-4 bytes when it stores upper planes of Unicode numbers.

    When software tries to read these Unicode numbers and translate them into actual fonts and letters, it must read the numbers from these bytes in memory or from a byte stream from the server over the Internet. But to read them correctly and extract the right numbers, web browsers and their various parsers need to know the exact "encoding" used when the page and its associated files were created. To do this, most browsers use the server's HTTP response headers, the HTML doc type, meta tag charset values, and byte order marks on documents to determine encoding settings. Knowing how those values are stored in HTML and other files matters. It determines if numbers are stored in one byte rather than two, for example. This is what UTF-8 represents and why it is so important. If the browser did not know which encoding to use, or even if Unicode is used, some or all of the characters would be decoded incorrectly and the Unicode characters displayed would be scrambled. When these numbers are read wrong they are lost and cannot be deciphered.

    The confusion behind all these charsets, Unicode, and encoding/decoding schemes means most developers work around the edges of this technology and just accept or "hope" the browsers do their job and interpret everything correctly. This works fine for most English-based websites, as the standards characters used are almost 99.9% of the time map to the older technology called ASCII, which uses the first 128 characters of UTF-8, matching the two numbering systems number-for-number with all the major alphanumeric characters, perfectly. Only 32 of those special command characters will not match. The same applies to UTF-16. So, as long as all your characters remain within the major English alphanumeric ones you do not ever have to worry about HTML5 and how it interprets, encodes, decodes, and stores those characters.

    The problems come when you start using "upper planes" of Unicode that hold foreign languages, emoticons, and special characters beyond the standard ASCII ones. There are 17 planes comprising over a million characters and their code points. So, its possible to misinterpret their encoding and decoding. The problem grows when you consider the fact most font sets do not have most of those glyphs built into them. Add to that the issue that many older browsers were not designed for Unicode character mapping, foreign languages, emoticons, or display of older language sheets, like Latin-1. The good news is that because HTML5 is UTF-8 now, all the modern browsers interpret the majority of foreign languages and a larger proportion of Unicode characters, correctly. Many fonts exist that support a vast number of glyphs. And memory and storage of UTF-8 and UTF-16 is now reliable and consistent. Remember, UTF-8 supports over a million characters. It will hold most of the Unicode numbers in 1-4 bytes just fine. It is when storage, encoding, and decoding occur of Unicode characters that you might see issues. The main problem is older browsers and even some newer ones that sometimes mis-identify certain languages or characters used, or jumble the way they are decoded.

    In the old days of HTML4.1, the older browsers often defaulted their charsets to Latin-1, or Windows-1252. And so, when foreign languages were used, the browser might or might now have the character code points, sheets, or fonts to interpret and display them correctly. Again, it might be that those characters were pasted into pages from a flawed encoding, so would be returned scrambled. Any data stored in databases that did not use Unicode, would also store the numbers incorrectly. They would then come out scrambled from memory in the wrong code points. Some modern technologies like React, I have read, still have some struggle with Unicode in memory, byte streams, or in the storage of encoded and decoded character sets.

    As I mentioned, the good news is that HTML5 now enforces use of good Unicode encoding and decoding. The code examples in this web page are also designed to maximize your chances none of these problems occur by making sure you use the right HTML5 markup and headers to trigger UTF-8 encoding and enable display of Unicode characters. By adding meta tags with the charsets for UTF-8, as well as setting up your software to encode in UTF-8 (which most now do), you are almost guaranteed to NOT have Unicode character issues as the browsers and their various parsers (see JavaScript one in next article) will now know exactly how to decode them. Add to this the fact most ASCII maps perfectly into UTF-8. You still may find some characters that fail to display correctly due to the issues mentioned above. In those cases, I will describe some ways you can bypass encoding problems and directly encode characters in a way that is guaranteed to work for decades to come.

    In Unicode, every character is identified with a number represented in memory of the browser, database, or computer as a numeric value called a "code point". The number is often displayed as a hexadecimal (Base16) value, which in turn gets stored or represented in memory as 1's and 0's. This is basically how most characters get translated. Each code point represents just one simple integer, which in turn represents over a million characters listed in the giant Unicode sheet. These numbers can grow as large as 4 bytes or 32-bits, which can hold billions of numbers, if needed. Understand that each special Unicode number represents its own special character in the massive 17 "planes" of Unicode and is uniquely tied to that character alone. It cannot be used by any other. As long as you know the right numbers you can display any character you want, regardless of how they are stored or encoded because Unicode numbers are universal. Know that the storage, encoding, and decoding of these numbers is what gets complex and what is variable in the computer world. Know that HTML5 uses UTF-8 to store, parse and display both its markup and content, but JavaScript parsers use UTF-16 (see JavaScript article, "Character Encoding in JavaScript" below). But as I mentioned, you really do not need to worry about the details of how they operate in these different encoding schemes. As long as you are not reverting back to what older browsers did - encode in old Windows-1252 or Latin-1, or try and trick HTML5 into not using UTF-8, most of your Unicode should work file in most browsers. The modern HTML5 browsers are very smart at figuring out what encoding all your files use, anyway. Modern web servers are designed to assist the browsers in that process using HTTP headers, as well. But what if you want to paste in some fancy Unicode characters into your content, or display emoticons, or special characters and scared you might see unknown or scrambled characters. There is a risk. But I am going to show you how that works so you will never again be fearful of using Unicode in your web pages.

    Unlike the limited character sets that came with browsers years ago (older ASCII-based encodings like Latin-1/ISO 8859-1, Windows-1252, etc.), Unicode number values are pulled directly from sheets that come with operating systems and browsers. The problems that remain, include the fact that many fonts stored on laptops and older desktops do not often include the FULL Unicode character sets. The web browsers today use tricks to fix this issue, like picking custom fonts from the user's set needed to display many multilingual characters, glyphs, and emoticons. However, this might still fail because developers often assume everyone has the right fonts or do not assist the browsers enough by providing fonts with the glyphs needed. Asian characters, which are more pictorial, often fail to display in web browsers around the world as they require very accurate glyphs. The problem was compounded by older browsers like Internet Explorer 1-6 and others that did not come with multilingual font support, so would fail to show many types of Unicode characters. These older browsers also were not designed to pick "alternative" Unicode-supporting fonts like later versions. And so, if they could not find the Unicode character in the author's set font in CSS, they would display a "?" or "unknown" error for that character. The problem was compounded by the fact the charsets used often included custom operating system versions of characters, like Windows-1252 which came with characters and numbers that did not match to Unicode's versions of those same characters. So, you can see the variety of issues that have occurred with Unicode over the years.

    To help you overcome all these issues with Unicode, I have created a checklist below of things you can do to maximize your chances that your web page's Unicode characters work in as many browsers as possible:

    Rules to Follow to Maximize Successful Unicode Character Display in Browsers

    1. Try and stay with the "lower planes" of Unicode characters by using the common "named" character references that are more widely supported in many older browsers. These are almost guaranteed to work in not only most common web fonts, but inside alternative fonts as well. Character names that do not map directly to Unicode code points may point to older character sets numbers used in older browsers that did not use Unicode.
    2. Pick a web page font for your website in CSS that contains all the language characters you will be using, or which have the best chance to contain the specific Unicode characters you will be displaying. Often, modern browsers will use their own fonts if they cannot find the character numbers in the author's font. But, if you choose a specific font using CSS that contains your glyph or character, it will almost guarantee your Unicode characters are displayed as expected. For example, there are Asian font sets you can choose that have all the right Unicode glyphs needed to display the full language needed.
    3. Have the browsers download custom font sets, as well as several alternatives, using CSS style sheets and the "@font-face" property. That will greatly increase the chance your special icons get downloaded and used correctly. If you are using special or unusual emoticons in your web pages, this is especially critical. Do not assume every computer in the world has the same fonts that your computer has. That is a very common mistake.
    4. Try some special 3rd party products like "Font Awesome" and others when using icons and emoticons, as they come with rich libraries of symbols that work well in most browsers. Some have their own named characters references for those glyphs, download custom fonts from their servers, or include scripts that determine browser type and version when picking which technology to use. These products help with picking the right alternative fonts to display a given glyph, or have superior Unicode code point checks to make sure browsers use the right numbers and characters.

    Now that you have all that info, lets discuss the types of character references and how to use them.

    What is in a Name? You have many choices in how you use Unicode characters in your web pages. The confusion online is often not about Unicode characters, but all the crazy names for these types of markers. You will hear the terms "Entity", "Escape Characters", "Encoding", "Character Reference", and more! So let's settle what the names mean first:

    • "CHARACTER REFERENCE" - A character reference is a generic term for any format or coded system used to represent Unicode characters when they cannot or are not used directly in a software system, like an HTML web page. "character references" have three subtypes: A "numeric character reference" refers to a character displayed using its "code point" in hexadecimal (&#x20AC; for the euro sign) or decimal form (&#8364; for the euro sign), while a "character entity reference" refers to a character by a predefined name, or "named" reference type (&euro; for the euro sign). So, nearly all Unicode character reference representations are covered under this term.
    • "ENTITY" - An "entity" is a form of "character reference". In many web sites the term "entity" represents any alphanumeric code used in HTML to represent a single letter or symbol in Unicode. It turns out "entity" can be used to represent any Unicode character represented by any combination of "&" and some letters or numbers, including the numeric and hexadecimal values. This would not include "natural text", which are Unicode characters pasted directly into web pages. However, the term "entity" is more often meant to describe ONLY "named" character references, for example the &euro; format for the euro symbol.
    • "DECIMAL ESCAPE" - A "decimal escape" is a form of "character reference". Anytime someone mentions "decimal escape" they are referring to a subtype of character reference that uses just the Base10 or numeric form of Unicode (&#8364;) with the raw Unicode number pasted in.
    • "HEX ENCODING" - A "hex encoding" is a form of "character reference". Anytime someone mentions "hex encoding" they are referring to a subtype of character reference that uses just the Base16 or hexadecimal form of Unicode (&#x20AC;).
    • "ESCAPING" - "Escaping" is also a form of character reference. Anytime someone mentions they are "escaping" a character, or using an "escape", they are referring to the "act" of replacing a Unicode letter with the character reference version using "&", which is either using letters, numbers, or hexadecimal forms to replace Unicode in a page. It is another generic Unicode term you might hear.
    • "ENCODING" - Anytime someone mentions "encoding" a character they are generally NOT talking about entities, escaping, or character references but the overall Unicode document format the file is saved in, which is generally UTF-8 in HTML5. So, encoding is what the characters are all saved or displayed in. It is another generic Unicode term you might hear. Note that encoding has nothing to do with character references as the encoding of the page should not matter much as character display when it comes to character references. "encoding" thus lies outside the encoding and decoding of web pages.
    • "CODE POINT" - This references either the decimal or hexadecimal numbers and letters used in creating a Unicode character reference. Often, some developers think this is the hex form, only. But a Unicode "code point" can mean either form of the representation of the stored Unicode reference number for each character.

    Now that you have all that info, let's discuss "types" of character references and how to use them. Once you have added your meta tags and are using HTML5, you can be confident you are telling most browsers you are using UTF-8 (see my HTML5 element section on <html>). Once you do, you are now free to start sharing Unicode characters directly in your page. The way you reference Unicode characters in HTML pages is variable. Other than pasting or saving raw Unicode characters in your HTML documents, the main way you can display Unicode is to bypass the encoding system and use "character references" directly. This technique allows you to use plain ASCII letters and numbers, in combination with a few special characters like "&" and ";", to represent Unicode directly. But you can also just push Unicode characters (like foreign languages) directly into HTML5 pages. The character reference Unicode alternative I have been mentioning was designed to allow you to use plain ASCII alphanumeric types in displaying Unicode without encoding or decoding, and is supported in nearly all legacy browsers and computer systems. But, to be thorough, there are four (4) main ways to use Unicode character sets in your web pages:

    1. Natural Text (example: €) - This is the simplest way to use Unicode, and represents the act of "pasting" Unicode characters directly in your web pages, either with a text editor or as supplied by the web server. An example of this would be translating your pages from English into a foreign language, like Japanese. In that case, you would need to simply store the translated text in a Unicode storage system on the server, then serve your page in HTML5. All modern HTML5 browsers would then represent those characters correctly. But, this is also the system most likely to fail if your users are not using an HTML5 or non-Unicode supporting browser with support for foreign languages. It could also fail if you do not have your charset correctly defined in the meta tags and server HTTP response headers, use the wrong fonts, or are using older browsers without multilingual capability (IE 1-7). The main point of failure would be the user not having the font needed to display your special Unicode characters or fails to find an alternative font with foreign language characters.
    2. UTF-8 "Named" Character References (example: &euro;) - If you stick with the "common" types of named characters, they will work in a wide range of new and old web browsers. If you use unusual ones, they are more likely to fail. Because so many common named character references have been around since the 1990's, they should work well and are recommended. An example would be © or &copy;, which has been used for over 20 years successfully in older browsers. Again, these work as they are still inside the ASCII or basic character set (minus 32 special characters in some older characters sets like Windows-1252 that Unicode does not use or support). Anything beyond those basic 256 characters would be problematic. Understand that the list of named references is very limited compared to the decimal or hexadecimal sets described below.
    3. UTF-8 Decimal Format (example: &#8364;) - This is the second most popular form of the "character reference" in Unicode and fairly reliable in modern browsers and in some from the past. These integers or decimal formats (Base10) are extremely reliable in any browser that supports Unicode, and that includes any modern HTML browser created the past 10-15 years. These numbers offer you over a million characters compared to the tiny number of named character references available for named entities. Again, the main problem using numbered references would be lack of support in many older browsers when using any non-ASCII characters sets or higher plane Unicode. So, try and avoid unusual Unicode character sets for widest browser support.
    4. UTF-8 Hexadecimal Format (example: &#x20AC;) - The advantage to using the hexadecimal version (Base16) is the numbers and letters are more compact, quickly parsed, and have widest support across all Unicode parsers today. But as mentioned above, these often limit browser support to the newer HTML browsers. As such, they work best staying with the more common character references. Note that these hex values can be written several ways, but always use the "x" prefix. Example: &#x0041;, which can also be written without the preceding 0's as &#x41;. Also note that, unlike many computer programs that use hex with a preceding "0x", that will not work for character references in HTML. In hex and Unicode, note that the format "x00" is UTF-8 and supports 1 byte. Each digit in this hex sequence is 4 bits (0000) or half a byte and each represents a 0-15 number or letter in hex. The larger version of "x0000" represents two bytes used by UTF-16 encoders. Both UTF-8 and UTF-16, however, can store up to 4 bytes and can represent larger Unicode numbers. There is also a CSS version of hex Unicode format that uses "\000000" and up to six hexadecimal digits. All these hex values are often translated into the decimal or numeric version by parsers. So, if you can access the Base10 integer for your hex Unicode. "&x41;" in hex would get translated to 65 in decimal: (16 to 1 power)x4 + (16 to zero power)1 = 65. That number then gets translated into its binary memory value of "0100 0001" (bits) which is one byte or one stored character number in UTF-8.

    Let's look at a few popular HTML "entities" in Unicode that have been used successfully the past 20 years. Again, these are simply single Unicode character reference that can be pasted directly into your HTML pages when you need to use a few special characters. They also work well in older browsers because they fall inside the popular strings of English ASCII character sets (256 characters) and map to the exact same numbers or "code points" as used in Unicode/UTF-8 (which HTML5 uses).

    • &nbsp; - This is my favorite "named" entity in Unicode! It is simply a "non-breaking space" character, and is the same as the keyboard space bar character. When you type spaces on the keyboard and drop them into an HTML file, every one you type that is not between words or objects in HTML pages gets stripped away and compacted to a single space characters by the browser. When you use this new space Unicode character reference these spaces get "glued" together and remain in the web page as a string of non-breaking line spaces. This allows you to drop these into HTML content areas and create spaces without them collapsing. Why would you need these? Often a "dummy" space is needed to force dimensions inside an HTML element to prevent it from collapsing, or as placeholder for content that will come later. One example would be empty table cells that now would have a space and this hold cells open, where a regular space would cause the cells to collapse. Note: always use the lowercase version of "nbsp" and in all other named entities, as they are case sensitive!
    • &lt; and &lt; - If you are trying to show HTML code to others, the "less than" and "greater than" named entities are also very helpful. There are numeric versions of these, the same as any name character reference. But I like the named ones as they are easier to remember. If you don't escape these, the browser will interpret them as HTML. XML parsers will also see them as markers for the start of XML nodes. So, use these whenever you need to avoid having them translated in web pages or in XML as markup.
    • Using HTML Instead of Character References - Here is an example of how to use Unicode "quotations", but where you might end up choosing a simple HTML element alternative, instead. If I wanted to create enclosed quotes I could simply copy the Unicode characters as "natural text" as so, “Hi there”. But that might fail in some older browsers that don't know these Unicode characters. A better way is to use "named" entities like “Hi there” (&ldquo; and &rdquo;). You could also turn to the large Unicode sheets that list the numeric forms of these quotations and use the "decimal escape" version, “Hi there” (&#8220; and &#8221;), or the "hex encoded" version, “Hi there” (&#x201c; and &#x201d;). But in this case, it turns out that the simple HTML element, <q>, supplies these quotes in a more reliable fashion for us already and is a better choice: Hi there (<q>Hi there</q>).

    If you want to use the full range of Unicode characters references in your web pages, simply Google it online. There are thousands of pages online listing the full Unicode code point sets and their numbers.

    One Final Note About Unicode and ASCII: As mentioned, some older web sites years ago used another form of ASCII called ANSI in Windows. All of ANSI's 256 characters seen in older HTML browsers and applications map ok to HTML5 and UTF-8 encoding EXCEPT 32 "special characters" that were proprietary to Windows. Those special characters - like the currency symbol, special quotes, trademark symbols, and others - DO NOT APPEAR in UTF-8. UTF-8 uses a different symbol set for those characters. That means where those characters were used might now show error markers today. In most cases, these old pages are either still delivered in the charset needed to display them using fonts that still support them, modern browsers still support ANSI, or the characters have already been translated to ASCII or UTF-8 versions. But if you see broken or jumbled characters in a web page, its likely because those special 32 characters are MISSING in Unicode and UTF-8 and should be removed or translated in the page to their equivalents in UTF-8. Until you do that, they are simply unknown characters. You can do that by either translating them to escaped numerical entity values or replacing the raw text with Unicode text which then maps those to their equivalents in UTF-8. So, just a heads up if you see broken characters in HTML5 browsers in some pages. Now you know why!

    Character Encoding in JavaScript

    Most young web developers building applications in ECMAScript today do not know how scripting works in terms of text and character manipulation. Creating these gigantic JavaScript API technologies, while not knowing how scripts decode web pages, is a strange aspect of today's web development environment. I want to show you how JavaScript works with Unicode and differs from HTML's encoding so you have an idea of how the two communicate and work with character data. It is this failure to understand decoding and encoding that is now causing problems in newer platforms like React, for example, and how it streams upper planes of Unicode correctly on its servers and in browsers. In the end, developers forget that manipulating strings and markup is all that JavaScript really does because the dominant media in 2022 in HTML is still displaying readable alphanumeric characters to Human Beings. Fancy scripting of web pages does not change that fact. This is why HTML and CSS will always have a longer shelf life than ECMAScript in web browsers over time, in my opinion, despite this desperate push to JavaScript the whole Internet. HTML is just a faster, more predictable, more manageable, more secure, cleaner, simpler technology than scripts when distributing millions of web pages and terabytes of data online. Can you tell I'm biased? I hope so.

    For now, I will skip most of the detailed discussion on general character encoding, storage of characters in bits and bytes, and the like, and assume you have a basic understanding of those terms. You can search for those terms online, if you need a refresher course. In this article, I am simply going to cover how JavaScript uses Unicode, how it decodes characters, and how that relates to HTML5's encoding system and its various markers. I found this topic completely confusing with very poor documentation online until I finally pieced together the answer of what is really going on. This discussion is in no way authoritative or exhaustive. But this may help you in your own understanding of JavaScript and HTML as you integrate the two together in your web pages and come across weird bugs and issues. The way modern browsers use ECMAScript to decode/encode HTML and character data is just not what we assume.

    The Mystery of Unicode

    Unicode is the future of how languages around the world are used on the Internet and beyond. "Unicode" is just that, a giant code table of all the characters of all the languages of the world and more mapped to numbers. Unicode is not about the "encoding" or "decoding" of characters, or their storage, or even about the display of those characters in web pages. Unicode is simply a giant listing that connects characters to over a million numbers (called "code points"). How those mapped numbers get stored in computer memory (in "code units" or bits and bytes) is what encoding does and what the technologies called "UTF-8" and "UTF-16" manage. But Unicode itself just controls the mapping of characters to their associated numbers. It is the Unicode tables that web browsers need when they use those numbers to then get the languages and characters they represent on computer screens. But it is the encoding schemes used by the browsers behind the scenes that matter; the script engines and markup parsers that parse, decode, encode, store, and extract those numbers over and over again in web browsers and servers that decides how well the overall character display system works. Get that wrong and everything is a jumbled mess!

    And so it is the "encoding" and "decoding" parts of this story that make this interesting. When Unicode numbers are given to a browser, for example, and get stored somewhere, they get put into bytes of "1's" and "0's" in your computer. When you see "UTF", think of it as a computer program that changes computer bits in memory to physical numbers and back to bits in memory again. Unicode translates the numbers returned in both systems into actual characters on a screen. But "UTF" is about how their numbers are stored and read. That is encoding. Unicode tables and "UTF" systems are two systems that HTML5, JavaScript, and many other computer languages use together when reading, encoding, decoding, and storing characters and numbers in your web pages. Unicode and UTF working together is what displays HTML page layouts, runs JavaScript movement of textual data in and out of the Document Object Model, and displays all the pretty characters and numbers you have been reading on your phone or computer screen.

    As a quick example, this is what code looks like when translated from various numerical formats to a visual character. The first number is an HTML-friendly "entity" that directly translates into a Unicode number that directly translates itself into a character the browser displays.

    &#x2665; = \u2665 = ♥

    There is a slight difference between the two encoding systems, UTF-8 and UTF-16, the most popular Unicode encoding systems currently used on the Internet. It is important you understand them in case you start building large websites that use foreign languages or characters and run into issues with garbled characters returned. If that happens, know that it isn't a problem with JavaScript, HTML, Unicode, foreign languages, or your choice of emoji characters. It is most likely a problem with how you encoded your web pages then decoded them using UTF-8 or UTF-16 in HTML and JavaScript.

    UTF-8 is the simplest system to use when encoding Unicode numbers. Such numbers are called "code points" as they represent actual characters you see in web pages. When UTF-8, for example, reads a letter it translates that into a Unicode number using the Unicode table. That number then gets translated again into memory or on your hard drive as a 1-byte or 8-bit number stored in binary (example: "A" = 65 in Unicode = 0x41 in hex = 01000001 in bits, the language of computers).

    In the old days of personal computers (1980's), everything in the English language and in numbers 0 to 9 was stored in an encoding system called ASCII, which also used a full 1-byte of memory (actually 7-bits of its total 8-bits was used). It could support 256 characters in that byte of memory, so supported the full English character set, numbers 0-9, and a variety of extra characters. (You can read more about ASCII online.) After ASCII came on the scene, every language and country tried to come up with their own mapping files to their own characters and numbers, creating a mess. Each code file that mapped numbers to characters meant operating systems like Windows had to store all those code files and pull them up when a foreign language had to be decoded and displayed.

    Unicode was invented to put all those mappings into one code file and simplify everything. Unicode now maps to 32-bits or 4-bytes of numbers representing every possible letter, number, and character conceived (over a million unique characters!). I have read only 130,000+ of those code points are actually used, so it has room for many more! When HTML5 was introduced they decided to embrace the Unicode standard by using the most basic encoder for Unicode they could find that would use the least memory possible. That was UTF-8.

    UTF-8 starts with 1-byte to hold all the basic ASCII characters and goes to 4 bytes as needed when storing upper level Unicode character numbers. UTF-16 works exactly the same except for one major difference: UTF-16 starts with 2-bytes instead of one as the minimum bytes needed to store even the simplest of characters and goes up in pairs of 2-bytes to 4 bytes like UTF-8 for higher order character numbers. What that means is they work close to the same except for that extra byte needed for UTF-16 when storing lower order characters like ASCII. Remember, ASCII is 1-byte so fits perfect with UTF-8 as it and ASCII store basic English letters and numbers exactly the same in computer memory. But UTF-16 would start with 2-bytes. Because of UTF-8's compatibility with ASCII in terms of byte storage, HTML5 (which by default always uses UTF-8)easily works with old web pages and scripts encoded in older ASCII systems, Latin-1, Windows-1252, and other English character encoded systems. HTML5 has thus become fully backwards compatible with older text and technologies for storing text, markup, and scripts using UTF-8. You never see any issues between HTML5, HTML4, XHTML, etc because of this cross-compatibility with older 1-byte, 8 or 7 bit storage number systems. That is important! UTF-16 reads ASCII perfectly fine, too, but it is that extra byte it uses in storage that means UTF-8 and UTF-16 cannot read each others values from storage reliably with out "decoding" each other first. It might be that most of the time they can get away with it as the extra byte in UTF-16 is usually ignored by UTF-8 when reading ASCII numbers. But it comes with risk.

    Remember: UTF-8 is not UTF-16 when it comes to storage of character numbers!

    If a small Chinese character or emoticon got pasted into your English text and the decoding systems were either ignored or it was assumed all your text is 1-byte character code, you likely would see lost or scrambled characters with the wrong code points when you retrieve your text back!

    Decoding Between JavaScript and HTML

    JavaScript (ECMAScript) supports Unicode like any other modern computer language does. But, JavaScript uses a UTF-16 "encoding" system when reading and storing its Unicode numeric values internally. As we mentioned before, HTML5 uses UTF-8 for reading and storing its Unicode numbers. Both encoders are designed to read these character numbers encoded in other schemes through the process called "decoding", which translates characters number from one encoding into their own number and memory scheme. As long as they are told accurately what those encodings are "encoded" in, they can decode them accurately. They know how to encode their own Unicode numbers, but they might not know how to decode others. That is why most systems fail when this process of knowing what someone is encoding in fails or gets misinterpreted. If a piece of software, like a JavaScript engine, does not know or cannot figure out the encoding of a foreign document, data stream, or string, that is when trouble starts simply because it might translate those bits into the wrong values.

    In the "olden days" of the Web, around 1998 when JavaScript came online, it was decided JavaScript should use UTF-16 and start with 2-bytes for every known character and move up to 4-bytes (variable length) when supporting the full set of global characters in Unicode. This is how JavaScript and ECMAScript was designed long ago so it would not run into problems parsing the first 65,000 characters supported at the time for a typical 2-byte sequence, potentially supporting global languages back then using various encoding schemes. As mentioned, HTML5 today supports UTF-8 encoding and storage, initially using 1-byte of memory for its code point numbers. It would only support 256 characters in storage initially, but go up to 4-bytes like UTF-16. And so today there is a small gap between how JavaScript and HTML5 store Unicode characters. Despite their encoding differences, however, that is not a big deal. I will explain why.

    Modern JavaScript "engines" in browsers, when it comes to ASCII characters (a-z, 0-9, etc), uses UTF-16 to read and manipulate them, but doesn't always store them in 2-bytes. Most developers don't realize that. JavaScript in many scripting engines (Like Chrome's V8 engine) uses UTF-16 when it reads its own source code as well as HTML and text in 2-byte block increments. But it still may store many of the lower order characters, like ASCII English characters, in only 1-byte like UTF-8. That doesn't create a problem when JavaScript decodes UTF-8 in HTML5, as all English text in ASCII matches UTF-8's 1-byte sequence, anyway. Old browsers and web pages encoded using old ASCII-friendly code pages, like Latin-1 or Windows-1252, also use the first 128 characters of ASCII and UTF-8 in memory, so are often interpreted and stored the same as ASCII sets as they all use the same numbers. Many common open-source JavaScript engines developed since 2008 still run many of the scripting engines in browsers, and translate the first 128 character numbers stored in 1-byte / UTF-8 quite easily. JavaScript engines like V8, I have read, now store these ASCII characters as 1-byte for speed, for example, and do not use a true UTF-16 storage mechanism for ASCII lower "plane" characters. Otherwise, they do use UTF-16. The main thing you need to know in understanding the two systems is that they work in harmony with lots of fallback mechanisms in place, especially when encoding and decoding strings and code used between them that involve the core English language characters and their numbers associated with old ASCII.

    The problems start when JavaScript reads upper plain Unicode numbers (not ASCII numbers) stored or embedded in UTF-8 web pages.

    Example: If your HTML page or script file, encoded with UTF-8, stores the "¢" or cent character (an upper level Unicode character, btw) directly in the file, in UTF-8 that becomes a two "code unit", or 2-byte set, as "\xc2\xa2". If JavaScript decodes it from UTF-8 correctly, that double-byte value gets encoded then re-encoded in JavaScript's UTF-16, or 4 such hex set, as "\xc2\x00\xa2\x00". That is how it is supposed to work!

    Decoding HTML5 Characters The main way JavaScript and HTML interact is through the decoding of each other's values (often using byte streams) then encoding them back into their native encoded values in memory. But both parsers and engines that read JavaScript and HTML in browsers and on servers have many ways to detect each others encodings. It is those detection schemes that make the whole process run seamlessly. It is when those schemes break down that you see problems. So as long as they sniff each others encodings in UTF-8, UTF-16, Latin-1, ASCII, AND those pages and text are encoded correctly, your browser, computer, and server will know how to correctly translate them. If that communication breaks down, that is when characters are scrambled or get lost. That is what happens often in foreign language systems. The extra memory or bytes USED between UTF-16 in JavaScript and UTF-8 in HTML5 does not really matter that much. It is how they are decoded that does. It is when you start trying to decode or encode these higher order "planes" of Unicode characters you might get tripped up between the two systems if you do not tell HTML and JavaScript what files are encoded in or fail to encode them correctly in the first place. That encoding issue is a common problem in IDE's or software systems web developers use to create web applications, as most encode, or don't encode, the same or consistently. That inconsistency is what trips up some developers when using higher order Unicode languages on say English-speaking computers or platforms. As long as they are encoded right, everything works. When they do not, it does not. So keep that in mind.

    For example, when you create a JavaScript "source file" with JavaScript code for your web page to link to, or type HTML markup in an HTML file with special characters or icons, in most modern software applications your file and its characters will either be encoded as a UTF-8 file explicitly or will be closely associated with an older format like ASCII or Latin-1 on English-speaking platforms that does not know how to save or encode these special characters. That is when problems could occur. For now, let's assume the software is using UTF-8 so can encode higher Unicode characters correctly. That script file with special characters is then saved and encoded as UTF-8 text and placed on the web server for your web page to consume.

    When JavaScript in your browser downloads the UTF-8 file and tries to read it from the web server, it will sniff the file using various techniques to figure out which of these encoding systems its encoded in. It will then decode parse the file, decode it, compile it, and run it in memory using its UTF-16 encoding system. This is a seamless process. Most JavaScript engines now expect script files in your web pages to be encoded in UTF-8 or ASCII by default and so just decode and re-encode all of its script files stored in UTF-8 to UTF-16 very quickly. As mentioned above, most encoders simply store each character in a single byte, anyway, if its using standard ASCII lower order character numbers. If any of these files or code have higher order foreign languages in them, those characters will require 2-4 bytes in storage, however. It is then critical that the numerous extra bytes needed to store them in JavaScript's UTF-16 decode the UTF-8 correctly. As we mentioned, if that gets handled wrong, that is when problems could start in your web pages or in JavaScript. But let's discuss the process of decoding in detail below, so you know how that translation actually works in a hierarchical fashion when reading simple script or HTML markup pages.

    Before JavaScript can process its own scripts (either inside an HTML page or downloaded via an external link), the file containing those scripts must be loaded into the script parser as UTF-16 encoded character sets, first. To read and decode all this text, a careful set of processes runs to download and decode the script file as follows:

    How JavaScript Decodes HTML Markup, Source Code, and Page Text

    1. Before JavaScript can take characters and encode them in its native UTF-16, it must decode the web page first. The web server takes top priority in this process (much like determining HTML encoding types) in telling JavaScript what the web page is encoded in, the HTML markup is encoded in, and what the accessory JavaScript "source code file" is encoded in.
    2. When a user's browser first calls the server for the HTML5 page and its JavaScript code or script libraries, the web server will send it the "Content-type: type/subtype; charset; boundary". This is usually in the form: "Content-type: text/javascript; charset=UTF-8", the "media-type" for the file sent in two pieces, and its "charset" encoding scheme (usually UTF-8 in 2022) for the web page. The server sends this with every JavaScript file called. This will be delivered with the web page and each script file in the HTTP Header that is sent to the browser from the server with each file. Today, the "new" recommendations in HTML5 says the MIME type from the server for HTML markup and text should be encoded in UTF-8 and have a file type of "text/html" for the web page, and "application/JavaScript" for the script files. Either scenario could be true or false in modern servers, however. But this is the first step towards getting the encoding type.
    3. How the HTML and JavaScript files are encoded that are sent to the browser from the server also matters, however. In most cases, using English/ASCII characters will not ever matter in confusing the file types and encoding. But say you add Chinese characters and used a custom older encoding scheme that doesn't use Unicode mappings? In that scenario, such a file maybe delivered could be incorrectly delivered with a "charset" of UTF-8 by the server, but its internal characters are now incorrectly decoded by the JavaScript engine because they in fact are either lost or the numbers represented by hexadecimal pairs sent from the server are wrong. If your server says to expect UTF-8 (the modern usage for HTML) but you pasted in characters encoded from older software that uses another format thats not encoded in UTF-8, the bytes of numbers that are stored would be decoded incorrectly. And so the character code point mappings Unicode needs are now lost. If this is live or streaming character data it would be lost forever! To fix that data to UTF-8 you would need to save your HTML, script, or text pages in UTF-8 in your software and save your web page in the UTF-8 encoding, again. This is just one of many examples of how a correct, modern encoding was sent by the server but data encoding did not match.
    4. JavaScript files loaded via script tags work the same way as above. The encoding of the file and the type sent by the server must match. In the case of script files, Javascript parsing engines often try and discover firs the "type" of file being sent, as it give the parser clues as to how to get its charset. The newest "content-type" often sent by the server for these script files is "application/JavaScript" along with "charset=utf-8" (not the old "text/javascript"). The server would deliver this type via HTTP to the browser and its scripting engines, and the JavaScript engine would recognize it as a valid script file ready to be parsed. It would then read the "UTF-8" encoding, decode it, and encode it into its native UTF-16. It could then parse, compile, and run the code, perfectly. If you saved your JavaScript source file with a different encoding than UTF-8 (what the server said), as above, and it had upper level Unicode, it could be jumbled and cause a nasty scripting error in the browser. As mentioned, because most ASCII and Latin-1 older encodings use 1-byte blocks and match perfectly to UTF-8, JavaScript likely would still decode it correctly even with the wrong type. That is why you will rarely see code issues in JavaScript using English character sets. It is using higher order languages that this could be the source of your issues. But at this stage, it is up to the server here to give JavaScript engines the right information to gather their own script libraries online and decode them from UTF-8 to UTF-16.
    5. If the server fails to deliver either the "right" encoding or no encoding, the JavaScript engines in browsers today have other places to look to figure out the right encoding. As mentioned above, the script engine that calls the JavaScript file is used to help JavaScript determine how to read source code and translate it into UTF-16. But if this is lost from the server, you can add an attribute of "type=text/JavaScript" or "type=application/javascript" to the 'script' element in HTML. It works the same as the web server in telling the scripting engine the correct file type to process. You can also add "charset=utf-8" and the engine will use that to help it decode your file, as well. It is possible to encode your JavaScript file as UTF-16 and then change the charset in the script tag. But I don't recommend it, as you could end up having the server send it as UTF-8, anyway. In addition, because of the support issues with "application/JavaScript" in older browsers, HTML5 recommends you just leave off type="text/javascript" from the 'script' tag and allow each browser to use its own default value. Old browsers would use "text/javascript" and new ones "application/JavaScript". I still use the 'script' tag attribute with "type=text/JavaScript" as I like supporting older browsers, who by default might not know the newer MIME type. The reality is that browsers and JavaScript still rarely use the "type" on the 'script' link element, anyway. Another issue found in older browsers is the fact they use the old default JavaScript file type and so likely use ASCII or Latin-1 encoding types when their old script files were created 20 years ago. Old Browsers will not know what that the new "type=application/javascript" is and possibly fail, so need the old type anyway. Right now that is mainly an issue in Internet Explorer 8 or lower. Again, because ASCII and 11-byte encoding English systems are forwards compatible with UTF-8's 1-byte encoding and storage systems, if like would work fine with no encoding or the wrong encoding sent to Javascript in the browsers. That is why, you can still use the older "type=text/javascript" format and it will not break anything. It is still widely supported for identifying JavaScript files in old and new JavaScript browser engines despite the newer HTML5 standard. It is when the day comes you try and save Unicode upper plane characters in these older encoded files or formats that problems would arise. So, try and stick with UTF-8 encoding in all your files.
    6. If the above issues fail using the server or 'script' element attributes, JavaScript looks to the meta tag "content-type" and "charset" values in your parent HTML page to determine the encoding type for both the script files and HTML page it downloads. The scripting engine then reads the HTML5 "<!doctype html>" doctype, which by default tells it to use UTF-8 for decoding all text. If that too is not found, then the encoding looks for meta tags in the page. You can actually now store all your encoding and script types in meta tags. Again, in most cases, your JavaScript engine will have determined the right encoding, but having these meta tags could help:

      <meta charset="utf-8" />
      <meta http-equiv="content-type" content="text/html; charset=utf-8" />
      <meta http-equiv="content-language" content="en-us" />
      <meta http-equiv="content-style-type" content="text/css" />

      There is one case when having these meta tags may make a really BIG difference in helping JavaScript decode your script and HTML pages. When foreign users view your web pages, the script engine looks for any number of encoding systems to support translation of English encoded data to upper level foreign data. Often it can look to the HTML page first when deciding those charsets. This is why when delivering web pages to foreign language users, without a meta tag or server encoding, you could run into problems displaying and using encoded Unicode higher level character sets, not just in JavaScript but in the HTML decoding system of the browser, as well.
    7. Lastly, when JavaScript reads pages, there is often a fallback mechanism all software systems use to detect encoding schemes in documents that goes beyond just web pages. Often in external documents that get opened frequently by 3rd party software, there is a hidden BOM or "byte order mark" at the top of the file. This BOM determines what encoding system was used when the file was created. Both the "endian" binary reading direction and the file's encoding are conveyed in the BOM. The endian byte order usually applies just to UTF-16 encoded pages, as the 2-byte system often requires it when reading multiple bytes to extra larger numbers. But the BOM often is the fallback mechanism the scripting parsers use when deciding how to decode files when all else fails. Other times, that BOM is stripped away. It depends. But it is one of several tricks the web browser and its parsers can use to determine what the text in the file was encoded in.

    As you can see, JavaScript and your browser have a rich set of tricks to use to make sure it decodes your character data correctly into its native UTF-16 number storage system. When JavaScript decodes your text files, its source code, or its script files into UTF-16, the script engines and parser in browsers figure out how to do all that using one of these many techniques above to make sure characters are encoded and decoded properly. So it has lots of fallback mechanisms to make sure that translation to UTF-16 is fluid and accurate. In addition, I read that the "V8" JavaScript engine behind decoding and encoding of pages actually stores all your HTML markup and DOM ASCII strings as true ASCII (like in UTF-8), so code like HTML tag names do not double in size and are easily transferable between encodings. With these particular byte sequences you don't really have to worry about how the actual bits are encoded. Source files are expected now to be encoded by default with UTF-8, as are all new web pages delivered by the web server. So in the end, the movement of characters between HTML and JavaScript are pretty seamless between the two encoding types now and should not cause issues. Just remember to encode your files in UTF-8 and JavaScript and the web server will handle the rest quite efficiently!

    As I mentioned many times, because 99.9% of English uses the old 1-byte 128 character ASCII set, they translate one-to-one in all encoding types, for the most part, without ever having any real issues in all these decoding systems. So you are doubly safe! It's when you use other higher-level Unicode numbers, languages, and characters that you may have to be vigilant and make sure your script files are encoded correctly and follow the rules.


    Last thing, you can skip many of these encoding issues in HTML and even JavaScript by using "character references" to specific Unicode characters directly in your page! If you need a couple emojis or special characters in your web page, rather than pasting them into UTF-8 encoded documents and risking tripping up UTF-16 in JavaScript, you can use these entities directly as they do not require decoding! These are actually interpreted "codes" written in plain English-ASCII that can be translated directly into Unicode by the browser and any JavaScript parser, bypassing decoding/encoding completely. I use these a lot in HTML for special characters or icons I need, but where I don't want paste the original character into my web pages or wrestle with a possible encoding issue between UTF-8 and UTF-16. These take several forms, including HTML "escape codes", "named character references", or "entities". In general, all these point to the same characters using numbers with an HTML-friendly prefix, like "&" that triggers the parser to translate them into Unicode directly. These are often in numeric or even text name flavors, both which work the same in displaying the character or emoji you might need! They are also easy to remember and quite helpful in pages that need glyphs, artwork, foreign currency, or other special characters.

    This Unicode entity below is 100% safe to use. There are thousands more online you can Google! Just paste your Unicode character reference into your web page using the ampersand numeric or text name version, like so:

    Use "&copy;" for the © copyright symbol

    What is LOCALHOST?

    Before I go into this complex knowledge-share about such a simple subject as "localhost" below, let me clear up one thing about new technology today that has increased confusion. This "localhost" information below is just some of the strange changes that have occurred recently when working with technology on modern OS's in 2022 that none of these companies bother to tell you about. We are all supposed to have all this shared intuitive "inside" knowledge in this industry, which is silly. As Einstein has noted, if you cannot explain something in simple everyday terms, its meaningless to millions of people. Truly intelligent people know this. :)

    "localhost" is often used by developers when building websites on web servers located on their personal computers. Developers often set up a local development web server on their computer, assign the loopback "localhost" domain name to it, then test their web application in their browsers using "localhost" before pushing them to live web servers online. The "localhost" name is thus assigned to the developer's default web server. But "localhost" is a strange little name, one missing the usual dot syntax of standard URL's yet often having a long port number attached (example: http://locahost:12345). Over the years, I have seen so many people confused by "localhost". So let's lay out the facts so we all understand how "localhost" works. To do that, I want to cover some helpful info on "localhost" and loopback IP's to help with the confusion, as there is a lot of "junk info" thrown around online by a lot of people that is incorrect and incoherent.

    "localhost", when typed in a browser or resolved in your computer, simply refers to your local machine. Often network people will just call it "local" or "home". It does resolve to a number of "internal" IP addresses. But those often point back to your computer again. When typed into the URL of your browser, it is not supposed to go out onto the network or Internet and resolve via DNS, however, like most URL's in the browser will do. It is not even supposed to go through your network card or NIC and seek resolution beyond your local computer. It is simply designed to bypass the network and map back to your local computer. But strangely, it can resolve outside the network, as we will see.

    "localhost" is sometimes called "local", which implies it maps directly back to the application or computer that called it using an internal IP assigned to it. This is the local machine, as mentioned. How it does that varies by OS and device, however. By default, "localhost" should NOT connect to the network when resolved from your browser. It should not go through your NIC or network card, or even through the firewall or be contained by any ports used. It also carries with it your full "local user access" credentials in terms of computer permissions, as opposed to network user permissions when a true domain or IP is used in your browser. As such, use of "localhost" carries with it special privileges, and so should be free of network, IP, firewall, or user access restrictions with all ports open to it. "localhost" seems to have a lot of freedom and power on your computer. That's important to know!

    As I mentioned, "localhost" is often mapped to a "loopback" address or IP, either internally on the computer via the OS, using some network addressing system, using special software, or some other internal DNS system. It depends on the server and device. In the past on personal Windows computers, this was handled by a simple text "hostname" file called "hosts" (%systemroot%\system32\drivers\etc\hosts). But since Windows 7, this has been disabled and now managed securely by other OS systems on personal computers. This was done in order to address security concerns and prepare for replacement of IPv4 with IPv6 where old loopback IPv4 address would no longer work. Often these internal PC systems control a priority IP mapping list for "localhost" thats secure and prevents malware or outside network devices from connecting to the network as "localhost" or an internal IP from getting access to the network. These new systems still work with the host file, but control mapping of "localhost" to "::1"(IPv6) and "127.0.0.1"(IPv4) network "loopback" addresses elsewhere by default. It is important to realize, when you type the IP instead, these loopback IP's go through the network layers while "localhost" does not. The "localhost" loopback interface bypasses have special properties that bypass any local network interface hardware or NIC, and allow software internal to your computer to listen to this "internal" domain name and resolve it.

    Below are two optional "host" file entries you may see commented out in your host file (%systemroot%\system32\drivers\etc\hosts). In the past they would map the domain name "localhost" to loopback IP's that route the name back to your computer. In Windows this is now handled by your computer's OS internally:

    127.0.0.1  localhost
    ::1        localhost


    You can test still test if these mappings are still assigned to "localhost" by typing in a command prompt on your computer the following: ping localhost (uses whatever IP is assigned to localhost, but often returns an IPv6 number like ::1, which is assigned to locahost internally) or ping -4 localhost (forces ping to use IPv4 and often returns the IP of 127.0.0.1 assigned to locahost internally). If you see the two IP's assigned in your command prompt they are already mapped for you!

    "localhost" is often by default also mapped to your local computer's various listening devices or software (i.e. your local web server), but the internal IP's above are not. Confused yet? Windows IIs on 7, 8, and 10 will have no binding by default to these internal IP's, only "localhost". This is usually limited this way for security reasons now by the operating system in your computer. "localhost" is a pointer back to your local host or the computer independent of any internal IP assigned to it. In addition, "localhost" uses the loopback or "virtual network interface" created by your operating system to bypass your computer's network hardware, like your network card or NIC, and loopback to the computer itself (always over port 80, by the way: http://localhost = http://localhost:80). In addition, IIs Express's web server in Visual Studio connects and works in the browser URL with "localhost" but without "127.0.0.1" or IP resolution, by default. You can change the configuration on your web server to accept these special loopback IP's (see below). But "localhost" will resolve to the web server without it. The same applies to IIs on a Windows Server. The loopback internal IP addresses associated with "localhost" are often not supported out of the box on internal default web sites. Typing "127.0.0.1" in your browser will often fail to connect to your server, for that reason.

    "localhost" has nothing to do with outside browsers and computers in your network that may try and connect to the default website on your local computer. Remember, "localhost" refers to your computer using its "internal" IP's, not from any "external" IP's, the latter which resolve outside your computer. Your computer can be assigned several outside IP addresses, depending on your network, NIC card, etc. One is supplied internally by your router or corporate network using DHCP. But your router is assigned one externally using a "static" IP assigned to your network (i.e. router) by your ISP or host provider. That means, if you are inside a network, like a home DHCP router where the router has assigned your computer an IP (like 192.168.1.75), your computer name and its IP would still be accessible by outside computers inside your network, but not your web server assigned "localhost" internally. It is only mapped to "localhost" and accessible via your computer. Notice again, your internal loopback IP's also will not have access to your web server and website by default, either. That is because your web server by default will not accept ANY IP, internal or external. It only responds to the loopback text string, "localhost", by default. When any device (even your own) uses those DHCP IP's to try to connect to try your local computer and or web server, the ping packets will pass through your physical network interface, try and connect to local IP and your web server, but fail. Just realize that "localhost" has nothing to do with control of your web server or access by outside IP addresses or even your NIC card. Your local web server by default only requires the "localhost" Host Header name sent by your browser and the virtual loop back interface on your computer to directly resolve. When you type "localhost" in your browser on your machine, the browser sends the packet requests and a default port without any name or DNS resolution call, physical hops, network calls, router calls, or special IP addresses when connecting to your local web server.

    Use of "localhost" is thus a very different system than how traditional browser URL's and IP's resolve. It took me awhile to fully understand that because I assumed everything resolved across the network using IP's, even if locally resolved. Not with "localhost". It is a special baby, indeed!

    The strange thing is, the domain called "localhost" also exists outside your own computer in external networks as well, including the World Wide Web. They say it is a reserved domain name intended for local IP address resolution only, representing the current computer it is used on. But some network admins will tell you that "localhost" is also a top-level domain (TLD) online. Others say it's simply a "hostname" local to your home computer only. But oddly enough, both are correct! It does act like a true "domain", like the ".com" name, and has a reserved one called ".localhost", too! It has to resolve this way in cases where DNS calls "leak" out onto the web looking for "localhost". As such DNS experts have asked local DNS systems and network admins to always assign "localhost" to their own domains and subdomains by simply attaching ".localhost" to the end of anyone in a network with a domain trying to call outside a computer for "localhost". Doing this prevents DNS systems from attempting to resolve the unknown "localhost" domain and prevent it from seeking resolution outside the network to the top level DNS servers. That allows for special cases where non-Windows or other PC's that don't capture these local unresolved domains correctly flood the Internet trying to find unknown "localhost" website domains online (like http://mysite.localhost/)

    So, if "localhost" is mapped internally back to your computer, how is that managed and how can you customize it, and why are we stuck with this weird loopback name with no IP? As I mentioned, "localhost" is often mapped to a series of loopback addresses internally on the computer to prevent it from being leaked out onto the network. In the past on Windows computers (before Windows Vista), this was handled very simply by your hosts (see above) file. This host file still works. But since Windows 7, this has been disabled and now managed by the OS. This new internal PC system now contains a sorted priority IP mapping list that's controlled by the Windows registry settings. It allows for the new IPv6 protocols of the future to also be assigned "localhost", but also prevents malware or outside network devices from connecting to the network as "localhost" using an internal IP and getting access. (so kind of a security fix?) This new local IP mapping system has meant the old "host" file entries for "localhost" are no longer needed and commented out, causing even more confusion!. The top IP's now mapped to "localhost" by Windows is "::1" (IPv6 loopback), one of several internal IP addresses, I am told. Most software systems will only listen for the native "localhost" header anyway, ignoring the IP. But just know, you can still open the host file and map additional IP's to "localhost", even external ones your browser might use, especially after you update your web server to listen for the internal IP addresses (see below). Keep in mind when it comes to your local web server (if you use one) still isn't mapped by default to these IP's nor does it listen or accept any of them, even if "localhost" is mapped to these IP's, internally.

    The problem with using "localhost" to resolve browser URL's or other software is it's not really a true URL that gets resolved externally in DNS with normal packet processing and name resolution like most public websites do. As such, it makes testing web sites difficult and inaccurate from how a typical HTML website and server might perform using DNS, routing to servers in and out of networks, carrying security like SSL/TLS, etc. It has really become quite a mess for web developers! If the "localhost" name is used for testing, its local to that person's machine only and their web server, which now cannot be accessed or shared with anyone else to test externally. It also bypasses the "Host Header" web server system where an IP and hostname work together to resolve what a web server receives as far as the request goes coming from the browser. As mentioned already, IP addresses by default are not resolved in a typical web server running on a Windows computer now. More on adding that below...

    "localhost" has other strange features in Windows computers. In Internet Explorer browsers, when inside a Windows network but on your local computer, typing any name in your browser's URL string - any text string without "." dot representing the physical name of a computer or server on the network - tells IE to pass your "local access" Windows credentials to whatever computer or web server is mapped and listening to that name on your network. This includes the name "localhost". So typing that name in your browser will also pass your local user credentials into the browser to authenticate with your local server now, with "elevated" privileges! Again, thats atypical of how most web servers authenticate users. If you go outside your computer to a computer or web server elsewhere in your network using such names of boxes (without a "." syntax in the name), IE will again pass your network user privileges as it goes through your network card. These windows credential systems thus apply to non-localhost names, too, and to any server name or IP that gets resolved or routed inside a corporate network where a domain name resolves (example: http:/bob/ would take you to the "Bob" computer name in the network, looking for a listening web server on "Bob"). In that case the browser again passes your network credentials because the URL has no "." in the name and assume its only local. For this reason, in the old days, we used to create intranet corporate websites inside the network on machines (like "SpongeBob", "Homer", "Bart", etc.), add Windows Authentication to their sites, then add their server names in the network with known IP's to our host file or via corporate DNS so users could route to the IIs servers from those named boxes. But we had to add the IP of the box to the web server so they could be read externally. "localhost" was then not needed locally when developing sites, just the IP or box name added to the web server. We used the box names with the advantage that credentials were passed in Internet Explorer, too, allowing anyone in the network could access each others servers. But again, "localhost" did not help us with any of this.

    In this sense, in the "Microsoft World", "localhost" behaves like a network name in terms of Windows Authentication, but not as a true external website URL where such authentication and credentials were passed using network box names. That is why on Windows, "localhost" appears to behave like any other computer name, passing credentials like any network address name does in the browser, yet only locally. Its like a "second name" for a computer every computer now has. It's no different than having a computer on your network, typing it in a browser, and seeing a computer name appear with all its public web sites and shares listed. The one difference here is that your credentials on your local box allow full local access, not domain-level network access. So your rights are increased when using "localhost" in terms of logging into your development website. That is how localhost is designed by default on Windows IIs. It is setup with your IIs web server to listen for "localhost" and give you full access "user" access (and often administrator access) beyond what a typical client-server exchange should have. If you try the loopback IP of "127.0.0.1" (having the "." means no credentials are now passed to "localhost" websites) in IE browsers, or via a real IP address in the browser, it assumes you are routing somewhere using an IP (even though its a loopback address), and thus seeks an IP on or off your network, and so does NOT send your credentials over the wire. Wow, that idea added more confusion for me. Because "localhost" is a special loopback IP address unique unto itself, it resolves internally on your computer but doesn't pass credentials like "localhost". And as we have seen, may or may not resolve to locahost in the browser or to a web server, unless manually added. That is because your computer is not resolving the IP to "localhost" like a normal DNS would. Nor is your web server set up to listen for the "127.0.0.1" IP, either. That is why typing that IP often fails to resolve to "localhost" in your browser OR find your local default web server and website setup by default with "localhost" (Host Header to your local web server using just the IP is thus lost). But the main idea here is that credentials are also not passed like in "localhost" using the loopback IP of "127.0.0.1".

    By default, your local web server, IIs Express, or IIs does not bind to any internal or external IP's, which was new to me. So, typing "127.0.0.1" in a browser will fail, by default. As mentioned, "localhost" is a unique name so could be bound to a number of different internal IP's and loopback addresses. But that has nothing to do with how your local IIs web server is setup on most new computers with web servers running. The "hosts" file on your computer, however, can still be used to change that and map "localhost" explicitly to any IP you like. But often, by default, that's handled by the computer and version of OS you are using. For that reason, newer servers never use IP binding for "localhost", even the default and common IP of "127.0.0.1". So, if you want to resolve loopback IP addresses like "127.0.0.1" so they connect to your "localhost" website, it means you need to add these IP-localhost mappings manually to your hosts file first AND second change your web server binding settings so they listen to any IP address you assign to localhost. That idea threw me for a "loop" when I first started typing "127.0.0.1" in my browser and it failed to connect to my local website. I could not resolve the "127.0.0.1" IP to my "localhost" website like in the "old days".

    One of the tricks you can do as a developer to resolve this when using "localhost" and "127.0.0.1", since "localhost" is mapped to the loopback IP elsewhere behind the scenes now, is open up IIs or IIs Express and set the default bindings for the local website on your computer to accept "all unassigned" IP's (under "Bindings"). You then need to open your "hosts" file (%systemroot%\system32\drivers\etc\hosts) in Notepad or a text editor and add an entry "127.0.0.1 localhost" to the file and save it to make sure that binding is set on newer computers. Only do the latter if you feel that loopback address is not being assigned to "localhost" by the OS. Make sure you open the file with a right-click, then choose "Run As Administrator" before you do. After you do this, when you type the loopback IP in your browser, it will send the loopback IP to the server as normal, but your local web server and website will be listening to all IP's now when resolving the request. The serve is set to accept all IP's, so accepts any sent. If you use "localhost", the host header name gets passed to your local server as normal but now with the loopback IP and is resolved, as well. "Localhost" only does this because of this "host" file relationship mapping and change to your server binding and the custom binding you manually added in your web server's default website.

    Knowing how this crazy "localhost" and "loopback" IP system works took me some time to figure out. So, I'm passing all the nuances of this to you. Now you know! So keep all these settings in mind when using these internal network names and addresses. There are lots of weird and unassumed things going on under the covers that you must be aware of. Understanding how they work together is helpful when things break or don't resolve as you quite expect. Local development of websites in 2022, unfortunately, requires too much specialized knowledge from most new developers. This is because of the people since 2010 now building these systems and frameworks adding unnecessary complexity, breaking a system that worked fine before. They just refuse to think about how new web developers entering the field use these tools and assume everyone else has the same specialized and proprietary knowledge they do. It is a form of stupidity and arrogance, if you ask me. It is unnecessary. That is why I am here to help. Sharing this new information with you has now become mission critical to me!

    Web Browser Secrets and Goodies

    As I develop websites, I've discovered some tricks when working with HTML pages, servers, and browsers most developers do not know about. I will list these below. Try these below in your browser and see if they do not help you.

    1. Press the space key when looking at a long web page of content. It will quickly scroll a large web page for you without using the arrow keys or scrollbar.
    2. Hold the shift key with clicking refresh in the browser to force a re-cache of CSS and other elements of a web page. Often refresh does NOT reload changes in CSS or even HTML as browsers are designed with advanced caching systems now to avoid calling the server again.
    3. On caching, often a browser will not reload linked CSS or JavaScript, but will pull it from the cache. There are settings in the browser and the server that control this. For that reason, when developing HTML and CSS sites, I like to add a query string to the end of the URL in my link or script element to force a reload every time I refresh or reload the web page. To do this, generate a date-time value on the server and express it as a "time tick" so it is always a unique number. Append this number to a variable (like ?v=) at the end of your websites URL. Seeing this custom URL, the browser will always download a fresh copy of your CSS or script file and show any new changes, rather than the cached version in the browser:

      <link media="screen" rel="stylesheet" type="text/css" href="styles.css?v=637480615038941445" />

      When I go live with my website, I remove the time tick number, then use the same query string to set a "version" number so I can control caching on all my user's browsers. Changing this number in a slower increment using a version number I can force refresh of my style sheets or scripts instantly when their browsers don't recognize the URL string with the changed version number (example: ...?v=1.1.3)
    4. Holding the shift key when clicking a web page hyperlink opens the link in a new browser window, regardless of the links 'target' attribute. I like to do this now as increasingly, for search reasons, more and more websites disallow you to go to a new window or tab in the browser, but replace the current page with the linked URL. I think they figure they get more Rank "juice" by doing so. But you can bypass that behavior easily this way by holding down the shift key when clicking any hypertext link or when opening a new browser window.
    5. "." is the Root of the World Wide Web Do you know what the Universal Root Domain of the World Wide Web is? It is simply a hidden "." at the end of a domain following by an "empty string". The "." is the root of the web, globally, with an empty string after it. But the "." allows you to access it. You can test this by typing a period after any URL online like so and it will still work. You have just made a more complete URL with the universal root domain added: https://en.wikipedia.org./wiki/Root_name_server
    6. HTTP and Their Default Port Numbers: Did you know that all web site calls that begin with "http:" always use port 80, and all websites that use "https:" always use port 443 by default for secure requests? You can actually paste in the ports to any URL online and they work the same! You can test this by adding 80 or 443 after any domain on the web. The two URL's will both work with or without the default port number: Change http://example.com/somepath to http://example.com:80/somepath
    7. The Magic of the Non-Breaking Space in HTML! Often times in HTML, you may find yourself needing an empty space. Maybe you just need to create a quick extra spacing between some text, need to add padding to an element, or need to simply fill in some spaces into an empty collapsing element that just needs a placeholder inside it until content is added later. I use the non-breaking space (&nbsp;) for this all the time. You never type a "space" on your keyboard for this character, as browsers are designed to strip those spaces out when they parse your final HTML. Try adding thousands of spaces to your html web page and find out what happens - they all disappear! Not the non-breaking space character!! To create a true blank space that sticks around you must use an "entity" character for the space character. It creates the exact same space as the "space" keyboard character, but its not created until the browser interprets it. So its permanent. This type of entity character is also XHTML compatible, too, so always works in all types of HTML standards. You can also stack as many as you need together in long strings.

      For three spaces just add this code: &nbsp;&nbsp;&nbsp;

      Three empty spaces will be shown in your HTML. The magic of this simple empty character is it will force the browser to drop in a simple empty text space where you need it and will always honor it, unlike a text space from the keyboard which will in most cases be erased from the final display.
    8. Avoid Extra Trips to a Server by using Correct URL Paths! Most developers do not know this, but adding a simple "trailing slash" ("/") at the end of a URL path (one that does not have a file or page at the end) reduces an extra round trip the browser uses when hyperlinking to a server URL. Why? For starters, in many server systems a URL with and without a slash after the path (but not including "/" after a domain name) are considered two separate URL's. Second of all, search engines often rank pages with and without slashes at the end differently and could flag them as duplicate content. If you point to one version of a folder in a path versus another, page rank could be different for the site linked to. You want to be consistent. Lastly, and most importantly, if a URL does not point to a specific web page, and is not terminated using a trailing slash, a second round trip is made to the server from a user's browser! A web site without a trailing slash can still point to a page on a server, but is often not what the browser is asking for. A slash "/" following a path means it wants the folder and that there could be many pages under that folder, which the server would control and deliver to the browser. Without the slash, some servers try and resolve to a specific page and fail as they need to know if you meant a folder. They then reject the call and ask the browser to send a complete path with "/" at the end. Others assume a path and return it with the slash on the end, anyway. Today, modern systems return paths in most cases, but there are still many older ones that respond to pages, as well. Often, its better to just point to a specific page in your URL, if you know of one used by the server. However, many modern servers return just a folder path in every case, as URL's are dynamically driven from a database, not a physical folder or file on a server. Regardless of what convention is used, if a URL request is made without a slash and no web page is given in the URL, a folder with the slash is what was intended, anyway. If there is a second round trip requested by the server to the browser with the slash because of this, it is wasteful. So, I always put a "/" after my url's in anchor tags if no file in the URL is used and a folder or root URL is intended. In some cases it avoids hundreds of extra trips to servers in a user's browser! So to avoid this, add the slash. Example: "http://mysite.com/page" will often force a browser to try a second call using this "http://mysite.com/page/". So always add the extra slash!
    9. Adding Dummy Elements in HTML: You can actually create made-up elements and add them in HTML5! Your web page will not "validate" as HTML and may show an error in a validator online. But because HTML5 and its "living standard" has returned to tag soup you can get away with it just fine. Web browsers will simply identify them as dummy "inline" elements, much like a "span" element, but show their contents. They can also be fully styled using CSS and used like plain HTML in your web pages. Keep in mind, such tags are not validated and may also cause some weird effects in some browsers. There should be rare negative cases for using made-up elements like this, so I would not recommend you do this. But its another extra feature of HTML5 that is available to you, though this technique is non-standard. An example is shown below:
      
      <mynewelement style="display:block;background-color:#ccc;text-align:center;border:1px #000 solid;">Can you see the content of my new element called "mynewelement"?</mynewelement>
      			
      Can you see the content of my new element called "mynewelement"?

    10. Unwanted Spaces and "Empty" 'divs': Sometimes you may see weird spaces appear between HTML elements or objects in HTML. This was more common in the past than today. Often table empty cells, images in "divs", images wrapped by anchor tags, or menu lists created unwanted "extra" white space you could not erase! Use the following tricks to fix your HTML when these "mystery spaces" appear:.

      Images inside block-level elements are notorious for creating unusual spaces beneath the image where it touches the border of the parent. To remove these, simply line up the image with the parent tags on the same line:

      <div><img src="myimage.jpg" alt="" /></div>

      If you need to create a true "empty div" with no spaces in between, simply add an empty comment inside the div. Empty divs, with only a comment inside, will not add any default dimensions and truly disappear from the page:

      <div><!-- --></div>

      If you need to remove "weird" spaces that sometimes appear when viewing a HTML list as a menu, either line up all the elements on the same line to remove spaces, or add an empty comment between all tags in the list, as shown below. This trick allows you to keep your menu structure but remove all extra hidden spacing between elements:

      
      <ul><!--
      	--><li><a href="#">Page 1</a></li><!--
      	--><li><a href="#">Page 2</a></li><!--
      --></ul>
      


      Finally, for empty table cells we have the "td {empty-cells:show;}" CSS property now which allows empty cells to be shown and have dimension. But often this is not supported by the browser, or not what you truly want. Maybe you want a placeholder or space inside to hold the cell open until content can be inserted. In those cases, I recommend you simply add a non-breaking space inside. Just paste this character reference into your table cells: &nbsp;

    back to top