Guidelines for creating web platform compatible components

W3C TAG Finding

This version:
https://www.w3.org/2001/tag/doc/webcomponents-design-guidelines/
Latest editor's draft:
https://w3ctag.github.io/webcomponents-design-guidelines/
Editor:
Kenneth Christiansen
Participate:
File a bug
Commit history
Mailing list

Abstract

Web components allow you to create encapsulated custom elements on the web platform, but how can you make sure that those elements actually follow common guidelines in such a way that useful elements fit in well with the rest of the platform? The TAG believes this is important so that users don’t feel like they are dealing with mismatched APIs and also a requirement if any of these elements were to end up in the HTML standard.

Status of This Document

This document has been produced by the W3C Technical Architecture Group (TAG).

Please raise issues on our issue list, alternatively, you can send comments on this finding to the publicly archived TAG mailing list www-tag@w3.org (archive).

1. Common patterns

The web platform is not known for being 100% consistent, but there are definitely some recognizable patterns across the platform, like with regard to naming. Try to stay consistent with what is already used, like if other elements uses “selected” as an attribute for the same behavior, there is no reason to start using something else (say, “chosen” or “marked”).

1.1 Native HTML elements

In order to answer that, we need to look how native elements work, and what defines them:

  1. Elements don’t throw errors when used declaratively. Native elements don’t throw errors during construction or using regular DOM interactions.

    For example, they don’t strictly enforce their content model. You can easily add a div element inside an img element even if that means it won’t render or behave properly, it should never throw.

  2. Elements are self-contained. Elements come as part of the web platform and thus will work without requiring any other libraries.

    • Make sure your element is self-contained and ships with all its dependencies.
    • Are all paths relative to required resources (images, etc.) relative to the component source?
    • The elements don't depend on anything else (or any other element) being loaded before.
  3. Use events to pass data to the outside world. All custom elements inherit from EventTarget, and thus events can be used to pass data along, but please follow the guidelines in the DOM Living Standard §2.11. See also the TAG’s guidance on event design.

    • One way to structure your elements for usability is the "data down, events up" flow pattern, e.g. sending data down the DOM tree by setting properties/attributes on elements, and dispatching events, which bubble up the tree.
  4. Use attributes to receive non-complex data. Elements are configured declaratively as much as possible, which allows them to be used declaratively, as well as work great with template bindings.

    There are a few things to keep in mind though

    • Use boolean attributes for boolean values, ie <my-element selected=""></my-element> instead of <my-element selected="true"></my-element>.
    • Don’t use custom attributes for styling, like bgcolor. Instead use Custom Properties or CSS Shadow Parts.
    • If elements accept complex data like objects, arrays or streams, create a JavaScript API to deal with these.
  5. Interactive elements are focusable, and can be interacted with using a keyboard in addition to mouse/touch. Generally, make sure that elements are accessible.

  6. Elements can be instantiated without being part of the document. Element can be created from scripts etc before inserted into the document, so don’t assume that document APIs like parentNode will be available before connectedCallback.

  7. Elements should only have basic styling. Native elements are implementable by multiple browsers on multiple platforms, so they have only generic styling out of the box. Theming of the element might be desired, but should be separated out from the essential style of the element (and made extensible). Create the simplest style possible—at least as basic, if not more, than existing standard elements. We can call this functional styling in contrast to “theme” like styling.

    It would not be appropriate to encode a specific UI styling, like Material Design (Google) or Cupertino (Apple), into the element.

    It is appropriate to create styling hooks to allow elements to be themed to match popular styles, like Material and Cupertino.

1.2 Other considerations

Apart from following the properties of native elements, there are a lot of other ways to make an element fit well with the web platform.

  1. Don’t enforce unnecessary child/parent relationships. Even though your element is intended to be used in conjunction with another element, attempt to make it works as child of any other element, if that makes sense.

  2. Avoid using callbacks. Refer to TAGs guidance on promises.

  3. Harmonize declarative (HTML) and imperative (JavaScript) APIs.

    Attributes (HTML) form (part of) your declarative API; your prototype defines your imperative (JavaScript) API. Try to keep the analogous parts linked whenever possible so a user can modify either with the same effect. (eg. <my-element opened=""> or this.opened = true).

Elements can store values set via attributes or imperative APIs in the attribute itself, or in the JavaScript property or elsewhere, but should be consistent. Come up with a plan for state management and stick to it consistently.

Note
Note

Custom elements have the requirement that they need to contain a hyphen (-) in their name. That is important, as it means that we can standardize elements by never allowing a hyphen - in that way, there will be no name clash.

Note

2. Other resources

The Gold Standard

3. Acknowledgement

Thanks to Alex Russell, Sangwhan Moon, David Baron, Domenic Denicola add Travis Leithead for their contributions to this document.