Mobile Ride-Hailing Screen — Free HTML CSS JS UI

Mobile Ride-Hailing Screen · Mobile · Plain HTML, CSS & JS · Live preview

What's included

Features

CSS-only map
Street grid and park drawn with gradients — no tiles.
SVG dashed route
A quadratic path with stroke-dasharray.
Teardrop pins
Classic markers from a single rotated element.
Tier selection
Accent border moves; price rewrites the CTA.
Attribute-driven price
Confirm reads data-price and data-eta.
State reset
Changing tier clears the matched confirm label.
Car animation
Web Animations drives the car to the destination.
No dependency
Pure HTML, CSS, and vanilla JavaScript.

About this UI Snippet

Mobile Ride-Hailing Screen — Ride Booking UI

Screenshot of the Mobile Ride-Hailing Screen snippet rendered live

A ride-hailing screen has a signature split: a map filling the top with pins and a route, and a bottom sheet where you pick a ride tier and confirm. This snippet builds a complete, interactive one inside a CSS phone frame — with a gridded map drawn entirely in CSS, an animated dashed route, selectable ride tiers that update the confirm price, and a car that drives along the route when you book — in HTML, CSS, and vanilla JavaScript with no map library or API key.

A map with no tiles

The map is pure CSS: two repeating linear gradients cross to form the street grid via background-size, and a blobby ::after with an organic border-radius suggests a park. The route is an inline SVG <path> with a quadratic curve and a stroke-dasharray, giving the dotted trip line without any external tiles — so the whole screen loads instantly and works offline, unlike a real map embed.

Teardrop pins

The pickup and drop-off pins use the classic map-marker shape made from a single element: a circle with three rounded corners and the fourth squared, rotated 45 degrees so the point faces down. Green marks the origin and indigo the destination, matching the dots in the trip summary below.

Tier selection that drives the price

Each ride tier is a button carrying data-price and data-eta. Selecting one moves an accent border and background to it and rewrites the confirm button's tier name and price from those attributes, so the call-to-action always reflects the current choice. Switching tiers also resets the confirm button out of its matched state — you would not want a stale "finding your Premium" label after changing your mind.

Booking animates the car

Tapping confirm turns the button green, changes its label to "Finding your …", and animates the car marker along a three-keyframe path from pickup toward drop-off using the Web Animations API with fill: 'forwards' so it holds at the destination. It is a lightweight way to convey "searching / en route" without a real GPS feed.

Accessibility and performance

Each ride tier is a real <button> and the confirm control is a button too, so the whole booking flow works from the keyboard and screen readers announce each option. When you adapt it, add aria-pressed to the selected tier so its chosen state is announced, and give the confirm button an aria-live region for the "finding your ride" status so the change is spoken, not just shown. The decorative map is inert — no focus traps, no listeners — so it never interferes with tabbing to the sheet controls. Performance is a strong point of the tile-free approach: the map is a handful of CSS gradients and one SVG path with no network requests, so it paints instantly and adds nothing to bundle size or runtime. The car animation runs through the Web Animations API, which the browser can composite off the main thread, and selecting a tier only rewrites two text nodes and toggles classes. For real geography you would swap in a map SDK, but the sheet, tiers, and confirm logic stay exactly as they are.

Reusing it

Swap the CSS map for your real map SDK, feed tiers and prices from your pricing API, and wire confirm to your booking endpoint. Keep the bottom-sheet pattern as-is — it is framework-agnostic. Present it inside a phone mockup, or pair it with a mobile map location card for a fuller navigation flow.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You do not have to guess how the tile-free map or the car animation actually work. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the crossing linear-gradient backgrounds form the street grid without any map tiles, or how the three-keyframe car.animate call with fill forwards keeps the car marker parked at its final position instead of snapping back. The same assistant can help optimize it — ask whether reading data-price and data-eta from the DOM on every tier click is the right pattern versus keeping tier data in a JavaScript array from the start, or how you would swap the CSS-drawn map for a real map SDK without breaking the bottom sheet's layout. It is just as useful for extending the feature: have it add a live ETA countdown once a ride is confirmed, support scheduling a ride for later instead of only now, or add a cancel-ride flow that reverses the confirmed state. 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 ride-hailing booking screen in plain HTML, CSS, and JavaScript inside a phone-frame container — no map SDK, no API key, no external tile service.

Requirements:
- Draw an entirely CSS-based map: use two crossing repeating linear-gradient backgrounds to form a street grid, and a separate softly-colored, irregularly-rounded shape to suggest a park or green space, with no image assets.
- Draw the trip route as an inline SVG path with a curved line and a dashed stroke-dasharray, and place two teardrop-shaped pin markers (a single element with three corners fully rounded, one corner squared, then rotated 45 degrees so the squared corner points down) in different accent colors for pickup and drop-off.
- A bottom sheet showing the pickup and drop-off addresses, a vertical list of selectable ride tiers where each tier button carries its own price and ETA as data attributes, and a payment method row.
- Selecting a ride tier must move a visible selection indicator (border and background) to the chosen tier and rewrite a confirm button's displayed tier name and price by reading that tier's data attributes, and switching tiers after a ride was already confirmed must reset the confirm button out of its confirmed state.
- Tapping confirm must change the button's label and background color to indicate a searching/matched state, then use the Web Animations API (element.animate, not CSS transitions) to move a car marker element through at least three keyframe positions approximating the route from pickup toward drop-off, holding at the final position once the animation completes.

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="mrd-phone">
  <div class="mrd-screen">
    <div class="mrd-map">
      <div class="mrd-status"><span>9:41</span><span class="mrd-batt"><i></i></span></div>
      <button class="mrd-back" aria-label="Back">&#8249;</button>
      <svg class="mrd-route" viewBox="0 0 260 320" preserveAspectRatio="none">
        <path d="M40 60 Q120 90 130 170 T210 250" fill="none" stroke="#6366f1" stroke-width="5" stroke-linecap="round" stroke-dasharray="6 10"/>
      </svg>
      <span class="mrd-pin from">A</span>
      <span class="mrd-pin to">B</span>
      <div class="mrd-car" id="mrdCar">🚗</div>
    </div>

    <div class="mrd-sheet">
      <div class="mrd-grip"></div>
      <div class="mrd-trip">
        <div class="mrd-tr"><span class="mrd-dot d1"></span><div><small>Pickup</small><b>Grand Central Station</b></div></div>
        <div class="mrd-tr"><span class="mrd-dot d2"></span><div><small>Drop-off</small><b>Brooklyn Museum</b></div></div>
      </div>

      <div class="mrd-tiers" id="mrdTiers">
        <button class="mrd-tier active" data-eta="4" data-price="14.50"><span class="mrd-ic">🚗</span><div class="mrd-tinfo"><b>Standard</b><small>4 min away</small></div><span class="mrd-tp">$14.50</span></button>
        <button class="mrd-tier" data-eta="3" data-price="22.00"><span class="mrd-ic">🚙</span><div class="mrd-tinfo"><b>Comfort</b><small>3 min away</small></div><span class="mrd-tp">$22.00</span></button>
        <button class="mrd-tier" data-eta="6" data-price="32.75"><span class="mrd-ic">🚘</span><div class="mrd-tinfo"><b>Premium</b><small>6 min away</small></div><span class="mrd-tp">$32.75</span></button>
      </div>

      <div class="mrd-pay">
        <span class="mrd-pic">VISA</span><span>•••• 4242</span><em>&#8250;</em>
      </div>
      <button class="mrd-confirm" id="mrdConfirm">Confirm <b id="mrdCTier">Standard</b> · <span id="mrdCPrice">$14.50</span></button>
    </div>
  </div>
</div>

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA ride screen renders with a CSS map, route, pins, and a bottom sheet of ride tiers.
  2. 2
    Pick a ride tierTap Standard, Comfort, or Premium — the selection border moves and the confirm price updates.
  3. 3
    Read the confirm buttonIt always shows the chosen tier name and its price so the action is unambiguous.
  4. 4
    Confirm the rideThe button turns green, switches to "Finding your…", and the car drives along the route.
  5. 5
    Change your mindSelecting a different tier resets the confirm button out of its matched state.
  6. 6
    Wire your backendSwap the CSS map for a real SDK and confirm against your booking API.

Real-world uses

Common Use Cases

Ride-hailing apps
The booking screen beside a mobile map location card.
Delivery tracking
Reuse the route for an order tracking timeline.
Bottom sheets
A ride take on a bottom sheet pattern.
Tier pickers
Adapt the tiers like a plan selector.
App mockups
Present it inside a phone mockup.
Learning CSS maps
A reference for tile-free maps and SVG routes.
Related: Mobile Food Order Screen
See the Mobile Food Order Screen for a related mobile pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

No. The map is drawn entirely in CSS: crossing linear-gradient backgrounds form the street grid and a blobby ::after suggests a park, while the route is an inline SVG path with a dashed stroke. This loads instantly and works offline. To use real geography, replace the map div with your map SDK and keep the bottom sheet unchanged.

Each pin is a single element with border-radius set to round three corners and square the fourth (50% 50% 50% 0), then rotated 45 degrees so the squared corner points downward. That produces the familiar map-marker teardrop from one div, with the letter counter-rotated to stay upright.

Each tier button carries data-price and data-eta attributes. Selecting a tier reads those attributes and rewrites the tier name and price inside the confirm button, so the call to action reflects the current choice. It also clears the matched state so a previous booking label does not linger after you switch tiers.

Confirm calls the Web Animations API on the car marker with a three-keyframe path from the pickup pin toward the drop-off pin, using fill: forwards so it holds at the end. It is a visual stand-in for a searching or en-route state; in production you would move the marker from real driver coordinates over a WebSocket.

Render the tiers from data and hold the selected tier in state; derive the confirm label and price from it rather than editing the DOM. Bind the active class to the selection and the matched class to a booking flag. Replace element.animate with a driver-position stream and animate the marker via state or a ref. Tailwind expresses the map grid, pins, and sheet with utilities.