Hero Image Pushes the Article Grid Down 320 px
A government portal is a Traditional Web app in OutSystems 11. The home screen has a full-width hero image and a grid of 12 article cards. The hero has no width or height attributes, and the cards sit in a Table Records. On a 4G connection, the text renders first; when the hero image arrives, it pushes the cards down by 320 px. Users report clicking the wrong article. To make the cards fade in, a developer added an OnReady JavaScript that adds a loaded class to the grid; the CSS sets .article-grid { opacity: 0; } .article-grid.loaded { opacity: 1; }. The result is a blank grid for about 400 ms after first paint. The screen's Prepare already fetches the 12 records. The design requires a 16:9 hero up to 1200 px wide.
1. Explain the layout-shift mechanism and why the OnReady fade-in makes perceived performance worse in a Traditional Web screen.
Read the worked answer
The browser does not know the hero's height until the image bytes arrive, because the image element has no intrinsic size reserved. The paragraph and grid are laid out at the top of the page, then the image loads, the hero grows to its natural height, and everything below moves down. That is a cumulative layout shift, and it is worse on slow connections because the delay between first paint and image arrival is longer.
In a Traditional Web screen the HTML is rendered on the server, but OnReady JavaScript runs after the DOM is available in the browser. The CSS starts the grid at opacity: 0, so the server-rendered cards are invisible until JavaScript runs and adds the class. That creates a second visual event: first a blank area, then the cards appear. The user sees less content at first paint than the server actually delivered. The fade is cosmetic; the blank period is the real cost.
2. Describe the server-side and CSS changes that reserve space for the hero and remove the blank-grid flash.
Read the worked answer
Reserve the hero's aspect ratio in CSS: wrap the Image in a Container with aspect-ratio: 16 / 9; max-width: 1200px; width: 100%; and make the image width: 100%; height: 100%; object-fit: cover;. If older browser support is required, use the padding-top percentage technique on the wrapper. Also set the Image widget's width and height properties so the rendered img carries intrinsic dimensions.
Remove .article-grid { opacity: 0; }. If a fade is required, use a CSS animation that starts at opacity: 0 only for a short, fixed duration and runs without JavaScript, or drop the fade entirely. Do not use OnReady to toggle a class that controls visibility of server-rendered content. If a class must depend on data, compute it in Prepare and bind it through the Style Classes expression so the first HTML response already has the correct class.
3. Which metric would you use to prove the fix, and what target would you set?
Read the worked answer
Use Cumulative Layout Shift (CLS) from Lighthouse or the Chrome Performance panel, measured on a throttled 4G profile, because the reported symptom is content moving after first paint. A reasonable target is CLS below 0.1 for the home screen, and ideally close to zero for the hero-to-grid shift specifically. Also record Largest Contentful Paint (LCP) before and after, since the hero is likely the LCP element and its dimensions affect when it is considered rendered.
Measure at least three runs on the same throttled profile and compare medians, not a single run. Do not use total page load time as the only proof: the page can still shift after load and feel broken.