SPB Git

spb/svgarden Public

SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)

HTML 79.2% Astro 10.3% JavaScript 6% CSS 3.7% Shell 0.8%
3.5 KB · 93 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/buttons/btn-split-reveal.html7  Desc   : Label splits into two clipped halves revealing a second label8  ============================================================9-->10<!--svgarden11title: Split-reveal button12slug: btn-split-reveal13category: buttons14tags: [button, clip-path, split, hover]15difficulty: intermediate16techniques: ["clip-path: inset()", layered-duplicates, transition, transform]17how_it_works: >18  The visible label is actually two identical copies stacked on top of each19  other: one clipped to its top half with clip-path: inset(0 0 50% 0), the20  other to its bottom half with inset(50% 0 0 0). On hover the halves translate21  in opposite vertical directions, so the word appears to tear apart along an22  invisible seam, while a third label scales up through the gap. Clipping is23  the load-bearing trick — both copies keep their full layout size, so nothing24  reflows during the animation and the split line always stays razor-straight.25customizable:26  - { var: "--sg-color",    label: "Accent",    type: color, default: "#7F77DD" }27  - { var: "--sg-size",     label: "Font size", type: range, min: 12, max: 26, default: 16, unit: px }28  - { var: "--sg-duration", label: "Speed",     type: range, min: 0.15, max: 1.2, step: 0.05, default: 0.4, unit: s }29created: 2026-08-1030-->31<button class="sg-btn-split-reveal" type="button" style="--sg-color:#7F77DD; --sg-size:16px; --sg-duration:0.4s;">32  <span class="sg-btn-split-reveal-base" aria-hidden="true">Hover me</span>33  <span class="sg-btn-split-reveal-half sg-btn-split-reveal-top" aria-hidden="true">Hover me</span>34  <span class="sg-btn-split-reveal-half sg-btn-split-reveal-bot" aria-hidden="true">Hover me</span>35  <span class="sg-btn-split-reveal-alt">Let's go →</span>36</button>37<style>38  .sg-btn-split-reveal {39    position: relative;40    appearance: none;41    font: inherit;42    font-size: var(--sg-size);43    font-weight: 600;44    color: inherit;45    background: transparent;46    border: 1.5px solid rgba(128, 128, 128, 0.45);47    border-radius: 10px;48    padding: 0.8em 1.9em;49    cursor: pointer;50    overflow: hidden;51    transition: border-color var(--sg-duration) ease;52  }53  .sg-btn-split-reveal-base {54    visibility: hidden;55  }56  .sg-btn-split-reveal-half {57    position: absolute;58    inset: 0;59    display: grid;60    place-items: center;61    transition: transform var(--sg-duration) cubic-bezier(0.5, 0, 0.2, 1);62  }63  .sg-btn-split-reveal-top { clip-path: inset(0 0 50% 0); }64  .sg-btn-split-reveal-bot { clip-path: inset(50% 0 0 0); }65  .sg-btn-split-reveal-alt {66    position: absolute;67    inset: 0;68    display: grid;69    place-items: center;70    color: var(--sg-color);71    transform: scale(0.6);72    opacity: 0;73    transition: transform var(--sg-duration) cubic-bezier(0.3, 1.5, 0.5, 1), opacity var(--sg-duration) ease;74  }75  .sg-btn-split-reveal:hover,76  .sg-btn-split-reveal:focus-visible {77    border-color: var(--sg-color);78  }79  .sg-btn-split-reveal:hover .sg-btn-split-reveal-top,80  .sg-btn-split-reveal:focus-visible .sg-btn-split-reveal-top {81    transform: translateY(-115%);82  }83  .sg-btn-split-reveal:hover .sg-btn-split-reveal-bot,84  .sg-btn-split-reveal:focus-visible .sg-btn-split-reveal-bot {85    transform: translateY(115%);86  }87  .sg-btn-split-reveal:hover .sg-btn-split-reveal-alt,88  .sg-btn-split-reveal:focus-visible .sg-btn-split-reveal-alt {89    transform: scale(1);90    opacity: 1;91  }92</style>93