Loading
The General Translation logo while a page loads, running live, then the work behind it: the hovers, how the motion is built, the checks that hold it and the fix that keeps everything but the moving line on the logo itself.
The loader
Meridian, then G. The meridian draws back once, then a line runs once round the meridian and the G draws off and back on once round the equator, for as long as the page loads.
Meridian, then G
The loader at 200 pixels, the live component this site uses. Every frame outside the moving line is the logo.
| Beat | Time | What moves |
|---|---|---|
| Draw-back | 600 ms | Once, when the loader mounts: the meridian draws back along its oval to the logo without its meridian. |
| Meridian lap | 1250 ms | A line runs once round the meridian, over the logo without its meridian. |
| Rest | 220 ms | The logo without its meridian holds still. |
| G lap | 1400 ms | The G draws off from its tip round the equator and back on, landing on its tip again. |
| Rest | 330 ms | The logo without its meridian holds still before the next lap. |
56 px
A prototype’s frame on /present
32 px
A pane on /compare in Both, 80 sheet pixels across
16 px
The smallest size the plate checks
The hovers
Three hovers were drawn on the logo. Meridian draws back is the one the component ships, and the other two stay as videos.
The live hover
Hover or focus this mark, a link back to the marks. The meridian draws back along its oval and draws out again on leave. Inside a link, a button or an element marked data-gt-logo-host, the mark moves with its host.
Meridian draws backShipped
The meridian draws back along its own oval over both poles until the mark is the logo without its meridian, then it draws out again when the cursor leaves. Nothing else moves. The component ships this one.
Meridians draw into the poles
The meridian opens at the bar and its four ends draw back into the two poles together, then they draw out again when the cursor leaves.
Meridians fold into the bar
The meridian opens at both poles and its left half folds down into the bar, and the move runs back when the cursor leaves.
Meridian, then GShipped
The loader as a video, drawn frame by frame from the component in Chrome. It plays the draw-back, three laps and the draw-back reversed, so it starts and ends on the logo. The ring and the T hold still the whole time.
How it is built
GtLogoMotion draws with SVG and CSS alone: no video, no canvas and no script per frame.
- The numbers
- scripts/build/logo-motion.json holds the logo’s measures and, for each beat, a table of where each moving end stands at 240 samples a second. They are the numbers the published videos were rendered from.
- The generator
- pnpm build:logo-motion runs scripts/build/logo-motion.mjs, which writes GtLogoMotion.geometry.ts and GtLogoMotion.css. Neither file is edited by hand, and --check fails when either differs from what the script would write.
- The loader
- The loader animates custom properties registered with @property, a dash’s length and its start along its path for each moving line. The keyframes keep only the samples that a straight line between their neighbours misses.
- The hover
- The hover transitions each dash’s own stroke-dasharray and stroke-dashoffset, with the beat’s course written as a CSS linear() easing. A leave halfway runs back from where it is.
- The WebKit rule
- Transitions sit on each dash’s own properties, never on a registered custom property. Safari runs a transition of a registered custom property but paints the var() that reads it at the end value, so there the hover jumped to its end.
- Only the moving line moves
- The still layer is the logo’s own path. The motion layer paints that same path and a mask takes it away only where a line has been undrawn, where the logo without that line shows instead. The layers add with plus-lighter in an isolated group under masks that partition the frame, so wherever nothing is undrawn the frame is the logo pixel for pixel.
- The ring and the meridian
- No mask reaches the ring, so the ring is the logo’s own path in every frame. The meridian is only drawn and undrawn along its own ellipse at the logo’s width, and its cut faces stay where the logo’s are until the draw-back reaches them.
- Dash lengths
- The dashes run on their paths’ own lengths, with no pathLength. Chrome scaled a pathLength dash by a coarser measure of the path than it dashes by, which put a dash’s end up to half a unit short of its numbers, the G’s landing among them.
- Browsers
- The motion needs @property, linear() easing and plus-lighter: Chrome 113, Safari 17.2 and Firefox 128 or later.
import GtLogoMotion from '@/components/brand/GtLogoMotion';
<Link href='/'>
<GtLogoMotion mode='hover' size={18} />
</Link>;
<GtLogoMotion mode='loader' size={56} label='Loading the prototype' />;The checks
pnpm test:marks runs scripts/lint/logo-motion.test.mjs, which draws the component in Chrome at 4x, seeks it to every 60 fps frame of the hover, the leave, the draw-back and one whole lap, and measures each frame against the logo.
- Hand-off
- At the start of the hover and of the loader, at the end of the leave and at every seam of the lap, the motion layer is the still logo with no pixel different.
- Still
- In every frame, every pixel is the logo where the meridian is drawn and the logo without its meridian where it has been undrawn, except within two pixels of the end that moves.
- Ring
- In every frame the ring’s core and outer edge, and its inner edge away from where a line merges into it, are the logo’s own pixels.
- End pose
- The draw-back ends on the logo without its meridian.
- Tip
- Through the whole loop the G’s tip is the logo’s, except while the G’s own lap runs over it.
- Meridian
- Wherever the meridian shows, every pixel it adds lies on the logo’s meridian ellipse at the logo’s width, and each cut face stands where the logo’s does within 0.05 units until the undrawn stretch reaches it.
- Steps
- No move starts or lands with a pop, and no step inside a move holds a frame.
- Course
- Every dash stands where the generator’s course puts it at that time, within 0.05 units, and no dash end jumps or stalls where the course does not.

The loader at 0.3, 1.25 and 2.55 seconds in Chrome, Firefox and WebKit, on paper and on ink. Only Chrome is held to the pixel. Firefox and WebKit round masks and blends by a level here and there, so the test draws them on request with LOGO_MOTION_BROWSERS.
Reduced motion
Under reduced motion the hover does nothing and the loader is the still logo with its label.
What reduced motion shows
The still logo, the same path as the logo everywhere else, in place of the loader and the hover.
- Every rule that moves or swaps a layer sits inside prefers-reduced-motion: no-preference, so a reader who asks for less motion sees the logo and nothing else.
- The loader keeps its live region and its label, so assistive technology still hears that the page is loading.
- The videos on this page play only while their figure is in view and motion is allowed. Their poster is the still logo.
On /compare
A pane whose page has not loaded shows the loader on the paper, 80 sheet pixels across, which is about 32 on screen in Both.
- The loader is drawn only from mount on and only over a pane still loading, so it never stands over a page that is already there.
- It leaves on the frame’s load event. A failed load can fire no load event at all, as Safari and Firefox did for a dropped connection, so each loader also leaves after 15 seconds and the pane shows whatever the browser drew.


Both panes of /compare while their pages load, in Chrome, on paper and on ink.
Before and after
Three fixes brought the loader to this state. The first keeps the logo the logo outside the moving line, the second makes the hover run in Safari, and the third keeps the ring off every mask, holds the meridian to its own ellipse and measures each dash on its path’s own length.

Frames of the hover and the loader from the first loader and from the final one. In the columns against the logo, grey is ink in both the frame and the logo, blue is ink only in the logo and red is ink only in the frame. Before, red edged every still part, because the motion layer drew them a little heavier than the logo, so the G’s top arc moved and the meridian’s C shrank. After, red is left only on the line that is moving and where the C closes behind the undrawn meridian. The G end at 4x: before, it stopped short of the logo’s tip, and after, it lands on it. The last row is the meridian’s bottom cut face at 8x: in the first hover it had moved 4.86 units by 1.083 seconds, and in the final one it has not moved.

Before: the hover in Safari, 0 to 0.6 seconds after the cursor enters. In each pair the top row is the published video and the bottom row the live component, on paper and on ink. The live mark jumped to the end of the draw-back at once.

After: the same frames once the transitions moved onto the dashes. The live mark follows the video.