Gauge Meter
Half-circle gauge, green to red, with a needle that swings to the value when the gauge appears, then follows every new value.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Data has 28 effects, including 1 free. Explore the category →
3 usage examples



How it works
The whole drawing sits in a 160 × 100 SVG: a half circle of radius 60 (.gmtr-track), the same half circle painted with a green → yellow → red gradient (.gmtr-fill), a white needle (.gmtr-needle) pivoting around the hub at the centre of the dial, and the value written below it (.gmtr-value). Arc and needle always show the same value: 70% paints 70% of the half circle and sets the needle at 36° (from −90° for 0% to +90° for 100%). The text sits below the hub, so the needle never crosses it.
The value is read from aria-valuenow (between aria-valuemin and aria-valuemax, 0 and 100 by default). By default the text is a percentage in the page format ("70%", "70 %" in French); with data-unit, it shows the raw value followed by the unit, for example aria-valuemax="10" data-unit=" / 10" gives "7 / 10".
Arc and needle stay at zero until the gauge is half visible, then rise over 2 s (ease-out), only once. A new value written to aria-valuenow later makes the needle and arc glide to it. Each gauge has its own gradient id and nothing is declared on window: several gauges live together in the page.
Accessibility
- Role:
role="meter"(a measurement within a known range), witharia-valuetextcopied from the displayed text. Name the gauge witharia-label("Estimated effort", "Bin fill level"). - Colour and text: the gradient is not the only information, the value is written in figures below the needle.
- Reduced motion: under
prefers-reduced-motion: reduce, no swing and no animated fill; the gauge shows its value as soon as it appears and jumps straight to later values. - Reading: a new value is not announced on its own (a gauge is not a live region); if the change matters, announce it in an
aria-liveregion of your own.
Browser compatibility
SVG, CSS transforms on SVG elements, CSS variables and dependency-free JavaScript (about 2.5 KB). Measured on 08/11/2026 in Chromium 151, Firefox 153 and WebKit 26.5 (Playwright): arc at 70% and needle at 36° in all three, whole arc with no cut, a gauge further down waiting for the scroll, a new value on the 2nd copy without touching the 1st, 390 px, reduced motion, no error. Versions taken from @mdn/browser-compat-data: IntersectionObserver sets the minimum.
Without IntersectionObserver, the gauge takes its value on load. Without JavaScript, the dial is empty, the needle lies to the left, and the HTML text ("70%") remains readable.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0228-root">
<div class="gmtr-gauge" role="meter" aria-label="Level" aria-valuemin="0" aria-valuemax="100" aria-valuenow="70">
<svg class="gmtr-svg" viewBox="0 0 160 100" aria-hidden="true">
<defs><linearGradient id="gmtr-grad">…</linearGradient></defs>
<path class="gmtr-track"></path>
<path class="gmtr-fill"></path>
<rect class="gmtr-needle"></rect>
<circle class="gmtr-halo"></circle>
<circle class="gmtr-hub"></circle>
</svg>
<span class="gmtr-value">70%</span>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Value (HTML — aria-valuenow on .gmtr-gauge) |
70 | Change it at start or in JavaScript (gauge.setAttribute('aria-valuenow', 45)): arc, needle and text follow. |
Bounds (HTML — aria-valuemin, aria-valuemax) |
0 and 100 | A score out of 10: aria-valuemax="10". The needle sits at the matching share of the range. |
Displayed unit (HTML — data-unit) |
absent: percentage ("70%") | When present, the text becomes the raw value plus the unit: data-unit=" / 10" → "7 / 10", data-unit=" mph" → "70 mph". |
Name for screen readers (HTML — aria-label) |
Level | What the gauge measures: "Estimated effort", "Server load". |
Dial colours (CSS — --gmtr-low, --gmtr-mid, --gmtr-high, --gmtr-track) |
#22c55e · #eab308 · #ef4444 · indigo at 20% | The gradient runs left to right. If the top of the scale is good news (full battery), swap --gmtr-low and --gmtr-high. |
Needle and hub (CSS — --gmtr-needle, --gmtr-glow) |
#fff · indigo at 35% | On a light background, a dark needle (#1f2937) and a light or transparent halo. |
Size (CSS — --gmtr-size) |
160px | Width of the gauge; the text is 12.5% of that width. |
Duration (CSS — --gmtr-duration) |
2s | Length of the first swing and the next ones. |
Background, text and height (CSS — --gmtr-bg, --gmtr-text, --gmtr-height) |
#0a0a0f · #fff · 300px | On a light page: --gmtr-bg:transparent; --gmtr-text:#111827; --gmtr-height:0px. |
FAQ
.gmtr-value{display:none} in your CSS. Screen readers still hear the value through aria-valuetext. Then write it elsewhere if colour alone is not enough for your visitors.aria-valuemin="0" aria-valuemax="120"), put the measurement in aria-valuenow and the unit in data-unit (" mph"). The number follows the page format, decimal included.data-unit is used.