Mobile Food Order Screen — Free HTML CSS JS Snippet

Mobile Food Order Screen · Mobile · Plain HTML, CSS & JS · Live preview

What's included

Features

Overlapping status bar
White time and battery float over the hero cover.
Blurred float buttons
Back and favorite use backdrop-filter.
Keyed cart model
Adds increment quantity, never duplicate.
Derived totals
Count and price recomputed from the source object.
Self-resetting feedback
Add button flashes a check then restores.
Rising cart bar
Appears with an animation on first add.
Category chips
Pill highlight moves on selection.
No dependency
Pure HTML, CSS, and vanilla JavaScript.

About this UI Snippet

Mobile Food Order Screen — Restaurant Menu UI

Screenshot of the Mobile Food Order Screen snippet rendered live

A restaurant screen is the workhorse of every food-delivery app — a hero cover, the name and rating, category chips, a scrollable menu of dishes with add buttons, and a cart bar that rises up once you have something in it. This snippet builds a complete, interactive one inside a CSS phone frame: tapping a dish's plus button adds it to the cart, the button flashes a green check, and a sticky cart bar tallies the item count and running total — in HTML, CSS, and vanilla JavaScript with no dependency.

The overlapping hero and status bar

The status bar is absolutely positioned over a gradient cover so the time and battery sit in white on the image, exactly like a real restaurant page where content scrolls under the notch. The back and favorite buttons float on the cover with a translucent, blurred background via backdrop-filter, keeping them legible over any hero color.

A cart model, not just a counter

Adds are stored in a cart object keyed by dish name, each entry holding a quantity and unit price. A refresh() function derives the total item count and the summed price from that object every time — so adding the same dish twice increments its quantity rather than duplicating it, and the total is always recomputed from the source of truth rather than nudged up by hand. This is the same shape you would send to a real checkout.

Add feedback that resets itself

Each plus button lives on the corner of the dish image with a white ring so it reads as a floating action. On tap it turns green and swaps to a check for half a second, then restores to a plus — instant confirmation that the item landed in the cart without navigating away. The scale-down :active state adds a physical press feel.

The rising cart bar

The cart bar is hidden while the cart is empty and appears with a short rise-and-fade animation the moment the first item is added. It shows a count badge, a label, and the tabular-figure total so the numbers stay aligned as they change. Category chips above the menu switch the active filter with a pill highlight.

Accessibility and performance

Each add button is a real <button> with an item-specific aria-label such as "Add Margherita", so screen-reader users know exactly what they are adding rather than hearing a bare plus. The category chips are buttons too, so the filter is keyboard-operable. When you make the chips actually filter the menu, move focus sensibly and consider aria-pressed on the active chip so its selected state is announced. Performance is light: the refresh() function walks the small cart object and writes two text nodes plus a visibility flag, so it can run on every add without cost, and the add confirmation is a class swap with a timeout rather than a re-render. The rising cart bar animates once with a CSS keyframe when it first appears and otherwise just stays put. If your menu is long, lazy-load the dish images with fixed dimensions so the list does not reflow as you scroll, and virtualize only if you have hundreds of items — most restaurant menus fit comfortably in a plain scroll container.

Reusing it

Feed the dishes from your menu API, wire the category chips to actually filter the list, and pass the cart object to your checkout. Lift the menu out of the phone frame for a responsive web ordering page, or keep it framed leading into a mobile checkout screen to present the full order flow.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You do not have to reverse-engineer the cart bookkeeping by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why the cart is a plain object keyed by dish name rather than an array, and why refresh() recomputes the count and total from that object every time instead of incrementing a running total. The same assistant is useful for optimizing it — ask whether the add-button's setTimeout-based reset to a plus icon could race if a user taps the same dish rapidly, or how backdrop-filter blur on the floating back and favorite buttons affects paint cost on lower-end phones. It is just as good for extending the feature: have it add a remove or decrement control per cart item, make the category chips actually filter the visible dish list, or add a per-dish customization sheet (size, extras) that changes the stored unit price. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a mobile restaurant menu / food-ordering screen in plain HTML, CSS, and JavaScript inside a phone-frame container — no framework, no cart library.

Requirements:
- A gradient hero cover with an absolutely-positioned status bar and floating back/favorite buttons using backdrop-filter blur over a translucent background so they stay legible over any hero color, followed by restaurant name, rating, delivery time, and category tag chips.
- A horizontally scrollable row of category filter chips with an active pill style, and a vertically scrolling list of dish rows, each storing its name and unit price as data attributes and showing a plus button positioned on the corner of its dish image.
- Maintain cart state as a single plain object keyed by dish name (not an array), where each entry holds a quantity and unit price; tapping a dish's plus button must create the entry if missing and otherwise increment its existing quantity, never create a duplicate entry for the same dish.
- Write one function that is the sole source of truth for the displayed item count and total price: it must iterate every key in the cart object, sum quantities for the count and quantity times price for the total, and be called after every cart mutation.
- Tapping a dish's plus button must give momentary visual confirmation by swapping its icon to a checkmark and turning it green for about half a second before automatically reverting, without navigating away from the menu.
- A cart summary bar must stay hidden while the cart is empty and appear with a short rise-and-fade-in entrance animation the instant the first item is added, showing the item count, a label, and the running total in tabular figures so digits stay aligned as they change.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="mfo-phone">
  <div class="mfo-screen">
    <div class="mfo-status"><span>9:41</span><span class="mfo-batt"><i></i></span></div>
    <div class="mfo-cover">
      <button class="mfo-back" aria-label="Back">&#8249;</button>
      <button class="mfo-fav" aria-label="Favorite">&#9825;</button>
    </div>
    <div class="mfo-info">
      <h1>Bella Napoli</h1>
      <div class="mfo-facts"><span>&#9733; 4.8</span><span>·</span><span>25–35 min</span><span>·</span><span>$2.99 delivery</span></div>
      <div class="mfo-tags"><span>Pizza</span><span>Italian</span><span>Pasta</span></div>
    </div>

    <div class="mfo-cats" id="mfoCats">
      <button class="mfo-cat active">Popular</button>
      <button class="mfo-cat">Pizza</button>
      <button class="mfo-cat">Pasta</button>
      <button class="mfo-cat">Drinks</button>
    </div>

    <div class="mfo-menu" id="mfoMenu">
      <div class="mfo-dish" data-name="Margherita" data-price="12.50">
        <div class="mfo-dtext"><b>Margherita</b><small>Tomato, mozzarella, fresh basil</small><span class="mfo-price">$12.50</span></div>
        <div class="mfo-dimg p1">🍕<button class="mfo-add" aria-label="Add Margherita">+</button></div>
      </div>
      <div class="mfo-dish" data-name="Pepperoni" data-price="14.00">
        <div class="mfo-dtext"><b>Pepperoni</b><small>Double pepperoni, mozzarella, oregano</small><span class="mfo-price">$14.00</span></div>
        <div class="mfo-dimg p2">🍕<button class="mfo-add" aria-label="Add Pepperoni">+</button></div>
      </div>
      <div class="mfo-dish" data-name="Carbonara" data-price="13.75">
        <div class="mfo-dtext"><b>Spaghetti Carbonara</b><small>Egg, pecorino, guanciale, pepper</small><span class="mfo-price">$13.75</span></div>
        <div class="mfo-dimg p3">🍝<button class="mfo-add" aria-label="Add Carbonara">+</button></div>
      </div>
      <div class="mfo-dish" data-name="Tiramisu" data-price="6.50">
        <div class="mfo-dtext"><b>Tiramisu</b><small>Mascarpone, espresso, cocoa</small><span class="mfo-price">$6.50</span></div>
        <div class="mfo-dimg p4">🍰<button class="mfo-add" aria-label="Add Tiramisu">+</button></div>
      </div>
    </div>

    <button class="mfo-cart" id="mfoCart" hidden>
      <span class="mfo-badge" id="mfoCount">0</span>
      <span>View cart</span>
      <span class="mfo-cttl" id="mfoTotal">$0.00</span>
    </button>
  </div>
</div>

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA restaurant page renders with a hero cover, category chips, and a dish menu.
  2. 2
    Add a dishTap the plus on a dish image — it flashes a green check and the cart bar rises into view.
  3. 3
    Add moreAdding the same dish again increments its quantity; the count and total update live.
  4. 4
    Watch the totalThe sticky cart bar shows the item count badge and the summed price in aligned figures.
  5. 5
    Switch categoriesThe pill chips move the active highlight between menu sections.
  6. 6
    Wire your checkoutPass the cart object to your order flow and feed dishes from your API.

Real-world uses

Common Use Cases

Food delivery apps
The menu step before a mobile checkout screen.
Restaurant pages
Pair dishes with a product card grid.
Add-to-cart flows
Reuse the button like an add to cart button.
Cart summaries
Feed the tally into a mini cart.
App mockups
Present it inside a phone mockup.
Learning cart state
A reference for keyed cart objects and derived totals.
Related: Mobile Calendar Screen
See the Mobile Calendar Screen for a related mobile pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Adds are stored in a cart object keyed by dish name. Adding a dish that already exists increments its quantity property rather than creating a second entry. The refresh function then sums quantities and prices across all keys, so the count and total always reflect the merged quantities.

The refresh function derives the count and total from the cart object on every change, so the displayed numbers are always consistent with the actual cart contents. Nudging a running total up by hand risks drift if you later add remove or edit actions; deriving from the source object stays correct no matter what changed.

On tap the plus button adds a green class and swaps to a check for about half a second, then a timeout restores the plus. This gives immediate visual confirmation that the item landed in the cart while keeping you on the menu, which is how real delivery apps encourage adding multiple items in one visit.

The bar carries the hidden attribute while the cart is empty and is revealed the moment the count goes above zero, entering with a short rise-and-fade animation. An empty cart bar would be noise, so surfacing it only when there is something to view keeps the screen focused on the menu.

Hold the cart as a keyed object or Map in state and derive the count and total with useMemo (React), computed (Vue), or a getter (Angular). Render dishes from your menu data and wire each add button to a state updater. Show the cart bar conditionally on count. Replace the timeout feedback with a state flag if you prefer. The CSS and Tailwind utilities port directly.