Cinematic Filmstrip
Horizontal film reel you drag to explore. Sprocket holes, warm amber type, and frame numbers give it a physical celluloid feel — ideal for film studies, festival histories, or any media company timeline that wants to read as cinema rather than spreadsheet.
Cinematic Filmstrip the 9th of 24 designs in the 24 CSS Timeline Layouts collection. The design pairs CSS styling with a small amount of JavaScript for interactivity. Copy the HTML, CSS and JavaScript panels below into your project — the JS is self-contained, has zero dependencies, and is safe to drop into any framework (React, Vue, Svelte, plain HTML). The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.
Live preview
The code
<div class="tl9-stripwrap">
<div class="tl9-sprockets" aria-hidden="true">
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
</div>
<div class="tl9-frames" id="tl9-frames">
<div class="tl9-frame" data-n="F·001">
<div class="tl9-year">1927</div>
<h3 class="tl9-title">The Jazz Singer</h3>
<p class="tl9-desc">The first feature-length film with synchronized dialogue. Warner Bros gambled on a dying studio — and changed cinema forever.</p>
<div class="tl9-meta">
<span class="tl9-chip">Sound Era</span>
<span class="tl9-chip">Warner Bros</span>
</div>
</div>
<div class="tl9-frame" data-n="F·002">
<div class="tl9-year">1941</div>
<h3 class="tl9-title">Citizen Kane</h3>
<p class="tl9-desc">Welles' debut redefined visual storytelling. Deep focus, unconventional structure, and narrative fragmentation became a new grammar.</p>
<div class="tl9-meta">
<span class="tl9-chip">RKO</span>
<span class="tl9-chip">Welles</span>
</div>
</div>
<div class="tl9-frame" data-n="F·003">
<div class="tl9-year">1960</div>
<h3 class="tl9-title">La Dolce Vita</h3>
<p class="tl9-desc">Fellini's freewheeling portrait of Roman high society. Coined a word, launched a visual culture, and bewildered critics for decades.</p>
<div class="tl9-meta">
<span class="tl9-chip">Nouvelle Vague</span>
<span class="tl9-chip">Fellini</span>
</div>
</div>
<div class="tl9-frame" data-n="F·004">
<div class="tl9-year">1972</div>
<h3 class="tl9-title">The Godfather</h3>
<p class="tl9-desc">Coppola transforms pulp crime fiction into Shakespearean tragedy. The American New Wave at its most commercially ruthless.</p>
<div class="tl9-meta">
<span class="tl9-chip">New Hollywood</span>
<span class="tl9-chip">Paramount</span>
</div>
</div>
<div class="tl9-frame" data-n="F·005">
<div class="tl9-year">1994</div>
<h3 class="tl9-title">Pulp Fiction</h3>
<p class="tl9-desc">Tarantino's fractured chronology, pop-culture saturation, and explosive dialogue reset independent cinema's ambitions globally.</p>
<div class="tl9-meta">
<span class="tl9-chip">Indie</span>
<span class="tl9-chip">Tarantino</span>
</div>
</div>
<div class="tl9-frame" data-n="F·006">
<div class="tl9-year">2019</div>
<h3 class="tl9-title">Parasite</h3>
<p class="tl9-desc">Bong Joon-ho's genre-shifting class satire became the first non-English film to win the Academy Award for Best Picture.</p>
<div class="tl9-meta">
<span class="tl9-chip">CJ ENM</span>
<span class="tl9-chip">Palme d'Or</span>
</div>
</div>
</div>
<div class="tl9-sprockets" aria-hidden="true">
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
<div class="tl9-hole"></div><div class="tl9-hole"></div><div class="tl9-hole"></div>
</div>
<p class="tl9-hint">↔ DRAG TO SCROLL ↔</p>
</div> .tl9-stripwrap {
--tl9-bg: #13111a;
--tl9-a: #f0c040;
background: var(--tl9-bg);
padding: 2rem 0 1.5rem;
font-family: 'Inter', system-ui, sans-serif;
overflow: hidden;
}
.tl9-sprockets {
height: 36px;
display: flex;
align-items: center;
padding: 0 1.5rem;
border-top: 2px solid rgba(240,192,64,0.15);
border-bottom: 2px solid rgba(240,192,64,0.15);
gap: 2.5rem;
overflow: hidden;
}
.tl9-hole {
width: 12px;
height: 18px;
border-radius: 3px;
border: 1.5px solid rgba(240,192,64,0.28);
flex-shrink: 0;
}
.tl9-frames {
display: flex;
overflow-x: auto;
scrollbar-width: none;
cursor: grab;
border-top: 3px solid rgba(240,192,64,0.22);
border-bottom: 3px solid rgba(240,192,64,0.22);
}
.tl9-frames::-webkit-scrollbar { display: none; }
.tl9-frame {
flex-shrink: 0;
width: 240px;
border-right: 2px solid rgba(240,192,64,0.1);
padding: 1.75rem 1.5rem;
position: relative;
transition: background 0.25s;
}
.tl9-frame:hover {
background: rgba(240,192,64,0.04);
}
.tl9-frame::before {
content: attr(data-n);
position: absolute;
top: 0.6rem;
right: 0.85rem;
font-family: ui-monospace, monospace;
font-size: 10px;
color: rgba(240,192,64,0.25);
}
.tl9-year {
font-family: 'Inter', sans-serif;
font-size: 2.2rem;
font-weight: 800;
color: var(--tl9-a);
line-height: 1;
margin-bottom: 0.5rem;
text-shadow: 0 0 30px rgba(240,192,64,0.3);
}
.tl9-title {
font-family: Georgia, 'Times New Roman', serif;
font-size: 1.05rem;
color: #fff;
margin: 0 0 0.5rem;
line-height: 1.25;
}
.tl9-desc {
font-size: 12.5px;
color: rgba(255,255,255,0.45);
line-height: 1.6;
margin-bottom: 1rem;
}
.tl9-meta {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.tl9-chip {
font-family: ui-monospace, monospace;
font-size: 10px;
letter-spacing: 0.5px;
padding: 0.2rem 0.55rem;
border: 1px solid rgba(240,192,64,0.25);
border-radius: 3px;
color: rgba(240,192,64,0.7);
}
.tl9-hint {
margin: 1.5rem 0 0;
text-align: center;
font-family: ui-monospace, monospace;
font-size: 10px;
color: rgba(240,192,64,0.35);
letter-spacing: 2px;
} // Drag-to-scroll the horizontal filmstrip. Mouse handlers wire
// up grab/release; touch handlers do the same for mobile. Wrapped
// in an IIFE so the element handle, state vars, and listeners stay
// scoped. Runs once per page load since the gallery dedupes
// identical js strings before emitting script tags.
(function() {
const el = document.getElementById('tl9-frames');
if (!el) return;
let down = false, sx = 0, sl = 0;
el.addEventListener('mousedown', e => {
down = true; sx = e.pageX - el.offsetLeft; sl = el.scrollLeft;
el.style.cursor = 'grabbing'; el.style.userSelect = 'none';
});
document.addEventListener('mouseup', () => { down = false; el.style.cursor = 'grab'; });
el.addEventListener('mousemove', e => {
if (!down) return; e.preventDefault();
el.scrollLeft = sl - (e.pageX - el.offsetLeft - sx) * 1.3;
});
let tx = 0;
el.addEventListener('touchstart', e => { tx = e.touches[0].pageX; sl = el.scrollLeft; }, { passive: true });
el.addEventListener('touchmove', e => { el.scrollLeft = sl - (e.touches[0].pageX - tx); }, { passive: true });
})();