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.
This document has been produced by the
[W3C Technical Architecture
Group (TAG)](https://www.w3.org/2001/tag/).
Please raise issues on our [issue list](https://github.com/w3ctag/webcomponents-design-guidelines/issues), alternatively, you can send comments on this finding to the publicly archived TAG mailing list
[www-tag@w3.org](mailto:www-tag@w3.org)
([archive](https://lists.w3.org/Archives/Public/www-tag/)).
## Common patterns
The web platform is not known for being 100% consistent, but there are
definitely some recognizable patterns across the platform, such as with regard
to naming. Try to stay consistent with what is already used, like if other
elements use “selected” as an attribute for the same behavior, there is
no reason to start using something else (say, “chosen” or “marked”).
### 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, and 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 beforehand.
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](https://dom.spec.whatwg.org/#action-versus-occurance). See also
the TAG’s guidance on [event design](https://w3ctag.github.io/design-principles/#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, i.e.
`` instead of
``.
* Don’t use custom attributes for styling, like `bgcolor`.
Instead use [Custom Properties](https://drafts.csswg.org/css-variables)
or [CSS Shadow Parts](https://drafts.csswg.org/css-shadow-parts/).
* If elements accept complex data such as 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**.
Elements can be created from scripts etc. before being inserted into
the document, so don’t assume that document APIs such as `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 as, 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, such as
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, such as Material and Cupertino.
### 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 work as a child of any other element, if
that makes sense.
2. **Avoid using callbacks**. Refer to TAGs guidance on
[promises](https://w3ctag.github.io/design-principles/#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 to the
same effect. (e.g. `` 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.
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.
## Other resources
[The Gold Standard](https://github.com/webcomponents/gold-standard/wiki)
## Acknowledgement
Thanks to Alex Russell, Sangwhan Moon, David Baron, Domenic Denicola add
Travis Leithead for their contributions to this document.