Drawing dimension lines on a web page
How the live, millimetre-accurate dimension lines on this site work, with ResizeObserver, a little SVG and one conversion factor.
If you resize the window on the home page of this site, the red dimension lines around my name update as you go. They report the size of the heading in millimetres, the way a construction drawing would. It is a small joke for people who work in both of my worlds, and it turned out to be a neat little piece of frontend.
Step one: measure the element
ResizeObserver tells you whenever an element changes size, which is exactly what you want here. Window resize events are not enough, because the heading can also change size when fonts finish loading.
const ref = useRef(null);
const [box, setBox] = useState({ w: 0, h: 0 });
useEffect(() => {
const el = ref.current;
if (!el) return;
const ro = new ResizeObserver(([entry]) => {
const { width, height } = entry.contentRect;
setBox({ w: width, h: height });
});
ro.observe(el);
return () => ro.disconnect();
}, []);Step two: convert to millimetres
CSS defines one inch as exactly 96 CSS pixels, and an inch is 25.4 mm. So one CSS pixel is 25.4 / 96, about 0.2646 mm. This is a reference measurement, not what a ruler held to your screen would show, but it is the same convention every browser uses for print, so it is a fair one.
const PX_TO_MM = 25.4 / 96;
const mm = Math.round(box.w * PX_TO_MM);Step three: draw it like a drafter would
Architectural dimensions end in short 45° ticks rather than arrowheads, with extension lines that run past the dimension line slightly. In SVG that is just a few line elements. I set vector-effect: non-scaling-stroke so the hairlines stay one pixel wide however the SVG is sized.
<svg width={w} height={24} aria-hidden="true">
<line x1={0} y1={12} x2={w} y2={12} /> {/* dimension line */}
<line x1={0} y1={0} x2={0} y2={24} /> {/* extension lines */}
<line x1={w} y1={0} x2={w} y2={24} />
<line x1={-5} y1={17} x2={5} y2={7} /> {/* 45° ticks */}
<line x1={w - 5} y1={17} x2={w + 5} y2={7} />
</svg>Step four: one moment of motion
On first load the lines draw outward from the centre with a CSS scaleX animation, and the number fades in after. That is the only animation on the page that runs without you doing something. Everything else stays still, and the whole thing switches off for anyone with reduced motion turned on.
Keeping it out of the way
The SVG is marked aria-hidden, because a screen reader announcing "312" before my name would be confusing, not charming. The heading itself stays a plain h1. Decoration should never cost the content anything.
- Frontend
- Build notes