Loading and performance
What a page shows before components load, how to avoid layout shift, and how to keep pages fast.
Neighborhood components are custom elements, so they only take shape once their JavaScript has loaded and registered them. Until then the browser shows the raw tags. This page covers what visitors see in that moment, how to keep it from jumping, and how to keep pages fast.
Before components load
Before a component is registered, the browser treats its tag as an unknown inline element:
- Content in slots shows, but unstyled. A Headline Content’s title and call to action appear as plain text on one line, in the page’s default font.
- Content set with properties doesn’t show at all. A Select’s options or a Product Card’s data only exist once the component loads.
- Sections have no size. Each component is a single line tall, so when the components load, sections grow and the page below them moves down.
This is why content that matters belongs in slots: it’s in the HTML, readable and visible to search engines, even before the components load. See Content model.
Reserve space for sections
To keep the page from jumping, give large sections a size before they load with :not(:defined), which matches custom elements that aren’t registered yet:
nbhd-headline-content:not(:defined),
nbhd-hero-split:not(:defined),
nbhd-jumbotron:not(:defined) {
display: block;
min-block-size: 24rem;
}
Match the sizes to your page: measure each section once it has loaded, at each breakpoint that matters. Reserving space is the safest choice, because the content stays readable if the script is slow or fails.
Or hide components until they load
To avoid the flash of unstyled text, you can hide components until they’re registered:
:not(:defined) {
visibility: hidden;
}
visibility keeps each element’s space, unlike display: none. The catch: if the script fails to load, the content never appears. Use it only for small components, or together with the reserved sizes above, never for a whole page.
Wait for a component in your code
Code that calls a component’s methods or reads its properties has to wait until it’s registered and has rendered. Some components finish setting up a frame after that: Carousel starts its slider on the next animation frame, so slideTo() does nothing until then.
await customElements.whenDefined('nbhd-carousel');
const carousel = document.querySelector('nbhd-carousel');
await carousel.updateComplete;
await new Promise(requestAnimationFrame);
carousel.slideTo(2);
Load the components once
Load the components in one way only: either import @fbin-web/neighborhood-core (or the React package) with your bundler, or add the build/library/neighborhood.js script tag. Loading both registers every component twice, which stops with an error such as the name "nbhd-container" has already been used with this registry.
<script type="module"> doesn’t block the page from rendering, so the script tag can go in the <head>.
What the components cost
Every component is registered from one entry point, so importing one component, such as NbhdButton, includes all of them. In v5, that’s about 115 KB compressed, including Carousel’s slider.
To keep that cost in check:
- Load it once per page, from one shared file, so the browser caches it across pages.
- Don’t load it on pages that don’t use any Neighborhood components.
Fonts
Each brand stylesheet loads the brand’s web fonts. Text uses a fallback font until they arrive, then switches.
-
Self-hosted fonts, such as Moen’s, are in the brand’s
fonts/folder. To load the main ones sooner, preload the fonts used in the first view of the page, usually the body and headline fonts in their regular weights:<link rel="preload" href="/assets/neighborhood/moen/fonts/denim/Denim-Regular.woff2" as="font" type="font/woff2" crossorigin />Preload only one or two files. Each preload competes with the page’s other first downloads.
-
Google Fonts. Many brands load their fonts from Google Fonts, from inside the brand stylesheet. Connect to Google’s servers early, so the fonts aren’t waiting on the stylesheet:
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />The brand page shows each brand’s fonts.
Images and video
- Lazy-load images below the first view with
loading="lazy", and keep the default,eager, for the images at the top of the page. - Use
provider="widen"for images hosted on Widen, so Neighborhood requests each image at the size it’s shown and in WebP where it can. - Give videos a
poster, so something shows before the video loads. - Autoplay only short, silent loops. Autoplaying video starts downloading as the page opens.
Content and media covers image sizes and cropping.
Check a page
Check key pages with your browser’s performance tools, such as Lighthouse in Chrome, on a mid-range phone setting. Look at:
- Cumulative Layout Shift, for sections that jump as the components load. Reserve their space as described above.
- Largest Contentful Paint, usually the hero image or title. Keep the hero image
eager, and its title in a slot.