A block that renders nothing until its view script arrives is a block that renders nothing on a hotel wifi connection, on a cold cache, or any time a CDN has a bad afternoon. The visitor does not see a loading state. They see a gap where your content should be.
When we built BlockCrate we set one rule: every block has to be useful before its JavaScript loads. Scripts may only upgrade what the browser has already drawn. That rule turned out to be less about clever fallbacks and more about picking the right primitive in the first place.
Let the browser do it
The accordion is the clearest example. It would be easy to write one with a click handler, a piece of state and an aria-expanded attribute you have to remember to keep in sync. Instead it is a native details element.
<details>
<summary>Shipping and returns</summary>
<p>Posted within two working days.</p>
</details>
That one choice hands you keyboard support, screen reader semantics and find-in-page expansion — browsers will open a closed details to reveal a search match — without a line of script. Panels can even open one at a time with no JavaScript at all. The script we do ship exists only to coordinate a couple of niceties on top.
The other four
The same instinct applied everywhere else:
- Carousels are scroll-snap strips. Without JavaScript they are still a horizontally scrollable row of items that you can swipe on a phone and scroll with a trackpad.
- The progress bar is rendered at its final value on the server. The script animates it from zero when it scrolls into view; if the script never arrives, the bar is simply already correct.
- Tabs fall back to a plain stack of labelled sections. Every panel is in the document and readable — you just lose the tabbing.
- The page slider is rendered server-side from a live query, so it is never a stale copy of what it is supposed to show.
Notice what is not on that list: a spinner. None of these blocks has a loading state, because none of them has a moment where there is nothing to show.
Reduced motion is part of the same idea
If a visitor has asked their operating system for reduced motion, the progress bar does not animate, the carousels do not auto-advance, and nothing slides. This is the same principle pointed at a different problem: the content is the point, and the movement is the enhancement. Take the enhancement away and you still have everything that matters.
An auto-advancing slider also pauses on hover and on keyboard focus. Not because a specification demands it, but because a carousel that moves while someone is reading it is a carousel that has made a decision on their behalf.
What this costs
Honestly: some flexibility. A native details element will not animate its own height, and getting a smooth open out of one takes more work than it would with a div and a class. We think that is a good trade. The alternative is reimplementing, slightly worse, what the browser already does correctly.
Assets load only on pages where a block is actually used, so a page without BlockCrate carries none of its weight — which is the other half of not making visitors wait for things.
