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
- Host: GitHub
- URL: https://github.com/stuartpb/pwalls-spec
- Owner: stuartpb
- Created: 2015-08-04T18:36:42.000Z (almost 11 years ago)
- Default Branch: master
- Last Pushed: 2015-08-24T00:02:58.000Z (almost 11 years ago)
- Last Synced: 2025-01-02T03:47:21.880Z (over 1 year ago)
- Homepage:
- Size: 184 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
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.