Skip to the content.

Frontend Best Practices

Our most stringent standards and expectations are for experiences that our customers provide their visitors – but we strive for similar quality in our authenticated experiences.

We expect diagnostic tools like Lighthouse and the Network tab in a browser to be used in profiling frontend experiences.

Semantic HTML

We expect markup to be expressed in valid, semantic HTML elements with proper heading structure, appropriate use of anchors vs. buttons and without legacy tags like <marquee>, <b> or <i>.

Beyond being more accessible, more digestable for search engines and scrapers, there are secondary benefits as well to relying too heavily on <div> to divide interfaces even when SEO isn’t a factor.

One example is that in the WordPress Admin, if a third-party plugin is loading a stylesheet indiscriminately targeting <div> in a way that interferes with our specificity, simply by using <header>, <section>, <aside> or other semantic tags we dodge that issue.

Documents and DOMs

Avoid excessive DOM size and depth

Excessive document sizes, whether transmitted in-full or built after runtime, impact browser performance and run up against memory limits of thin clients. It doesn’t matter how clever and well-formed code is, if there’s simply too much of it, the experience is poor.

While these are not hard limits, they are good reminders and worthy targets. In the end, less markup is faster markup.

In WordPress, we often don’t control DOM size, shape or depth – but we can be congnizant of how our code exists within the environment.

Batch DOM changes

If looping data to write to the DOM, batch those changes into DOM nodes that get added with a single insertion, instead of updating the DOM during each loop iteration.

Buffer giant lists

Use efficient scrolling and paging techniques like list virtualization to limit DOM elements to those only currently visible in the viewport.

Runtime Execution

Avoid render-blocking resources

<script>

Make appropriate use of defer and async.

In WordPress, the script_loader_tag filter can be used to apply per-handle.

When possible, make use of media to declare the media query the stylesheet applies to so the browser can prioritize requests.

In WordPress, the style_loader_tag filter can be used to apply per-handle.

Preload, preconnect & prefetch

Preloading

JavaScript, CSS stylesheets, webfont files, frame documents, audio, video and XHR requests to JSON files can be preloaded.

While not every resource should be preloaded, it’s a great way to declare high-priority assets and make them available before or early in browser rendering.

Learn more about using <link>’s for preloading at MDN.

Preconnection

Preconnection allows a browser to resolve DNS for an origin resource, often making subsequent requests to that domain faster.

This resource hint empowers the browser to setup a connection before an HTTP request is sent to the server, cutting down on request latency.

preconnect is best for resources that will always be requested, and ideal for connecting CDNs and image services.

Font resources must have the crossorigin attribute with rel="preconnect"

Prefetch

prefetch is a low-priority technique for resource-hinting. It instructs browsers to fetch resources in the background during idle time and keep them in browser cache.

There are three distinct kinds of prefetching:

Link prefetching should be used sparingly, only on top-priority assets like a company logo, or one with overwhelming certainty of being needed.

DNS prefetching

Where preconnect is best for assets that will always be requested, dns-prefetch performs DNS lookups during idle and has broader browser support and therefore serves as a good fallback for browsers that don’t support preconnect.

DNS resolution is often fast, but use of dns-prefetch can cut 20-120ms from the request round-trip.

Lazy-loading images and iframe embeds

Often images and service embeds like YouTube included directly are the bulk of the impact to performance budgets, so we look to solutions that rely on IntersectionObserver for images or user-interaction for service embeds. However, it is important images and video don’t rapidly enter the rendered document causing Cumulative Layout Shift – one huge contributor to the perceived performance of a frontend. So providing placeholders, skeleton animations and aspect-ratio’s that are exact or very close to the final image or frame are very important.

Avoid excessive use of spinners and skeletons

Loading and progress states are a valuable way to communicate to users, but they can be overdone and more distracting than helpful.

A few common issues we try to avoid:

Runtime Payloads

JavaScript

Too many dependencies

While we don’t have hard performance budgets and don’t believe in rebuilding the wheel, please keep a close eye on the size of vendor dependencies and whether the ROI for the business purpose supports the additional resource weight.

Prefer getElementById and simple matches over querySelectorAll

Aim for the most-efficient selectors when selecting DOM nodes in JavaScript.

Prefer mouseup to click

mouseup fires quicker than click and can greatly contribute to the perceived performance of interface interactions.

Reads and write to browser storage

The performance of browser local and session storage can be both slow, unreliable and limited and require additional vendor dependencies to assure compatibility.

Browsers also limit the quanity of data that can be stored before unclear prompts that can scare and annoy users, and these caps are for the cumulative use by all code executing for a site.

Efficient tapping of browser events

We expect appropriate use of requestAnimationFrame() and requestIdleCallback() within JavaScript, debouncing at a higher cadence if necessary and using something like IntersectionObserver for scroll observation insteady of legacy solutions with poor performance.

Inline & Linked CSS Stylesheets

Images and embeds

On YouTube, Twitter and Facebook

Embeds from popular services often can be a drag on frontend performance, so using lazy-loading techniques on iframes, styles to help mitigate CLS and judicious use should all be considered when using media and content embeds.

Limit & Group Media Queries

Media queries can be expensive to execute as a browser resizes and repaints, including on the first paint. Knowing this, aim for the fewest possible media queries, never leave an empty media query in stylesheets and consider using a tool like postcss-combine-media-query to combine media queries in isolated component systems.

Leverage CDNs and subdomains

CDNs that keep assets at-the-edge are a common best practice for fast delivery of static assets.

While less of an issue with HTTP/2 and greater, browsers can have a maximum number of concurrent resource requests and with HTTP/1.1 this often maxed-out at 6-8 requests per-domain. By storing images and media on a different CDN subdomain that scripts and styles, or further subdividing assets, browsers can more quickly download resources for presentation.

Minify assets, including HTML

Minification – removing white space, line breaks and reducing variable names so assets are optimized for machines not readability – is an important technique in modern development. This also goes for HTML markup delivered to browsers and in API responses to reduce the transmission size of documents.