-
Notifications
You must be signed in to change notification settings - Fork 11
Layout issues around <wp-block>
and display: contents
#49
Comments
Should it inherit everything like this? wp-block > * {
all: inherit;
} Or just a few rules? It'd be great to have a CSS expert look at this. |
Bringing this in here from another conversation: More backgroundWhen the theme uses selectors like With the current setup those descendants however are the AlignmentsWhat still won't work either with the above inherit rules nor with just One option to solve all this is to take the block wrapper out of the React component, and treat Another one is doing an alternative That is, of course, if we want to support existing theme styles. We can also require theme devs to do an update to support frontend blocks. I think with block themes the alignment and content width styling is provided by WordPress, so maybe it's only classic themes that'd need to work around this. |
I don't think that's an option.
I don't think we can do anything during the hydration because that would cause a flash. This needs to come as is from the server. We could try to move the
I researched this a bit when we started, and React doesn't support wrapperless hydration. There are some hacky ways to do it, but I'd prefer to avoid those. But Preact does support wrapperless hydration. It's not documented, though. I remember reading a tweet from @developit about it. I'll try to find it. At this moment, I'm a bit disappointed with |
I found the tweet: https://twitter.com/_developit/status/1538248499988418561 And the code is here: https://gist.github.com/developit/f4c67a2ede71dc2fab7f357f39cff28c I'll test it out. |
Initially, it seems to be working fine: https://codesandbox.io/s/nice-mountain-su6zl1?file=/src/index.js For this app: const App = () => <div id="root">content</div>; And these targets: const root = document.getElementById("root");
const rootFragment = createRootFragment(
document.body,
document.getElementById("root")
); Using <body>
<div id="root">
<div id="root">content</div>
</div>
</body> And using <body>
<div id="root">content</div>
</body> |
Anyway, we should research first if using a custom element is not possible at all. Safari doesn't support custom built-in elements ( |
Nice! I played around using a DocumentFragment as the root with React, and that actually somewhat works too — except for event handlers, which React attaches to the root: https://codesandbox.io/s/upbeat-wozniak-wnfo39?file=/src/index.js I've been thinking on an alternative to custom elements, and maybe just a |
I tried We can also take a look at how the custom-elements polyfill checks for new elements. Maybe there's another alternative. |
@jasmussen: We need some help here 🙂 We'd like some confirmation on whether using a Would you mind taking a look or pinging someone that could take a look? Thank you very much! 🙏 |
Looking at the code, I see the polyfill looks for nodes being added/removed by subscribing the |
I've not yet found an excellent use of
I have a feeling you might get a better answer from @scruffian or @mtias. I'm assuming by "interactive blocks" you're referring to anything that uses JS on the frontend, or are there other cases? And by this wrapper, I assume you mean it would be an additional wrapper to what might exist already, right? I.e. Navigation by default outputs this:
So, essentially a fragment but for the frontend. It's tricky, as any wrapping div will default to being block level, but the block itself might be inline-block, or flex, or inline-flex. Additionally (and as suggested in the initial post), any direct-descendant CSS that assumes blocks are immediate children of the post list will target the wrong element. Here's a wide image as an example:
Purely in the name of exploring ideas (they might inspire better ones) would you be able to transplant the classes one level up? I.e. this:
Another question: would limiting the features being explored to just block themes improve predictability? I.e. Is it impossible to accomplish what you're after without a wrapping element? Hopefully Ben or Matías can help shed some better light, and hope this was helpful. |
I think using the custom element built-in extends ( I was following Andrea's work recently (the author of the polyfill) and he's very adamant about his approach to custom element builtin extends being "THE way" 🤷♂️:
We used the custom element builtin extends in the earlier version of the BHE. Was there another reason why we removed them other than the lack of Safari compatibility? |
I'd like to try this alternative wrapperless hydration based on a static virtual DOM: #60 It would not be as simple as switching to Preact to use |
I'm having an interesting conversation about the stability of Preact's internal properties in Preact's Slack: https://preact.slack.com/archives/C3M9NTD16/p1661766573099969 (you need to login first). They don't guarantee their stability, but Fresh is also using For WordPress, if we finally want to access those internal properties, we would have to:
|
A bit more info about that conversation:
So I think this is the situation:
|
I'd rather stay away from |
Could you explain why? |
Sorry if that's a silly idea, but I kind of lack the context and overview of what we are trying to achieve and all the constraints.
|
Regarding versioning - we could consider setting up an integration test in Preact core with a stripped-down version of WP's element base so that any potentially-breaking change will be flagged in CI. One thing I wanted to suggest (not sure if it has already been suggested here) would be that a Custom Element could be used to initialize the Preact tree for a DOM subtree without necessarily wrapping that tree: <!-- this div is as-rendered by the preact component: -->
<div class="wp-block-image alignwide size-large">
<figure>
<img ...>
</figure>
<input class="abc">
</div>
<wp-block name="image" props="{}"></wp-block>
<!-- ^ this CE hydrates its previous sibling(s), then hides/removes itself --> Rough implementation: import { h, hydrate } from 'preact';
class WpBlock extends HTMLElement {
constructor() {
this.style.display = 'none';
}
connectedCallback() {
let root = this.previousElementSibling; // or createRootFragment w/ scan back to comment
let block = this.getAttribute('name');
let props = JSON.parse(this.getAttribute('props') || this.textContent || '{}');
hydrate(h(components[block], props), root);
}
} |
Just in the comment above ;) "Can't we make Also, to be precise: <wp-block name="image" props="{}"></wp-block>
<!-- ^ this CE hides itself, then hydrates its previous sibling(s), then removes itself --> import { h, hydrate } from 'preact';
class WpBlock extends HTMLElement {
constructor() {
super();
this.style.display = 'none'; // hide myself.
}
connectedCallback() {
let root = this.previousElementSibling; // or createRootFragment w/ scan back to comment
let block = this.getAttribute('name');
let props = JSON.parse(this.getAttribute('props') || this.textContent || '{}');
hydrate(h(components[block], props), root);
this.remove(); // remove myself
}
} |
@tomalec sorry for the laconic phrasing. Mainly due to its semantic ambivalence, the contentious nature on Safari/Webkit, and the fact it doesn't seem necessary for this particular scenario. |
That's a definitely fair point if we aim to start polyfill free.
"A customized built-in element inherits the semantics of the element that it extends." I get that
I think it actually is useful, as it allows customizing elements with different parsing behavior. |
Thanks for your suggestions, folks 🙂 We are going to start working on this issue. We'll try to do it so we can compare the performance of all the different approaches. I'll report back on what we find out, although if the performance differences are not significant, we'll prioritize the options that don't introduce additional elements in the DOM to keep the HTML as clean as possible (i.e., mutation observer for detection + |
Closed as we're not actively working on this experiment anymore and this works fine in the Directives Hydration. |
Themes commonly style the top-level content elements, like
.entry-content > *
, for layout and spacing, eg to allow various alignments. Example:This doesn't really work with
display: contents
on the<wp-block>
wrapper:One option is inheriting these spacing styles that would apply to the wrapper:
I'm not sure that's enough for every theme, this would need wider testing and some strategy to keep compatibility with existing theme and possibly plugin styles.
The text was updated successfully, but these errors were encountered: