webdevpuneet.com

Air Quality Index Gauge — Free EPA AQI Semicircle Gauge

Air Quality Index Gauge · Charts · Plain HTML, CSS & JS · Live preview

CategoryCharts

Copy & paste

Source Code

<section class="aqi-wrap">
  <span class="aqi-tag">epa aqi scale</span>
  <h1>Air Quality Index</h1>

  <div class="aqi-gauge-stage">
    <svg class="aqi-gauge" viewBox="0 0 220 130" id="aqiSvg">
      <path d="M 14 116 A 96 96 0 0 1 42.7 45.9" fill="none" stroke="#22c55e" stroke-width="18" stroke-linecap="round"/>
      <path d="M 42.7 45.9 A 96 96 0 0 1 92.3 16.4" fill="none" stroke="#eab308" stroke-width="18" stroke-linecap="round"/>
      <path d="M 92.3 16.4 A 96 96 0 0 1 127.7 16.4" fill="none" stroke="#f97316" stroke-width="18" stroke-linecap="round"/>
      <path d="M 127.7 16.4 A 96 96 0 0 1 168.5 39.6" fill="none" stroke="#ef4444" stroke-width="18" stroke-linecap="round"/>
      <path d="M 168.5 39.6 A 96 96 0 0 1 197.4 79.6" fill="none" stroke="#a855f7" stroke-width="18" stroke-linecap="round"/>
      <path d="M 197.4 79.6 A 96 96 0 0 1 206 116" fill="none" stroke="#7f1d1d" stroke-width="18" stroke-linecap="round"/>
      <line id="aqiNeedle" x1="110" y1="116" x2="110" y2="30" stroke="#fff" stroke-width="3" stroke-linecap="round" transform="rotate(0 110 116)"/>
      <circle cx="110" cy="116" r="7" fill="#fff"/>
    </svg>
    <div class="aqi-readout">
      <span class="aqi-value" id="aqiValue">42</span>
      <span class="aqi-band" id="aqiBandLabel">Good</span>
    </div>
  </div>

  <input type="range" id="aqiSlider" min="0" max="500" value="42" step="1" class="aqi-slider">

  <div class="aqi-presets" id="aqiPresets">
    <button type="button" data-val="25">Good</button>
    <button type="button" data-val="75">Moderate</button>
    <button type="button" data-val="125">USG</button>
    <button type="button" data-val="175">Unhealthy</button>
    <button type="button" data-val="250">Very Unhealthy</button>
    <button type="button" data-val="400">Hazardous</button>
  </div>

  <div class="aqi-advisory" id="aqiAdvisory">
    <strong id="aqiAdvisoryTitle">Good</strong>
    <p id="aqiAdvisoryText">Air quality is satisfactory, and air pollution poses little or no risk.</p>
  </div>
</section>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), 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

Real EPA breakpoints
50/100/150/200/300 — the actual AQI category boundaries.
Standard AQI colors
Green through maroon, matching official EPA category colors.
Six-arc SVG gauge
Each band drawn as its own proportionally sized colored arc.
Animated needle sweep
Spring-eased rotation across the full 0–500 semicircle.
Per-band health advisory
Real short-form guidance text for each category.
Slider and presets
Drag freely or jump to one value per band instantly.
Single source of truth
One BANDS table drives color, label, angle, and advisory.
Zero dependencies
Pure SVG and CSS, no charting library.

About this UI Snippet

Air Quality Index Gauge — Real EPA Breakpoints, Colors, and Advisories

Screenshot of the Air Quality Index Gauge snippet rendered live

This gauge uses the actual US EPA Air Quality Index scale — the same six categories, breakpoints, and colors published in the EPA's AQI technical documentation — not an invented 0-100 approximation. Drag the slider or click a preset and every part of the UI (needle angle, readout color, band name, health advisory) derives from the same real breakpoint table.

The real EPA breakpoints

The BANDS array encodes the actual six AQI categories: Good (0-50, green #22c55e), Moderate (51-100, yellow #eab308), Unhealthy for Sensitive Groups (101-150, orange #f97316), Unhealthy (151-200, red #ef4444), Very Unhealthy (201-300, purple #a855f7), and Hazardous (301+, maroon #7f1d1d). bandFor(aqi) walks the table and returns the first band whose max the value doesn't exceed — the same lookup logic any real AQI display uses, just applied to a value you control with a slider instead of a live sensor feed.

One SVG arc, six colored segments

The gauge is a single semicircular SVG built from six separate <path> arcs, each stroked in its band's exact color and sized proportionally to that band's real point range — the Good segment is visually narrower than Hazardous's open-ended range gets represented as a fixed final wedge, matching how AQI scales are conventionally drawn. A single needle <line> rotates from -90° (0 AQI) to +90° (500 AQI) via transform: rotate(), animated with a spring-like cubic-bezier transition so moving the slider sweeps the needle smoothly across the full 500-point scale.

A health advisory per band, not just a color

Each band carries the real short-form advisory language associated with that AQI category — from "little or no risk" at Good to "everyone is more likely to be affected" at Hazardous — so the gauge communicates what the number actually means, not just what color it is. Pair this with a weather widget or weather forecast card for a complete environmental conditions dashboard.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSThe gauge renders at AQI 42 — Good.
  2. 2
    Drag the sliderThe needle sweeps and the readout updates live, 0–500.
  3. 3
    Click a presetJump straight to a representative value for each band.
  4. 4
    Read the advisoryThe health message below updates per real EPA band.
  5. 5
    Cross the 50/100/150/200/300 marksWatch the color and band name change at the real breakpoints.
  6. 6
    Wire up live dataReplace the slider with a call to update(aqi) from an air-quality API.

Real-world uses

Common Use Cases

Weather dashboards
Add an air-quality tile next to a weather widget. The needle sweeps across six real EPA bands, from Good through Hazardous.
Environmental monitoring apps
Show live sensor readings with the correct category colour and a health advisory for each band, instead of an invented 0–100 scale.
Smart home displays
Tile an air-purifier or HVAC panel with the current AQI, so residents see at once whether to open windows or run the purifier.
Outdoor activity advice
Warn runners and cyclists before they head out. Presets let users jump to each category to read what it means for sensitive groups.
Public health portals
Publish a municipal air-quality gauge using the official breakpoints (50, 100, 150, 200 and 300), alongside a weather forecast for context.
Related: Chart.js Gradient Revenue Chart
See the Chart.js Gradient Revenue Chart for a related charts pattern worth pairing with this one.
Related: Chord Diagram Chart
See the Chord Diagram Chart for a related charts pattern worth pairing with this one.
Related: Beeswarm Plot Chart
See the Beeswarm Plot Chart for a related charts pattern worth pairing with this one.
Related: Arc Diagram Chart
See the Arc Diagram Chart for a related charts pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Yes. The BANDS table uses the real US EPA Air Quality Index breakpoints: Good 0-50, Moderate 51-100, Unhealthy for Sensitive Groups 101-150, Unhealthy 151-200, Very Unhealthy 201-300, and Hazardous 301 and above, matching the EPA's published AQI technical documentation. The colors (green, yellow, orange, red, purple, maroon) match the official category colors used on EPA and AirNow reporting.

The gauge sweeps a 180-degree semicircle, so the needle's rotation angle is (aqi / 500) * 180 - 90, mapping AQI 0 to -90 degrees (pointing left) and AQI 500 to +90 degrees (pointing right). A CSS transition with a spring-like cubic-bezier easing animates the rotation whenever the underlying value changes, whether from the slider or a preset button.

AQI values technically extend past 500 in extreme cases, but 500 is the top of the standard reporting scale used by the EPA and AirNow, and the slider and gauge are capped there (values are clamped with Math.max/Math.min). The Hazardous arc represents 301-500 on the gauge, consistent with how the scale is conventionally visualized even though real-world Hazardous readings can occasionally exceed 500.

Yes — the slider and preset buttons are just two ways of calling the same update(aqi) function, which handles clamping the value, finding the right band, and updating the needle angle, readout, and advisory text. Call update(currentAqiFromYourApi) on whatever interval your air-quality data source refreshes, and remove or hide the slider if you don't want manual control.

Keep the numeric AQI value in component state, derive the active band by running the same breakpoint lookup against it, and bind the needle's rotate() transform, the readout color, and the advisory text to that derived band — the SVG arcs themselves are static and never need to re-render, only the needle's transform attribute and a few text/color bindings change.