Saliem Talash
Homepage pictures after a JavaScript-disabled reload on October 19 2026

Notes · Websites

What remains when this site's WebGL turns off

A look at the HTML, DOM and WebGL paths behind the homepage, and a practical routine for checking their boundaries.

The bending project strip on this site's homepage has more than one way to draw its pictures. WebGL supplies the curved planes and shader treatment, but the page also contains ordinary images and text. Looking at those layers separately makes it easier to ask a useful question: which parts of the experience depend on the enhancement?

This note describes the implementation checked on October 18, 2026. The check routine below is a suggestion for examining it, not a report of completed browser tests or measured performance.

On October 19, 2026, three captures recorded a reload with JavaScript disabled, forced DOM after three native Right key presses, and automatic GPU mode during a held native drag. They show those limited states; reduced-motion, data-saving, network-failure and context-loss tests are not reported here.

Start with what the document contains

The generated homepage includes the heading, company links, project pictures and project titles in HTML. Each project card is a list item containing a picture and heading. It is not an anchor, and clicking the strip is not a route into a project.

A separate, visually hidden navigation list contains the project URLs. Those links have a negative tab index, so their presence does not demonstrate an ordinary keyboard route through every project. HTML content, visible navigation and keyboard usability are separate things to inspect.

When JavaScript is disabled, CSS permits the picture row to scroll horizontally and the document to scroll normally. That is the static starting point. It should not be confused with the JavaScript-driven DOM mode, which positions and moves HTML card elements itself.

Forced DOM pictures after three native Right presses on October 19 2026
Forced DOM pictures after three native Right presses on October 19 2026

Choosing the DOM path

The homepage initially records its tier as DOM while the enhancement decision is pending. After the page load event and a scheduled frame, it runs the tier checks and imports the strip controller.

Without a test override, reduced-motion preference selects DOM. So do a reported data-saving preference or a reported 2g connection, a recognised bot or lab user agent, reported device memory below four gigabytes, and fewer than four reported processor cores. An unavailable core count also takes the conservative branch. Missing memory information does not trigger the memory check.

These are selection rules, not a measurement of how powerful a device is. Device memory is approximate and is not available in every browser. A usable WebGL2 context is another requirement; context creation errors and recognised software renderers select DOM instead.

Adding ?tier=dom forces that mode before the normal checks. It is useful for isolating the renderer, but it cannot prove that reduced-motion or data-saving detection works. Those need separate checks without the override.

What WebGL adds

Only the live path dynamically imports the WebGL renderer, which imports Three.js. If renderer creation fails, the strip controller switches to DOM. A failure higher up the asynchronous strip-loading chain is caught and logged as an unavailable strip; that branch needs its own browser check rather than an assumption that every failure looks identical.

The live renderer caps device pixel ratio at 1.5 for a coarse pointer and two otherwise. Those are configuration limits, not measured frame rates. The DOM pictures remain part of the strip structure. CSS hides them when the WebGL layer is marked on.

There is also a context-loss mechanism: the renderer listens for loss and restoration, marks drawing unavailable, and changes the strip's display state so the HTML pictures are no longer hidden by the WebGL-on rule. Restoration schedules another frame. Those handlers describe intended recovery; their presence alone does not prove successful recovery in every browser.

Hover films have another boundary. Reduced-motion and reported data-saving conditions disable that feature. Otherwise, its module is requested when the intent controller first asks to show a film, rather than being imported with the initial homepage module.

Automatic GPU strip bending during a held native drag on October 19 2026
Automatic GPU strip bending during a held native drag on October 19 2026

A suggested failure check

Try this on a disposable test tab, recording the browser, viewport and conditions for each run:

  1. Disable JavaScript, reload, and inspect the heading, pictures, scrolling and available navigation. Record any missing task rather than assuming HTML presence is enough.
  2. Re-enable JavaScript and load ?tier=dom. Exercise the strip and inspect the network requests for the renderer. Remove the parameter before testing automatic selection.
  3. Enable reduced motion in the operating system or browser tools, reload without an override, and check both the selected mode and film behaviour. Test data-saving signals only where the browser can actually provide them.
  4. On the live path, test renderer-load failure and simulated context loss separately. Check the pictures, controls, console and restoration behaviour. Record the observed result, including failures.

Compare those observations before changing the fallback. The useful deliverable is a clear account of what remains readable, what remains operable and what still needs work under each condition.

Prepared with AI assistance. Examples are fictional unless stated.