---
name: futuristic-hud-interface
description: Use when you want "Sci-fi, complex, exotic" - Uses rings, grids, panels, and metrics like a sci-fi heads-up display.
---

# Futuristic HUD Interface

> **Category:** Premium / Futuristic  -  **Personality:** Sci-fi, complex, exotic
>
> **Best use:** Gaming, cyber, dashboards
>
> **Ratings:** Professional 2/5 - Casual 2/5 - Exotic 5/5 - Visual impact 5/5 - Difficulty 5/5 - Performance cost 4/5

## What it is

A "heads-up display" composition: a dark, glowing command console layered from many small primitives — concentric **SVG range rings**, a rotating **tick bezel**, dashed counter-rotating rings, a **conic-gradient radar sweep**, **corner brackets**, a centered **targeting reticle**, segmented bar gauges, and dense **monospace telemetry** that updates live. No single trick carries it; the cinematic effect comes from *stacking* legible HUD elements over a scanning grid with scanlines and a vignette. Reach for it on gaming, cyber-security or "mission-control" dashboards where the *vibe* is the product.

## Dependencies / CDN

None - pure CSS + inline SVG + vanilla JS. Two Google Fonts give it the console look (optional):

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Oxanium:wght@400;600;700;800&family=Share+Tech+Mono&display=swap" rel="stylesheet">
```

`Oxanium` is the angular display/label face; `Share Tech Mono` (with `font-variant-numeric: tabular-nums`) keeps the readouts from jittering as digits change.

## HTML

Trimmed scaffold — a framed stage, the radar core, one telemetry readout + gauge, and the pointer reticle (a direct child of the stage so it can track anywhere):

```html
<div class="hud-stage" id="hud">
  <div class="hud-bggrid"></div>                 <!-- drifting grid -->
  <i class="hud-corner tl"></i><i class="hud-corner tr"></i>
  <i class="hud-corner bl"></i><i class="hud-corner br"></i>

  <!-- central radar / reticle -->
  <div class="hud-core">
    <div class="hud-sweep"></div>                <!-- conic-gradient sweep -->
    <svg viewBox="0 0 360 360">
      <g class="ring"><circle cx="180" cy="180" r="150"/><circle cx="180" cy="180" r="112"/>
                      <circle cx="180" cy="180" r="74"/><circle cx="180" cy="180" r="36"/></g>
      <g class="grid" id="spokes"></g>            <!-- JS fills radial spokes -->
      <g class="cross"><line x1="180" y1="14" x2="180" y2="346"/><line x1="14" y1="180" x2="346" y2="180"/></g>
      <g class="tick hud-spin" id="ticks"></g>    <!-- JS fills rotating tick bezel -->
      <circle class="hud-spin s2" cx="180" cy="180" r="160" fill="none"
              stroke="#34e7ff" stroke-width="2" stroke-dasharray="2 11" opacity=".5"/>
      <circle class="arc-track" cx="180" cy="180" r="128"/>
      <circle class="arc" id="arc" cx="180" cy="180" r="128" transform="rotate(-90 180 180)"/>
    </svg>
    <div class="hud-core-read">
      <span class="lab">Reactor Output</span>
      <span class="big"><b data-k="pwr">87.4</b><u>%</u></span>
      <span class="sub" data-k="pwrStat">&#9679; NOMINAL</span>
    </div>
  </div>

  <!-- telemetry readout + segmented gauge -->
  <div class="hud-read"><span class="k">Altitude</span>
    <span class="v"><b data-k="alt">412.6</b><u>km</u></span></div>
  <div class="hud-seg" data-seg data-n="18" data-k="thr"></div>

  <!-- interactive targeting reticle (hover-only) -->
  <div class="hud-reticle" id="reticle">
    <svg viewBox="0 0 54 54"><circle cx="27" cy="27" r="15"/>
      <line x1="27" y1="0" x2="27" y2="12"/><line x1="27" y1="42" x2="27" y2="54"/>
      <line x1="0" y1="27" x2="12" y2="27"/><line x1="42" y1="27" x2="54" y2="27"/>
      <circle class="dot" cx="27" cy="27" r="2"/></svg>
    <span class="tag">BRG 142&deg; / RNG 4.20km</span>
  </div>
</div>
```

## CSS

The load-bearing pieces (palette vars, scanning grid, the rotating-ring trick, the radar sweep, segmented gauge, and the reduced-motion freeze):

```css
.hud-stage{
  --h-cy:#34e7ff; --h-am:#ffb13b; --h-rd:#ff4d6d; --h-gn:#53f3a6;
  --h-line:rgba(52,231,255,.18); --h-grid:rgba(52,231,255,.055); --h-cyd:rgba(52,231,255,.55);
  position:relative; overflow:hidden; border-radius:20px; isolation:isolate; min-height:680px;
  color:#d2eefb; font-family:'Oxanium',system-ui,sans-serif;
  background:
    radial-gradient(120% 90% at 50% -12%, rgba(52,231,255,.12), transparent 58%),
    linear-gradient(162deg,#06101c,#04080f 70%);
}
/* scanning grid (masked + drifting) */
.hud-bggrid{position:absolute; inset:-2px; z-index:0; pointer-events:none;
  background-image:linear-gradient(var(--h-grid) 1px,transparent 1px),
                   linear-gradient(90deg,var(--h-grid) 1px,transparent 1px);
  background-size:34px 34px;
  -webkit-mask:radial-gradient(125% 105% at 50% 40%,#000 52%,transparent 100%);
          mask:radial-gradient(125% 105% at 50% 40%,#000 52%,transparent 100%);
  animation:hud-griddrift 14s linear infinite}
@keyframes hud-griddrift{to{background-position:0 34px,34px 0}}

/* spin ANY concentric SVG group around its own centre */
.hud-spin{transform-box:fill-box; transform-origin:center; animation:hud-rot 20s linear infinite}
.hud-spin.s2{animation-duration:30s; animation-direction:reverse}
@keyframes hud-rot{to{transform:rotate(360deg)}}

/* radar sweep = a rotating conic gradient, ring-masked */
.hud-sweep{position:absolute; inset:6.5%; border-radius:50%; pointer-events:none;
  background:conic-gradient(from 0deg, transparent 0 268deg,
            rgba(52,231,255,.04) 300deg, rgba(52,231,255,.5) 358deg, transparent 360deg);
  -webkit-mask:radial-gradient(circle,#000 0 57%,transparent 63%);
          mask:radial-gradient(circle,#000 0 57%,transparent 63%);
  animation:hud-rot 4.8s linear infinite}

/* gauge ring: dash the whole circumference, reveal with dashoffset (set in JS) */
.hud-core .arc-track{stroke:rgba(52,231,255,.12); fill:none; stroke-width:6}
.hud-core .arc{stroke:var(--h-cy); fill:none; stroke-width:6; stroke-linecap:round;
  filter:drop-shadow(0 0 6px var(--h-cyd))}

/* segmented bar gauge */
.hud-seg{display:flex; gap:3px; height:10px}
.hud-seg i{flex:1; border-radius:1px; background:rgba(52,231,255,.12)}
.hud-seg i.on{background:var(--h-cy); box-shadow:0 0 6px var(--h-cyd)}

/* hover-only targeting reticle (moved by JS transform) */
.hud-reticle{position:absolute; left:0; top:0; z-index:8; width:54px; height:54px;
  pointer-events:none; opacity:0; transition:opacity .25s}
.hud-reticle.live{opacity:.92}
.hud-reticle svg line,.hud-reticle svg circle{stroke:var(--h-cy); fill:none; stroke-width:1.4}

@media (prefers-reduced-motion: reduce){
  .hud-bggrid,.hud-spin,.hud-sweep{animation:none!important}   /* static HUD: no spin/sweep */
  .hud-sweep{opacity:.34}
}
```

## JavaScript

Generates the dense primitives, animates the gauge/telemetry, and drives the pointer reticle. The `reduce` guard is checked **before** starting any loop:

```js
(function(){
  var stage=document.getElementById('hud'); if(!stage) return;
  var SVG='http://www.w3.org/2000/svg';
  var reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  var pol=(cx,cy,r,d)=>{var a=(d-90)*Math.PI/180; return [cx+r*Math.cos(a), cy+r*Math.sin(a)];};
  var ln=(a,b)=>{var l=document.createElementNS(SVG,'line');
    l.setAttribute('x1',a[0]);l.setAttribute('y1',a[1]);l.setAttribute('x2',b[0]);l.setAttribute('y2',b[1]);return l;};

  // 72-tick rotating bezel (major every 30deg) + 12 radar spokes
  var ticks=document.getElementById('ticks');
  for(var t=0;t<360;t+=5){var maj=t%30===0,len=maj?14:7,l=ln(pol(180,180,168,t),pol(180,180,168-len,t));
    l.setAttribute('class', maj?'tick maj':'tick'); ticks.appendChild(l);}

  // gauge ring: dasharray = circumference, dashoffset = remaining
  var arc=document.getElementById('arc'), C=2*Math.PI*128; arc.style.strokeDasharray=C;
  var setArc=p=>arc.style.strokeDashoffset = C*(1-p/100);

  // segmented bars: build N <i>, light the first round(pct%)
  var segs={};
  stage.querySelectorAll('[data-seg]').forEach(el=>{var n=+el.dataset.n||16; el.innerHTML='';
    for(var i=0;i<n;i++) el.appendChild(document.createElement('i')); segs[el.dataset.k]={el,n};});
  function setSeg(k,pct){var g=segs[k]; if(!g) return; var on=Math.round(pct/100*g.n);
    [].forEach.call(g.el.children,(c,i)=>c.classList.toggle('on', i<on));}

  // live telemetry (small clamped random-walk)
  var put=(k,v)=>{var e=stage.querySelector('[data-k="'+k+'"]'); if(e) e.textContent=v;};
  var S={pwr:87.4,thr:74,alt:412.6};
  var wlk=(v,d,lo,hi)=>{v+=(Math.random()*2-1)*d; return v<lo?lo:v>hi?hi:v;};
  function render(){ put('pwr',S.pwr.toFixed(1)); put('alt',S.alt.toFixed(1)); setSeg('thr',S.thr); setArc(S.pwr); }
  render();
  if(!reduce) setInterval(()=>{ S.pwr=wlk(S.pwr,.5,82,92); S.thr=wlk(S.thr,1.6,60,92); S.alt=wlk(S.alt,.4,409,416); render(); }, 900);

  // pointer reticle: appears on hover, transforms to the cursor, reads bearing/range from centre
  var ret=document.getElementById('reticle'), tag=ret.querySelector('.tag');
  function place(x,y,w,h){
    ret.style.transform='translate('+(x-27)+'px,'+(y-27)+'px)';
    var dx=x-w/2, dy=y-h/2, brg=(Math.atan2(dx,-dy)*180/Math.PI+360)%360;
    tag.textContent='BRG '+('00'+Math.round(brg)).slice(-3)+'° / RNG '+(Math.hypot(dx,dy)/(Math.min(w,h)/2)*9.4).toFixed(2)+'km';
  }
  if(!reduce){
    stage.addEventListener('pointermove',e=>{var r=stage.getBoundingClientRect();
      ret.classList.add('live'); place(e.clientX-r.left, e.clientY-r.top, r.width, r.height);});
    stage.addEventListener('pointerleave',()=>ret.classList.remove('live'));
  }
})();
```

## How it works

- **Stack of cheap primitives.** Each ring/tick/spoke is a plain SVG `<circle>`/`<line>`. Density (72 ticks, 4 range rings, dashed rings, spokes) reads as "complex instrument" while staying vector-crisp at any size.
- **`transform-box: fill-box` + `transform-origin: center`** lets a single `@keyframes rotate(360deg)` spin *any* concentric SVG group around the dial centre without hand-computing a pixel origin. Different `animation-duration`/`direction` per ring gives parallax.
- **Radar sweep = rotating `conic-gradient`.** A bright trailing wedge fading to transparent, clipped to a ring with a `radial-gradient` mask, then spun with the same rotate keyframe. No SVG, no canvas.
- **Gauge ring = `stroke-dasharray`/`stroke-dashoffset`.** Set the dash to the full circumference and reveal a percentage by animating the offset; `rotate(-90deg)` starts it at 12 o'clock.
- **Live telemetry** is a clamped random-walk on a `setInterval`, rendered into `tabular-nums` mono text so the layout never shifts.
- **Targeting reticle** is a hover-only overlay that is a *direct child of the stage*, moved with a `transform: translate` to the pointer; bearing is `atan2(dx, -dy)` (north = up) and range is the normalised distance from centre.

## Customization

- **Palette:** every colour is a CSS var on `.hud-stage` (`--h-cy` primary, `--h-am` amber alert, `--h-rd` lock, `--h-gn` nominal). Swap `--h-cy` to amber/green for a different faction.
- **Density / speed:** add ticks by changing the `5`deg step; change ring `animation-duration` to slow/quicken the spin; tune the sweep period (`4.8s`).
- **Theme:** it's a recipe, not just a radar — reuse the bezel + arc as a circular KPI, the segmented bars as battery/signal meters, the ticker as a status feed.
- **Gauge value** is data-driven: feed real numbers into `setArc()` / `setSeg()` / `put()` instead of the random-walk.

## Accessibility & performance

- **Reduced motion:** the JS reads `prefers-reduced-motion` and never starts the telemetry/sweep loops; CSS `animation:none` freezes spin/grid/sweep so the HUD renders as a clean static frame.
- All decorative layers are `aria-hidden`/`pointer-events:none`; the reticle is purely visual. Put the *real* information (the numbers) in normal, readable DOM so it's available to AT and not trapped in canvas.
- It's GPU-cheap (transform/opacity only — no layout thrash, no per-frame canvas), but it is *busy*: keep body copy off the animated zones and ensure your mono text clears the WCAG contrast bar against the dark field.

## Gotchas

- **`transform-box: fill-box` is required** for the spin trick — without it `transform-origin: center` resolves against the SVG viewport, not the group, and concentric rings wobble off-axis.
- **Mask needs the `-webkit-` prefix** (`-webkit-mask`) for the sweep/grid or Safari shows a full disc / unmasked grid.
- **The reticle must be a child of the element you measure.** If it lives inside an inner column but you translate it with stage-relative coordinates, it drifts by that column's offset — keep the positioned ancestor and the coordinate space the same (here: the stage).
- **`overflow:hidden` + `isolation:isolate`** on the stage are what keep the glow, masks and the off-frame reticle tag clipped to the rounded panel instead of spawning a page scrollbar.
- Don't animate the gauge by re-rendering the whole SVG; only mutate `stroke-dashoffset` / toggle `.on` classes.
