PreactBaseElement
creates a <c style="display: contents">
element in the shadow root appended to its associated custom element. Note: display: contents
is not supported everywhere, and its accessibility is not up to spec. Given display: inline
is an acceptable fallback for it, <c>
is utilized because it is display: inline
by default.
For a passthrough element, it looks like this:
amp-foo
├── #shadow-root
| └── c > Foo({children: Slot})
└── … user supplied children rendered via slot
display: contents
removes an element's box while keeping its contents, essentially promoting its children up a level in the DOM with some interesting side effects.
What's important to know style-wise is all properties are calculated, but box-based rules are not painted. This means an ineffective border: 5px solid blue
, though not visible to the end user, is still present and accounted for in style calculations.
<div style="border: 5px dashed red; color: red"> // red border, red font
<c style="display: contents;
border: 5px solid blue; color: blue"> // not painted
<div style="border: inherit"> // blue border, blue font
Hello world
</div>
</c>
</div>
Basically the style logic is completely separate from the painting rules.
The following would be a reasonable, common, and intuitive way to style an amp-lightbox
:
<amp-lightbox style="background-color: cyan;" />
Because the underlying <Lightbox>
element has a default background-color
of rgba(0,0,0,0.9)
(translucent black), opening it causes the end-user to see both: translucent black, and faintly underneath, cyan. We want a way for user provided styles on the amp-lightbox
to override, not mix with, certain stylistic defaults provided by the Lightbox
.
Accordingly, we set default styles in PreactBaseElement
and amp-lightbox
to do exactly that: (1) make box-styles from the custom element available but ineffective via inherit in the base implementation, and (2) propagate style values to the desired target inside the shadow via inherit and part. It is particularly important, for background
, to make sure they are only visibly applied once, and not on intermediary layers (which would otherwise compound something like fractional opacities and mess up visibility-based animations in Preact).
Affected styles include: background
, padding
, border
, box-sizing
. These could all be set to inherit to give the underlying Preact components access to them, but we are holding off on applying them all until clear use cases come up for them.
display: flex
parent treats display: contents
element like a fragment, so we get things like the following where A, B, and C here are laid out based on display: flex
, as if <c>
wasn't there at all.
<div style="display: flex">
<c style="display: contents">
<div>A</div>
<div>B</div>
<div>C</div>
</c>
</div>