An open API service indexing awesome lists of open source software.

https://github.com/stuartpb/pwalls-spec

HTML/CSS/DOM Parts and Walls Proposal
https://github.com/stuartpb/pwalls-spec

Last synced: 5 months ago
JSON representation

HTML/CSS/DOM Parts and Walls Proposal

Awesome Lists containing this project

README

          

# HTML Parts and Walls

## Status

This document is "pre-specification" which means that I haven't even figured out enough spec bureaucracy to give this document a proper status. It's been [posted to the WICG Discourse](http://discourse.wicg.io/t/html-parts-and-roots/1032), and that's about it.

## Overview

This document proposes two new attributes that, like `class` and `id`, may be applied to any element in HTML:

- `wall`, a boolean attribute specifying that the element is to be treated as a boundary for the purposes of the `getPart()` function and the Walled Descendant Selector defined below.
- `part`, an attribute with a name value, following the same uniqueness and traversal constraints within walled boundaries as `id` has within document boundaries.
- `id` may still be defined on an element with `part`, as they have different access implications. (A framework or polyfill may generate `id` values to uniquely identify every element in a document: this will not affect `part`.)

## Motivation

It's still not great to write components in HTML:

- CSS selectors always applying globally leads to unduly elaborate namespacing schemes like BEM.
- There's still no real good solution for addressing *unique children* of an element.

Shadow DOM is supposed to solve this, but it comes with a handful of even worse problems:

- The isolated context cuts you off from reusing your page styles.
- Just because I want to style for a component, doesn't mean I want to make its children inaccessible to `getElementsByTagName` &c.
- Styles defined by the page to apply *within* the context of Shadow DOM are impossible (the closest this came to a solution was `/deep/`, which only served to bring all the contextual problems of CSS selectors back and undo the most significant guarantee Shadow DOM is supposed to provide).
- Indexing elements *within* the component requires you to either go full-hog about designing the inner HTML to depend on Shadow DOM's ID isolation, or use clumsy class-based addressing techniques.
- Shadow DOM contexts can't be created declaratively (without Custom Elements, which require lots of JS and bring further constraints).

Walled elements introduce a lighter option than Shadow DOM contexts for *basic* encapsulation. (For styling within heavier encapsulation, the Walled Descendant combinator may *also* be used for *crossing* Shadow DOM boundaries.) It provides a facility page authors may use to create a hierarchy *in the context of their page*, allowing them to have simple and straightforward access *within the boundaries of their hierarchy*, without being concerned about namespacing *at every level* (the scope of concern for namespace schemes can be limited to selecting the proot).

## DOM Parts

Elements have a `getPart()` function, which works similarly to how `getElementById` or `getElementByClassName[0]` works (doing a depth-first search under the element), except looking for `part` rather than `id` and avoiding traversal beyond wall boundaries (as well as the document boundaries which all traversal algorithms avoid).

Example: say I have this HTML:

```html



108:00



42


23
16



4
8
15


```

(Note: This element would normally be created as one of many, having no IDs defined. The IDs are purely for illustrative purposes in the following description.)

Let `fig1 = document.getElementById('fig1')`.

Running `fig1.getPart('timer')` would return the element with the ID `fig2`, as that is the unique (first) element under `fig1` with the `part` attribute value `timer`.

Running `fig1.getPart('bubble')` would return the element with the ID `fig3`, as that is the unique (first) element under `fig1` with the `part` attribute value `bubble`. (The fact that the element itself has a `wall` value does not stop the *element itself* from being found.)

Running `fig1.getPart('funnel')` would return `null`, as the only element with the `part` attribute value `funnel` underneath `fig1` is underneath the element with the ID `fig3`, which has the `wall` attribute defined, causing the search to not recurse further into that element's descendants. (Getting the element with the ID `fig4` would require starting the search from its first ancestor with the `wall` attribute, namely the element with the ID `fig3`, ie. `fig1.getPart('bubble').getPart('funnel')`.

Running `fig1.getPart('track')` would return would return the element with the ID `fig6`, as that is the unique (first) element under `fig1` with the `part` attribute value `track` that is not underneath an element (namely, the element with the ID `fig3`) which has the `wall` attribute defined (which causes the search to not recurse further into that element's descendants, hence skipping the element with the ID `fig5`).

Running `fig1.getPart('bubble').getPart('track')` would return the element with the ID `fig5`, as that is the unique (first) element under `fig1.getPart('bubble')` with the `part` attribute value `track`.

## The Walled Descendant Combinator for CSS Selectors

A `|>` sequence may be used after a [compound selector](https://drafts.csswg.org/selectors-4/#compound), to define a wall or Shadow DOM boundary crossing. The element matched on the LHS of the combinator must have the `wall` attribute defined or contain a Shadow DOM. The compound selector to the right of the `|>` only matches descendants of the LHS that *do not cross* further walls (though the matched element may itself have a `wall` attribute specified, the descendants of a child with `wall` specified *will not* match the combinator). The `#` character, after a `|>`, refers to *either IDs or parts* within the LHS walled context (the specificity is increased as an ID selector for either kind of match).

Note: It is important to note that *further combinators left of the walled desecendant combinator* may traverse *any number* of walls. Walls *only* come into play *around the walled descendant combinator*. Any non-walled descendant combinators (namely, the whitespace or `>>` "general" descendant combinator), as before, *are not separated* by walls.

## Differences between walled elements and Shadow DOM

- Elements under a walled element are still selected by selectors in the top-level document, as well as functions like `getElementsByClassName`.
- Walls can be defined without JS.
- Child elements may be moved between walled elements without having to create a copy with `importNode`, discard the old node, and expecting things that `importNode` doesn't copy to break.

## Differences between `part` and `class` or `name`

- Unlike class names, parts are expected to be unique within the context of their wall (which allows for optimizations to `getPart`, as well as warnings in validators, and other developer tool enhancements).
- Part names under walls do *not* have to be considered in the global namespace, unlike class names. (Similarly, part names do *not* have to correspond to the name used for a value when submitting a form.)
- Unlike `getElementsByName` or `getElementsByClassName`, `getPart` is restricted to wall boundaries.

## Extensions to existing elements

A standard structure for the standard elements UAs currently construct within Shadow DOM could be defined, using `part` attributes to refer to a hierarchy of their components, for access in styling, as an alternative to non-standard vendor-prefixed pseudo-elements, as we currently use. (This includes the sub-components of scrollbars, which would remain pseudo-elements, but be standardized as pseudo-elements containing walls.)

## Example: Doctor Listings

```html

/* TODO: finish example stylesheet */
.profile |> #photo {

}
.profile |> #name {

}
.profile |> #bio {

}




Foo Bar

lorem ipsum





Boo Car

lorem ipsum





Kenny Baz

lorem ipsum



```

## Example: Chat UI (initial content with HTML template)

```html

/* TODO: finish example stylesheet */
.message-card|> #avatar {

}
.message-card|> #name {

}
.message-card|> #message {

}





// TODO: write script

```

## Example: Chat UI (live snapshot of variant using no HTML template)

```html


















// TODO: write script

```

## TODO

- Everything marked "TODO" above.
- Add proposals for what the standard element parts look like.