webdevpuneet.com

Mobile Search Screen — Free HTML CSS JS UI Snippet

Mobile Search Screen · Mobile · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

<div class="msc-phone">
  <div class="msc-screen">
    <div class="msc-status"><span>9:41</span><span class="msc-batt"><i></i></span></div>
    <div class="msc-bar">
      <div class="msc-field">
        <span class="msc-mag">&#9906;</span>
        <input id="mscInput" type="text" placeholder="Search" autocomplete="off">
        <button class="msc-x" id="mscX" aria-label="Clear" hidden>&times;</button>
      </div>
      <button class="msc-cancel" id="mscCancel">Cancel</button>
    </div>

    <div class="msc-scroll">
      <div class="msc-default" id="mscDefault">
        <div class="msc-shd"><span>Recent</span><button class="msc-clr" id="mscClr">Clear</button></div>
        <div class="msc-chips" id="mscRecent">
          <button class="msc-chip">wireless earbuds</button>
          <button class="msc-chip">running shoes</button>
          <button class="msc-chip">coffee grinder</button>
          <button class="msc-chip">desk lamp</button>
        </div>
        <div class="msc-shd"><span>Trending</span></div>
        <div class="msc-trend" id="mscTrend"></div>
      </div>

      <div class="msc-results" id="mscResults" hidden></div>
      <p class="msc-none" id="mscNone" hidden>No results for "<span id="mscQ"></span>"</p>
    </div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Two-state screen
Recent/trending at rest, results while typing.
One render path
A single run() drives every entry point.
Highlighted matches
Matched substring wrapped in a mark tag.
Escaped regex
Query escaped so special chars are safe.
Sliding cancel
max-width transition on focus, iOS-style.
Chip prefill
Recent and trending taps run the search.
Named empty state
Echoes the exact query on no results.
No dependency
Pure HTML, CSS, and vanilla JavaScript.

About this UI Snippet

Mobile Search Screen — Live Search UI

Screenshot of the Mobile Search Screen snippet rendered live

A search screen has two faces — a resting state with recent searches and trending queries, and an active state that filters results live as you type. This snippet builds a complete, interactive one inside a CSS phone frame: typing filters a catalog and highlights the matched substring, recent chips and trending rows prefill the query, a cancel button slides in on focus, and a no-results state names what you searched — in HTML, CSS, and vanilla JavaScript with no dependency.

Two states from one input

When the field is empty, the default view shows recent-search chips and a ranked trending list; the moment you type, that view hides and a results list takes its place. A single run() function reads the input, decides which view to show, and renders — so every entry point (typing, tapping a chip, tapping a trend row) funnels through the same logic and the screen stays consistent.

Live filtering with highlighted matches

Typing filters a catalog array by a case-insensitive substring test, then renders each match with the matched portion wrapped in a <mark>. The highlight is built by replacing the query with a captured group using a RegExp, and the query is escaped first so special characters like . or ( cannot break the pattern — the safety step most naive highlighters miss. Each result shows an icon, the highlighted name, and its category.

The sliding cancel button

Focusing the field slides a Cancel button in from zero width using a max-width and opacity transition, and tapping it clears the query, blurs the field, and returns to the default view — the exact iOS search-bar behavior. A small clear (×) button inside the field appears only when there is text.

Prefill from recent and trending

Recent searches are tappable chips and trending queries are a ranked list with a rising-percentage badge; tapping either drops its text into the input and runs the search immediately, so common queries are one tap away. The "Clear" action empties the recent list and leaves a quiet placeholder in its place.

A named empty state

When nothing matches, the results are hidden and a message echoes the exact query — "No results for …" — so the user knows the search ran and simply found nothing, rather than staring at a blank screen wondering if it is loading.

Accessibility and performance

The field is a real text input and the recent chips, trending rows, cancel, and clear controls are all buttons, so the screen is fully keyboard-operable. When you adapt this, wrap the results region in an aria-live="polite" container so the match count is announced as you type, give the input role="searchbox" semantics, and make sure the highlighted <mark> does not swallow the readable text — screen readers still read marked text, so the emphasis is purely visual. Performance is fine for a client-side catalog: filtering is a single indexOf pass over the array per keystroke and the results render with one innerHTML write. The important safety detail is escaping the query before building the highlight RegExp, which prevents both broken patterns and needless re-compilation errors. For a real backend, debounce the input by a couple hundred milliseconds so you are not firing a request per character, and guard against out-of-order responses by tracking the latest query. Rendering matches by splitting on the match, rather than injecting HTML, avoids any escaping concerns entirely when you port to a framework.

Reusing it

Swap the catalog for your data or an async endpoint (debounce the input for network calls), persist recent searches, and wire results to detail screens. Lift it out of the phone frame for a responsive web search, or keep it framed beside an expandable search field to present a full flow.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA search screen renders with recent chips and a ranked trending list.
  2. 2
    Focus the fieldA Cancel button slides in from the right edge.
  3. 3
    Type a queryThe default view hides and matching catalog items appear with the typed text highlighted.
  4. 4
    Tap a chip or trendRecent chips and trending rows prefill the query and run the search instantly.
  5. 5
    Clear or cancelThe inline × clears the text; Cancel resets everything to the default view.
  6. 6
    See no resultsSearch for something absent and a message echoes your exact query.

Real-world uses

Common Use Cases

Full-screen app search
Show recent chips and trending queries at rest, and switch to live-filtered results the moment the user types, with an expandable search as the web counterpart.
E-commerce app search
Feed filtered results into a product card grid, with matching text wrapped in a mark tag so shoppers see why each item matched.
Autocomplete behaviour
Pair with an autocomplete input to compare suggestion-as-you-type with full results, using a single run() function for every entry point.
Command-style navigation
Offer a mobile cousin of the command palette, where a no-results state tells people when nothing matches their query.
Safe highlight reference
Study how the query is escaped before it becomes a regular expression, so special characters typed by users never break the highlighting.
Related: Mobile Ride-Hailing Screen
See the Mobile Ride-Hailing Screen for a related mobile pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Each result name has the query wrapped in a mark tag. The code builds a case-insensitive RegExp from the query with a capture group and replaces the match with the same text inside mark. Crucially it escapes the query first, so characters like . ( or [ are treated literally and cannot break the pattern.

User input can contain regex metacharacters. Without escaping, typing an open parenthesis or a plus would create an invalid or unintended pattern and either throw or highlight the wrong thing. Escaping those characters first makes the search treat the query as literal text, which is what a user expects.

A single run() function reads the input value. If it is empty, the recent-and-trending default view shows and the results hide; if there is text, the default hides and results render. Because typing, chips, and trending taps all call run(), the two states never get out of sync.

Cancel starts at max-width zero with opacity zero. Focusing the field adds a class that transitions its max-width and opacity up, sliding it into view. Tapping it clears the query, blurs the field, and removes the class so it slides away — the standard iOS search-bar interaction.

Hold the query in state and derive results with a filter in useMemo (React), computed (Vue), or a pipe (Angular). For a live API, debounce the input and fetch in an effect, guarding against out-of-order responses. Render highlights by splitting on the match rather than using innerHTML. Persist recents in storage. Tailwind expresses the field, chips, and rows with utilities.