Yeah, if you have or frequently interact with children, you are probably
familiar with the nonsense saying six
seven
. Is this a
ridiculously silly meme? Of course it is, but so is (for example) trying to
trick people into watching a particular music
video. Watching my first-grader
experience her first meme is wonderful and I choose to celebrate it!
Therefore, without further ado, I present:
Source code
In case you are interested, below is the source code for this animation.
Standalone HTML
This is the page linked above.
index.html HTML
<!doctype html>
<html lang="en">
<!--
Silly* six-seven animation
Christopher Phan <https://chrisphan.com/>
2026-W01
For Emmy
SPDX-License-Identifier: MIT
*This whole six-seven thing is silly, but so is finding 1000 creative ways to
trick someone into watching the same Rick Astley video :-) -->
<head>
<title>Six seven</title>
<meta charset="utf-8" />
<link href="reset.css" rel="stylesheet" />
<link href="animate.css" rel="stylesheet" />
</head>
<body>
<svg
width="800"
height="500"
xmlns="http://www.w3.org/2000/svg"
id="67_animation"
aria-label="The number 67 and the words 'six seven' in various fonts and colors move horizontally from right to left at differing speeds."
>
>
<defs>
<path
d="M 0,0 v -40 a 50 50 180 0 0 -100 0 v 120
a 50 50 180 0 0 100 0 v -19 h -20 v 14
a 30 30 180 0 1 -60 0 v -20
a 30 30 180 0 1 60 0 h 20 v -5 a 40 40 90 0 0 -40 -40
q -40 0 -40 10 v -60 a 30 30 180 0 1 60 0 v 30 z"
id="six"
/>
<path
d="M 0,0 h 150 v 25 c -30,0 -70,30 -70,70 v 30 h 50 v 20 h -50
v 75 h -25 v -75 h -50 v -20 h 50 v -35 c 0,-30 30,-50 40,-60
h -110 v -25 z "
id="seven"
/>
<g id="six-seven">
<use href="#six" x="100" y="90" style="transform: scale(0.2)" />
<use href="#seven" x="135" y="2" style="transform: scale(0.2)" />
</g>
<path
id="disp_seg_vert"
d="M 0,0 l 20,20 v 50 l -20,20 l -20,-20
v -50 l 20,-20 "
/>
<g id="disp_seg_horiz">
<use href="#disp_seg_vert" style="transform: rotateZ(-90deg)" />
</g>
<g id="6_lcd">
<use href="#disp_seg_horiz" x="5" y="-5" />
<use href="#disp_seg_vert" />
<use href="#disp_seg_vert" y="100" />
<use href="#disp_seg_vert" x="100" y="100" />
<use href="#disp_seg_horiz" x="5" y="95" />
<use href="#disp_seg_horiz" x="5" y="195" />
</g>
<g id="7_lcd">
<use href="#disp_seg_horiz" />
<use href="#disp_seg_vert" x="95" y="5" />
<use href="#disp_seg_vert" x="95" y="100" />
</g>
<g id="67_lcd">
<use href="#6_lcd" />
<use href="#7_lcd" x="150" />
</g>
<pattern
id="background_6_7"
width="80"
height="80"
patternUnits="userSpaceOnUse"
patternContentUnits="userSpaceOnUse"
>
<rect fill="black" x="0" y="0" width="80" height="80" />
<use href="#six-seven" fill="#333" style="transform: scale(0.5)" />
<use
href="#67_lcd"
fill="#333"
x="400"
y="25"
style="transform: scale(0.1)"
/>
<use
href="#67_lcd"
fill="#333"
y="400"
x="25"
style="transform: scale(0.1)"
/>
<use
href="#six-seven"
fill="#333"
x="80"
y="80"
style="transform: scale(0.5)"
/>
</pattern>
<text class="label1" id="67_1">67</text>
<text class="label2" id="67_2">67</text>
<text class="label3" id="67_3">67</text>
<text class="label1" id="67_4">six seven</text>
<text class="label2" id="67_5">six seven</text>
<text class="label3" id="67_6">six seven</text>
<text class="label4" id="67_7">67</text>
<text class="label5" id="67_8">67</text>
<text class="label4" id="67_9">six seven</text>
<text class="label5" id="67_10">six seven</text>
<text class="label6" id="67_11">67</text>
<text class="label6" id="67_12">six seven</text>
<rect
class="background"
id="bg"
x="-80"
y="-80"
width="960"
height="660"
fill="url(#background_6_7)"
/>
</defs>
<style>
.label1 {
font: 60px sans-serif;
}
.label2 {
font: 120px serif;
}
.label3 {
font: 90px monospace;
}
.label4 {
font: 100px cursive;
}
.label5 {
font: 75px fantasy;
}
.label6 {
font: 130px system-ui;
}
</style>
</svg>
<script src="animation_67.js"></script>
</body>
</html>
Typescript
I wrote the main script in TypeScript. It needs to be transpiled down to JavaScript before being used.
animation_67.ts TypeScript
/* @filename: animation_67.ts
*
* Silly* six-seven animation
*
* Christopher Phan <https://chrisphan.com/>
* 2026-W01
*
* For Emmy
*
* SPDX-License-Identifier: MIT
*
* *This whole six-seven thing is silly, but so is finding 1000 creative ways to
* trick someone into watching the same Rick Astley video :-)
*
*/
class AnimatedElt {
// Represents a `use` element in an SVG that we will be moving around
elt: SVGUseElement
rootSvg: SVGElement
constructor(elt: SVGUseElement, rootSvg: SVGElement) {
this.elt = elt
this.rootSvg = rootSvg
}
create(
targetSVG: SVGElement,
x: number,
y: number,
href: string,
id: string,
fill: string
): AnimatedElt {
const elt = document.createElementNS('http://www.w3.org/2000/svg', 'use')
elt.setAttribute('x', `${x}`)
elt.setAttribute('y', `${y}`)
elt.setAttribute('id', id)
elt.setAttribute('fill', fill)
elt.setAttribute('href', `#${href}`)
targetSVG.appendChild(elt)
return new AnimatedElt(elt, targetSVG)
}
move(dx: number, dy: number) {
if (dx !== 0) {
const currentX = this.elt.getAttribute('x')
let newX = dx
if (currentX !== null) {
newX += parseFloat(currentX)
}
this.elt.setAttribute('x', `${newX}`)
}
const currentY = this.elt.getAttribute('y')
if (dy !== 0) {
let newY = dy
if (currentY !== null) {
newY += parseFloat(currentY)
}
this.elt.setAttribute('y', `${newY}`)
}
}
}
class Mover {
velocityX: number
velocityY: number
item: AnimatedElt
lastUpdate: Date
constructor(velocityX: number, velocityY: number, item: AnimatedElt) {
this.velocityX = velocityX
this.velocityY = velocityY
this.item = item
this.lastUpdate = new Date()
}
create(
targetSVG: SVGElement,
x: number,
y: number,
href: string,
id: string,
fill: string,
velocityX: number,
velocityY: number
): Mover {
const item = AnimatedElt.prototype.create(
targetSVG, x, y, href, id, fill
)
return new Mover(velocityX, velocityY, item)
}
update() {
const now = new Date()
const elapsedTime = (now.valueOf() - this.lastUpdate.valueOf()) / 1000
this.lastUpdate = now
this.item.move(this.velocityX * elapsedTime, this.velocityY * elapsedTime)
}
}
function randomColor(): string {
const hue = Math.floor(Math.random() * 360)
const sat = Math.random() * 100
const light = Math.random() * 75 + 25
return `hsl(${hue}, ${sat}%, ${light}%)`
}
/* The SVG should have the following elements defined:
* - 67_lcd
* - background_6_7 (pattern)
* - 67_n for n = 1 to 12
*
* For example: https://chrisphan.com/67_animation/
*/
function createNew(n: number, targetSVG: SVGElement): Mover {
const y = Math.random() * 500
let c = n
if (n > 13) {
c = Math.floor(Math.random() * 14)
}
let href: string = ""
if (c === 0) {
href = "six-seven"
} else if (c === 13) {
href = "67_lcd"
} else {
href = `67_${c}`
}
const id = `mover_${n}`
const fill = randomColor()
const velocityX = - (Math.random() * 50 + 50)
return Mover.prototype.create(targetSVG, 850, y, href, id, fill, velocityX, 0)
}
function update(
targetSVG: SVGElement,
objects: Array<Mover>,
active: Array<number>,
startTime: Date,
count: number,
lastAdded: Date | null,
inactive: Array<number>) {
const now = new Date()
const elapsedTime = (now.valueOf() - startTime.valueOf()) / 1000
let sinceLastAdded = 1000000
if (lastAdded !== null) {
sinceLastAdded = (now.valueOf() - lastAdded.valueOf()) / 1000
}
let newCount = count
let addedOne = false
if (elapsedTime > newCount && sinceLastAdded > 0.5) {
if (objects.length < 60) {
const newThing = createNew(count, targetSVG)
objects.push(newThing)
active.push(objects.length - 1)
addedOne = true
} else if (inactive.length > 0) {
const recycledIndex = inactive.shift()
const recycled = objects[recycledIndex]
recycled.item.elt.setAttribute('x', `${850}`)
recycled.lastUpdate = new Date()
active.push(recycledIndex)
addedOne = true
}
if (addedOne) {
newCount++
lastAdded = new Date()
}
}
let newActive: Array<number> = []
active.forEach((idx) => {
objects[idx].update()
if (objects[idx].item.elt.getAttribute('id') === 'back') {
if (parseFloat(objects[idx].item.elt.getAttribute('x')) > 80) {
objects[idx].item.elt.setAttribute('x', '0')
}
if (parseFloat(objects[idx].item.elt.getAttribute('y')) > 80) {
objects[idx].item.elt.setAttribute('y', '0')
}
newActive.push(idx)
}
else if (parseFloat(objects[idx].item.elt.getAttribute('x')) > -1000) {
newActive.push(idx)
} else {
inactive.push(idx)
}
})
window.requestAnimationFrame(
() =>
update(
targetSVG,
objects,
newActive,
startTime,
newCount,
lastAdded,
inactive)
)
}
const mainSvg = document.querySelector("svg[id='67_animation']") as SVGElement
let background = Mover.prototype.create(mainSvg, -80, -80, "bg", "back", "#333", 5, 5)
let objects: Array<Mover> = [background]
let active: Array<number> = [0]
const startTime = new Date()
update(mainSvg, objects, [0], startTime, 0, null, [])