Start with a search that works
Consider a directory with a search box and a category filter. Its first implementation can be a GET form that submits to a results page. The query belongs in a named input, the category in a select, and each result in a real link. A copied results URL should show the same search on another device.
This is the starting point described by progressive enhancement: essential content and functionality are available first, with improvements added for browsers that can support them. It gives the project a working path to test before asynchronous requests introduce more states.
Complete the response
The server should return the selected category and query with the results. Show an explicit empty result message, and let the person change the search without retyping it. Reject invalid parameters safely; client validation cannot protect the endpoint from a direct request.
The same principle applies to a contact form. Give it an action and method, validate on the server, and return field errors with the safe input preserved. Associate each message with its control. A confirmation page should mean the submission was accepted, rather than merely that a click handler ran.
Make the document usable at different sizes
Test the form at a narrow width with a long category name and a long result title. Let controls wrap and text determine the height of each result. Fixed card heights often fail as soon as the content differs from the design sample.
Keep keyboard focus visible. Check that CSS has not put the visual order at odds with the tab order. For navigation, use ordinary links within a labelled navigation region; a site navigation list does not automatically need the behavior of an application menu. The WAI menus tutorial is a useful reference for structure and operation.
Add faster results with an exit path
JavaScript can intercept the search submission and update the result region. Preserve the form's normal destination so the request still has a usable URL. While loading, make the pending state clear. If the request fails, keep the query and provide a way to retry or open the results page normally.
Avoid hiding the navigation before the script responsible for opening it has initialized. A failed script should not leave a mobile page with an invisible menu. Add the collapsed behavior only when the control and its event handlers are ready, then keep its expanded state synchronized with what is visible.
Test the same task through both paths
Submit the search with JavaScript disabled. Open a result, press Back, and change the category. Then repeat with scripts enabled and a deliberately failed request. The person should still know which query is active and how to continue.
Also test keyboard operation and browser zoom. A successful fetch can still leave focus on an element that has been removed, or update results without any useful status feedback. Check these transitions while building the enhancement; they are part of completing the search.
Sources & further reading
Technical references checked on 17 September 2026.