Skip to content
Luna UI
Luna UI
button cool animation webcore y2k
HTML
<div class="tv-webcore-stamps tv-webcore-stamps--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;
  }
}
Markdown MIT License
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).