Part of the Webcore kit
HTML
<div class="tv-webcore-stamps">
<span class="tv-webcore-stamps-label">link me</span>
<div class="tv-webcore-stamps-window">
<div class="tv-webcore-stamps-track">
<ul class="tv-webcore-stamps-list">
<li><a class="tv-webcore-stamps-item" href="#"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--pink">luna ui ♡</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--navy">webcore</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--grey">best viewed 800×600</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--stripes">made with notepad</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--lilac">y2k forever</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--violet">sign my guestbook</span></a></li>
</ul>
<ul class="tv-webcore-stamps-list" aria-hidden="true">
<li><a class="tv-webcore-stamps-item" href="#" tabindex="-1"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--pink">luna ui ♡</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#" tabindex="-1"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--navy">webcore</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#" tabindex="-1"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--grey">best viewed 800×600</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#" tabindex="-1"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--stripes">made with notepad</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#" tabindex="-1"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--lilac">y2k forever</span></a></li>
<li><a class="tv-webcore-stamps-item" href="#" tabindex="-1"><span class="tv-webcore-stamps-badge tv-webcore-stamps-badge--violet">sign my guestbook</span></a></li>
</ul>
</div>
</div>
</div>
CSS
/* A marquee of 88×31 buttons or stamps: two copies of the row slide left in a loop and pause on hover. */
.tv-webcore-stamps {
--tv-webcore-stamps-face: var(--tv-webcore-pink, #f7b5e4);
display: flex;
align-items: stretch;
box-sizing: border-box;
width: 100%;
border: 1px solid var(--tv-webcore-navy, #2c2b9f);
background: var(--tv-webcore-stamps-face, #f7b5e4);
color: var(--tv-webcore-navy, #2c2b9f);
font: 14px/1.2 "Lucida Console", "Courier New", ui-monospace, monospace;
box-shadow: 3px 3px 0 color-mix(in srgb, var(--tv-webcore-navy, #2c2b9f) 25%, transparent);
}
.tv-webcore-stamps-label {
display: inline-flex;
flex-shrink: 0;
align-items: center;
padding: 0 10px;
border-right: 1px solid var(--tv-webcore-navy, #2c2b9f);
background: var(--tv-webcore-navy, #2c2b9f);
color: var(--tv-webcore-paper, #ffffff);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.tv-webcore-stamps-window {
flex: 1;
min-width: 0;
margin: 3px;
overflow: hidden;
border: 2px dotted color-mix(in srgb, var(--tv-webcore-navy, #2c2b9f) 45%, transparent);
}
.tv-webcore-stamps-track {
display: flex;
width: max-content;
animation-name: tv-webcore-stamps-scroll;
animation-duration: var(--tv-webcore-stamps-duration, 24s);
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.tv-webcore-stamps-list {
display: flex;
align-items: center;
gap: 8px;
margin: 0;
padding: 6px 8px 6px 0;
list-style: none;
}
.tv-webcore-stamps-list:first-child {
padding-left: 8px;
}
.tv-webcore-stamps-item {
display: block;
line-height: 0;
}
/* Your own buttons and stamps: shown at their pixel size, scaled without blurring. */
.tv-webcore-stamps-item img {
display: block;
width: auto;
height: 31px;
image-rendering: pixelated;
}
.tv-webcore-stamps-item:focus-visible {
outline: 2px dashed var(--tv-webcore-navy, #2c2b9f);
outline-offset: 2px;
}
.tv-webcore-stamps:hover .tv-webcore-stamps-track,
.tv-webcore-stamps:focus-within .tv-webcore-stamps-track {
animation-play-state: paused;
}
@keyframes tv-webcore-stamps-scroll {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
/* Placeholder buttons, drawn in CSS so the preview needs no image files. */
.tv-webcore-stamps-badge {
display: grid;
place-items: center;
box-sizing: border-box;
width: 88px;
height: 31px;
padding: 0 4px;
border: 1px solid var(--tv-webcore-navy, #2c2b9f);
font-size: 9px;
font-weight: 700;
line-height: 1.05;
letter-spacing: 0.06em;
text-align: center;
text-transform: uppercase;
}
.tv-webcore-stamps-badge--pink {
background: linear-gradient(90deg, var(--tv-webcore-pink, #f7b5e4), var(--tv-webcore-lilac, #a49bf3));
color: var(--tv-webcore-navy, #2c2b9f);
}
.tv-webcore-stamps-badge--navy {
background: var(--tv-webcore-navy, #2c2b9f);
color: var(--tv-webcore-pink, #f7b5e4);
}
.tv-webcore-stamps-badge--grey {
background: var(--tv-webcore-grey, #d9d9e5);
color: var(--tv-webcore-navy, #2c2b9f);
}
.tv-webcore-stamps-badge--stripes {
background: repeating-linear-gradient(45deg, var(--tv-webcore-paper, #ffffff) 0 4px, color-mix(in srgb, var(--tv-webcore-lilac, #a49bf3) 40%, var(--tv-webcore-paper, #ffffff)) 4px 8px);
color: var(--tv-webcore-navy, #2c2b9f);
}
.tv-webcore-stamps-badge--lilac {
background: var(--tv-webcore-lilac, #a49bf3);
color: var(--tv-webcore-paper, #ffffff);
}
.tv-webcore-stamps-badge--violet {
background: var(--tv-webcore-violet, #a445dd);
color: var(--tv-webcore-paper, #ffffff);
}
/* Stamps: bigger tiles with a perforated paper edge. */
.tv-webcore-stamps--stamps .tv-webcore-stamps-item img {
height: 56px;
}
.tv-webcore-stamps--stamps .tv-webcore-stamps-badge {
width: 99px;
height: 56px;
border: 3px dotted var(--tv-webcore-paper, #ffffff);
box-shadow: 0 0 0 1px var(--tv-webcore-navy, #2c2b9f);
font-size: 11px;
}
.tv-webcore-stamps--stamps .tv-webcore-stamps-list {
gap: 10px;
padding-top: 8px;
padding-bottom: 8px;
}
/* Still: the first row wraps into a grid of buttons, and the loop copy is hidden. */
@media (prefers-reduced-motion: reduce) {
.tv-webcore-stamps-track {
width: auto;
animation: none;
}
.tv-webcore-stamps-list {
flex-wrap: wrap;
}
.tv-webcore-stamps-list[aria-hidden="true"] {
display: none;
}
}
Usage & credits
- Use when
- Site buttons, link-me buttons, fan stamps and webring badges in a homepage footer or sidebar.
- Avoid when
- Links people need to find quickly; put essential navigation somewhere that stands still.
- Requires
- Replace each placeholder with your own image, for example <img src="mybutton.gif" width="88" height="31" alt="My site">. · Keep the second copy aria-hidden="true" with tabindex="-1" on its links; it only makes the loop seamless. · Set --tv-webcore-stamps-duration to change the speed (default 24s).
- From
- Luna UI