webdevpuneet.com

EV Charging Status Card — Free HTML CSS JS Snippet

EV Charging Status Card · Cards · Plain HTML, CSS & JS · Live preview

CategoryCards

Copy & paste

Source Code

<div class="wrap">
  <div class="ev-card">
    <div class="ev-head">
      <div>
        <h3>Model 3 · Garage</h3>
        <p class="ev-plug">Connected — AC Level 2, 7.4 kW</p>
      </div>
      <span class="ev-badge" id="evBadge">Charging</span>
    </div>

    <div class="ev-battery">
      <svg class="ev-battery-shell" width="120" height="60" viewBox="0 0 120 60">
        <rect x="2" y="2" width="106" height="56" rx="10" fill="none" stroke="#e2e8f0" stroke-width="3"/>
        <rect x="110" y="20" width="8" height="20" rx="3" fill="#e2e8f0"/>
        <clipPath id="battClip"><rect x="6" y="6" width="98" height="48" rx="7"/></clipPath>
        <rect id="battFill" x="6" y="6" width="0" height="48" rx="7" fill="#22c55e" clip-path="url(#battClip)"/>
      </svg>
      <div class="ev-pct-wrap">
        <span class="ev-pct" id="evPct">0%</span>
        <span class="ev-pct-label">charged</span>
      </div>
    </div>

    <div class="ev-stats">
      <div class="ev-stat">
        <span class="ev-stat-label">Range added</span>
        <span class="ev-stat-val" id="evRange">0 mi</span>
      </div>
      <div class="ev-stat">
        <span class="ev-stat-label">Time to full</span>
        <span class="ev-stat-val" id="evEta">--:--</span>
      </div>
      <div class="ev-stat">
        <span class="ev-stat-label">Est. cost</span>
        <span class="ev-stat-val" id="evCost">$0.00</span>
      </div>
    </div>

    <button class="ev-stop-btn" id="evStop">Stop charging</button>
  </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

A single pct value drives the battery fill, percentage text, range added, ETA, and cost together
Range added and cost are computed from kWh added since session start, not total battery charge
Time-to-full recalculated every tick from remaining kWh divided by charger rate, not a separate countdown
Battery fill color shifts red / amber / green based on current charge level
Animated SVG battery shell with a clipped fill rectangle that transitions smoothly on width change
Automatic "Complete" state once the target percentage is reached, disabling the stop button
Stop-charging control freezes the session and correctly reflects a partial-session range/cost
Dark card treatment suited to an in-vehicle or charger-kiosk display context

About this UI Snippet

EV Charging Status Card — Animated Battery, Live ETA & Cost Estimate

Screenshot of the EV Charging Status Card snippet rendered live

An EV charging screen has to answer three questions a driver actually cares about while they wait: how much battery is added, how much longer until it's done, and what is this session costing. This card ties all three to a single pct (current charge percentage) value, so as the battery fills, the range, ETA, and running cost recompute together instead of drifting out of sync with separately-tracked numbers.

One percentage value drives four different displays

pct is the only thing that changes on every tick(). The SVG battery fill's width attribute, the large percentage readout, the "range added" estimate, and the running cost are all recomputed from pct inside a single render() call. This is deliberate: a charging UI that tracked range and cost as independently-incrementing counters would risk them drifting out of sync with the percentage bar if any one calculation had a rounding bug — deriving everything from one source number rules that class of bug out entirely.

Why range and cost use kWh added, not kWh remaining

kwhAdded is computed as ((pct - START_PCT) / 100) * BATTERY_KWH — the *delta* since the session started, not the battery's current total charge. This matters because the driver's real question is "how much has *this* charging session given me," not "how full is the battery overall" (a battery that started at 34% and is now at 60% has added 26 percentage points of range and cost, and the card should show exactly that, not a number based on the full 60%).

Time-to-full derived from charge rate, not a countdown timer

Rather than counting down a separately-ticking clock (which could desync from the actual fill animation), etaEl's text is recalculated every tick from remainingKwh / CHARGE_RATE_KW — the battery capacity still needed to reach TARGET_PCT, divided by the charger's rate in kW. This means the ETA always reflects the true remaining distance to the *target* charge level (commonly 80%, not 100%, since most EV charging guidance caps daily charging there to preserve battery health) rather than an arbitrary fixed countdown.

Battery fill color as a secondary signal

colorForPct() shifts the battery's fill color from red below 20%, to amber up to 50%, to green above that — a quick-glance health indicator layered on top of the numeric percentage, similar to how a phone's battery icon changes color at low charge. The color and the numeric percentage are computed together in the same render() call so they can never show a contradictory state (like a green icon at 15%).

Stopping mid-session

The "Stop charging" button freezes pct at whatever the interval last reached rather than resetting anything — every other displayed value (range added, cost) remains correctly computed for the *partial* session, since they were always derived from the current pct, not from an assumption that charging would run to completion.

Step by step

How to Use

  1. 1
    Watch it chargepct increments automatically toward TARGET_PCT — the battery fill, percentage, range, ETA, and cost all update together every tick.
  2. 2
    Set the session parametersEdit START_PCT, TARGET_PCT, BATTERY_KWH, CHARGE_RATE_KW, MILES_PER_KWH, and COST_PER_KWH at the top of the JS to match a real vehicle and charger.
  3. 3
    Connect real charger telemetryReplace the setInterval(tick, 450) simulation with a callback from your charger or vehicle API that sets pct directly, then calls render().
  4. 4
    Adjust the color thresholdsEdit the percentage cutoffs inside colorForPct() to change when the battery fill switches from red to amber to green.
  5. 5
    Wire up Stop chargingReplace the click handler's local state change with an actual API call to halt the charger session, then update the badge on a successful response.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a Tailwind CSS version.

Real-world uses

Common Use Cases

EV owner mobile apps
The core use case — a live charging status screen for a home wallbox or public charger session, viewed from the vehicle owner's phone.
Public charging network dashboards
Show session status across multiple bays on a charging network operator's station management dashboard.
In-vehicle infotainment displays
A dark, glanceable layout suited to a car's center console screen while parked and charging.
Home energy management systems
Pair with solar/battery monitoring in a smart-home energy app, showing EV charging as one load alongside household consumption.
Learn single-source-of-truth UI patterns
A clean example of deriving multiple displayed values (range, cost, ETA) from one underlying number rather than tracking each separately.
Fleet and workplace charging management
Adapt the cost estimate and time-to-full fields for a fleet manager tracking multiple vehicles charging on a shared workplace charger bank.

Got questions?

Frequently Asked Questions

Counting down a separate timer risks it drifting out of sync with the actual battery fill percentage. Instead, etaEl is recalculated from remainingKwh (target minus current charge) divided by CHARGE_RATE_KW on every tick, so the ETA always reflects the true remaining distance to TARGET_PCT even if the fill rate changes.

kwhAdded is (pct - START_PCT) / 100 * BATTERY_KWH — the energy added during this specific session, not the battery's overall state of charge. This matches what a driver actually wants to know: what did this charging session give me, not how full is the battery overall.

TARGET_PCT defaults to 80 because many EV manufacturers recommend daily charging to around 80% rather than 100% to reduce long-term battery degradation, reserving a full charge for longer trips. Change TARGET_PCT to 100 if your use case needs a full-charge session.

Remove the setInterval(tick, 450) simulation and instead call render() whenever your charger or vehicle telemetry API delivers a new percentage reading, after setting the pct variable to that real value.

colorForPct() returns red below 20%, amber from 20-49%, and green from 50% up — computed fresh every render() call from the same pct value used everywhere else on the card, so the color can never contradict the displayed percentage.

pct freezes at its current value, running is set to false, and the badge and button update to a stopped state. Because range added and cost were always derived from the current pct rather than an assumption of reaching TARGET_PCT, they remain correct for the partial session with no extra logic needed.