{"id":806,"date":"2026-08-19T04:27:20","date_gmt":"2026-08-19T04:27:20","guid":{"rendered":"https:\/\/www.cssportal.com\/blog\/?p=806"},"modified":"2026-08-19T04:27:20","modified_gmt":"2026-08-19T04:27:20","slug":"animation-effects-when-copying-to-clipboard","status":"publish","type":"post","link":"https:\/\/www.cssportal.com\/blog\/animation-effects-when-copying-to-clipboard\/","title":{"rendered":"Animation Effects When Copying to Clipboard"},"content":{"rendered":"<style>\r\n  :root {\r\n    --css-blue: #2563eb;\r\n    --css-blue-light: #dbeafe;\r\n    --css-blue-mid: #93c5fd;\r\n    --css-blue-dark: #1d4ed8;\r\n    --css-blue-pale: #eff6ff;\r\n    --css-ink: #0f172a;\r\n    --css-ink-muted: #475569;\r\n    --css-border: #e2e8f0;\r\n    --css-white: #ffffff;\r\n    --css-radius: 12px;\r\n    --css-mono: 'DM Mono', monospace;\r\n  }\r\n  \/* \u2500\u2500 Prose \u2500\u2500 *\/\r\n  .prose { margin-bottom: 48px; }\r\n  .prose p { color: var(--css-ink-muted); margin-bottom: 16px; }\r\n  .prose p:last-child { margin-bottom: 0; }\r\n  .prose strong { color: var(--css-ink); font-weight: 600; }\r\n  \/* \u2500\u2500 Section heading \u2500\u2500 *\/\r\n  .section-label {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 12px;\r\n    margin-bottom: 12px;\r\n  }\r\n  .section-num {\r\n    font-family: var(--css-mono);\r\n    font-size: 11px;\r\n    color: var(--css-blue);\r\n    letter-spacing: 0.1em;\r\n    background: var(--css-blue-light);\r\n    padding: 3px 9px;\r\n    border-radius: 100px;\r\n    margin-top: 10px;\r\n  }\r\n  \/* \u2500\u2500 Effect description \u2500\u2500 *\/\r\n  .effect-desc {\r\n    font-size: 15px;\r\n    color: var(--css-ink-muted);\r\n    margin-bottom: 20px;\r\n    line-height: 1.65;\r\n  }\r\n  .effect-desc strong { color: var(--css-ink); font-weight: 600; }\r\n  \/* \u2500\u2500 Demo card \u2500\u2500 *\/\r\n  .demo-card {\r\n    border: 1.5px solid var(--css-border);\r\n    border-radius: var(--css-radius);\r\n    overflow: hidden;\r\n    margin-bottom: 16px;\r\n  }\r\n  .demo-card-header {\r\n    background: var(--css-blue-pale);\r\n    padding: 14px 20px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    border-bottom: 1.5px solid var(--css-blue-light);\r\n  }\r\n  .demo-card-title {\r\n    font-family: var(--css-mono);\r\n    font-size: 12px;\r\n    font-weight: 500;\r\n    color: var(--css-blue-dark);\r\n    letter-spacing: 0.05em;\r\n    text-transform: uppercase;\r\n  }\r\n  .demo-badge {\r\n    font-family: var(--css-mono);\r\n    font-size: 10px;\r\n    color: var(--css-ink-muted);\r\n    background: var(--css-white);\r\n    border: 1px solid var(--css-border);\r\n    padding: 2px 8px;\r\n    border-radius: 100px;\r\n  }\r\n  .demo-area {\r\n    padding: 32px 28px;\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 20px;\r\n  }\r\n  \/* \u2500\u2500 Snippet rows \u2500\u2500 *\/\r\n  .snippet-row {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 12px;\r\n    flex-wrap: wrap;\r\n  }\r\n  .snippet-box {\r\n    flex: 1;\r\n    min-width: 0;\r\n    background: var(--css-white);\r\n    border: 1.5px solid var(--css-border);\r\n    border-radius: 8px;\r\n    padding: 12px 16px;\r\n    font-family: var(--css-mono);\r\n    font-size: 13.5px;\r\n    color: var(--css-ink);\r\n    cursor: text;\r\n    user-select: all;\r\n    white-space: nowrap;\r\n    overflow: hidden;\r\n    text-overflow: ellipsis;\r\n    position: relative;\r\n  }\r\n  \/* \u2500\u2500 Wrapper divs for positioning \u2500\u2500 *\/\r\n  .toast-anchor,\r\n  .confetti-anchor,\r\n  .trace-wrap {\r\n    flex-shrink: 0;\r\n    display: inline-flex;\r\n    width: fit-content;\r\n  }\r\n  \/* \u2500\u2500 Copy buttons \u2500\u2500 *\/\r\n  .copy-btn {\r\n    flex-shrink: 0;\r\n    width: fit-content;\r\n    align-self: center;\r\n    background: var(--css-blue);\r\n    color: #fff;\r\n    border: none;\r\n    border-radius: 8px;\r\n    padding: 10px 18px;\r\n    font-family: 'Instrument Sans', sans-serif;\r\n    font-size: 13.5px;\r\n    font-weight: 600;\r\n    cursor: pointer;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 7px;\r\n    transition: background 0.18s, transform 0.12s;\r\n    position: relative;\r\n    overflow: hidden;\r\n  }\r\n  .copy-btn:hover { background: var(--css-blue-dark); }\r\n  .copy-btn svg { width: 15px; height: 15px; flex-shrink: 0; }\r\n  \/* \u2500\u2500 Divider \u2500\u2500 *\/\r\n  .divider {\r\n    border: none;\r\n    border-top: 1.5px solid var(--css-border);\r\n    margin: 48px 0;\r\n  }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 1: Ripple\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  @keyframes ripple-out {\r\n    0%   { transform: scale(0); opacity: 0.5; }\r\n    100% { transform: scale(3.5); opacity: 0; }\r\n  }\r\n  .ripple-effect {\r\n    position: absolute;\r\n    border-radius: 50%;\r\n    background: rgba(255,255,255,0.55);\r\n    pointer-events: none;\r\n    animation: ripple-out 0.6s ease-out forwards;\r\n    transform-origin: center;\r\n  }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 2: Checkmark Swap\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  .btn-check-swap .label-copy,\r\n  .btn-check-swap .label-done { transition: all 0.2s; }\r\n  .btn-check-swap.copied1 .label-copy { display: none; }\r\n  .btn-check-swap .label-done { display: none; }\r\n  .btn-check-swap.copied1 .label-done { display: flex; align-items: center; gap: 6px; }\r\n  .btn-check-swap.copied1 { background: #16a34a !important; }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 3: Floating Toast\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  .toast-anchor { position: relative; }\r\n  @keyframes toast-rise {\r\n    0%   { opacity: 0; transform: translateY(0) translateX(-50%) scale(0.85); }\r\n    15%  { opacity: 1; transform: translateY(-12px) translateX(-50%) scale(1); }\r\n    75%  { opacity: 1; transform: translateY(-14px) translateX(-50%) scale(1); }\r\n    100% { opacity: 0; transform: translateY(-28px) translateX(-50%) scale(0.9); }\r\n  }\r\n  .toast-pop {\r\n    position: absolute;\r\n    bottom: calc(100% + 8px);\r\n    left: 50%;\r\n    transform: translateX(-50%);\r\n    background: var(--css-ink);\r\n    color: #fff;\r\n    font-family: var(--css-mono);\r\n    font-size: 11.5px;\r\n    padding: 5px 12px;\r\n    border-radius: 6px;\r\n    white-space: nowrap;\r\n    pointer-events: none;\r\n    animation: toast-rise 1.6s ease forwards;\r\n  }\r\n  .toast-pop::after {\r\n    content: '';\r\n    position: absolute;\r\n    top: 100%;\r\n    left: 50%;\r\n    transform: translateX(-50%);\r\n    border: 5px solid transparent;\r\n    border-top-color: var(--css-ink);\r\n  }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 4: Particle Burst\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  .particle-btn { overflow: visible; }\r\n  @keyframes particle-fly {\r\n    0%   { opacity: 1; transform: translate(0,0) scale(1); }\r\n    100% { opacity: 0; transform: translate(var(--css-tx), var(--css-ty)) scale(0); }\r\n  }\r\n  .particle {\r\n    position: absolute;\r\n    border-radius: 50%;\r\n    background: var(--css-blue-mid);\r\n    pointer-events: none;\r\n    animation: particle-fly 0.65s ease-out forwards;\r\n    width: 6px; height: 6px;\r\n  }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 5: Scanner Sweep\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  .scanner-box { position: relative; overflow: hidden; }\r\n  @keyframes scan-sweep {\r\n    0%   { left: -4px; opacity: 0; }\r\n    5%   { opacity: 1; }\r\n    95%  { opacity: 1; }\r\n    100% { left: calc(100% + 4px); opacity: 0; }\r\n  }\r\n  .scan-line {\r\n    position: absolute;\r\n    top: 0; bottom: 0;\r\n    width: 3px;\r\n    background: linear-gradient(to bottom, transparent, var(--css-blue), transparent);\r\n    pointer-events: none;\r\n    animation: scan-sweep 0.7s ease-in-out forwards;\r\n    box-shadow: 0 0 10px var(--css-blue), 0 0 20px var(--css-blue-mid);\r\n  }\r\n  @keyframes scan-flash {\r\n    0%, 100% { background: var(--css-white); }\r\n    40% { background: var(--css-blue-pale); }\r\n  }\r\n  .scanner-box.scanning { animation: scan-flash 0.7s ease; }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 6: Slide-Up Label\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  .slide-btn { overflow: hidden; }\r\n  .slide-btn .slide-default,\r\n  .slide-btn .slide-done {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 6px;\r\n    transition: transform 0.3s cubic-bezier(.34,1.56,.64,1), opacity 0.25s;\r\n  }\r\n  .slide-btn .slide-done {\r\n    position: absolute;\r\n    inset: 0;\r\n    justify-content: center;\r\n    transform: translateY(100%);\r\n    opacity: 0;\r\n  }\r\n  .slide-btn.slid .slide-default { transform: translateY(-110%); opacity: 0; }\r\n  .slide-btn.slid .slide-done { transform: translateY(0); opacity: 1; }\r\n  .slide-btn.slid { background: var(--css-blue-dark) !important; }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 7: Border Trace\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  @property --css-p {\r\n    syntax: '<percentage>';\r\n    inherits: false;\r\n    initial-value: 0%;\r\n  }\r\n  .trace-wrap {\r\n    position: relative;\r\n    border-radius: 10px;\r\n    padding: 3px;\r\n    background: var(--css-border);\r\n  }\r\n  .trace-wrap::before {\r\n    content: '';\r\n    position: absolute;\r\n    inset: 0;\r\n    border-radius: inherit;\r\n    background: conic-gradient(var(--css-blue) var(--css-p, 0%), transparent 0%);\r\n    transition: none;\r\n    pointer-events: none;\r\n    z-index: 0;\r\n    opacity: 0;\r\n  }\r\n  .trace-wrap.tracing::before {\r\n    opacity: 1;\r\n    animation: trace-go 0.85s linear forwards;\r\n  }\r\n  @keyframes trace-go {\r\n    from { --css-p: 0%; }\r\n    to   { --css-p: 100%; }\r\n  }\r\n  .trace-wrap .trace-inner {\r\n    position: relative;\r\n    z-index: 1;\r\n    border-radius: 7px;\r\n    background: var(--css-blue);\r\n    color: white;\r\n    border: none;\r\n    padding: 10px 18px;\r\n    font-family: 'Instrument Sans', sans-serif;\r\n    font-size: 13.5px;\r\n    font-weight: 600;\r\n    cursor: pointer;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 7px;\r\n    transition: background 0.2s;\r\n    width: fit-content;\r\n  }\r\n  .trace-wrap .trace-inner:hover { background: var(--css-blue-dark); }\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANIMATION 8: Confetti Shower\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  .confetti-anchor { position: relative; }\r\n  @keyframes confetti-fall {\r\n    0%   { opacity: 1; transform: translate(var(--css-cx), -4px) rotate(var(--css-cr)) scale(1); }\r\n    100% { opacity: 0; transform: translate(var(--css-cx), var(--css-cy)) rotate(calc(var(--css-cr) + 360deg)) scale(0.3); }\r\n  }\r\n  .confetto {\r\n    position: absolute;\r\n    pointer-events: none;\r\n    width: 7px;\r\n    height: 7px;\r\n    border-radius: 2px;\r\n    animation: confetti-fall 0.9s ease-in forwards;\r\n    top: 0;\r\n    left: 50%;\r\n    z-index: 10;\r\n  }\r\n  \/* \u2500\u2500 Intro note box \u2500\u2500 *\/\r\n  .note-box {\r\n    background: var(--css-blue-pale);\r\n    border-left: 4px solid var(--css-blue);\r\n    border-radius: 0 8px 8px 0;\r\n    padding: 16px 20px;\r\n    margin-bottom: 16px;\r\n    font-size: 15.5px;\r\n    color: var(--css-ink-muted);\r\n  }\r\n  .note-box strong { color: var(--css-blue-dark); }\r\n  \/* \u2500\u2500 Tabbed code blocks \u2500\u2500 *\/\r\n  .code-tabs {\r\n    border: 1.5px solid var(--css-border);\r\n    border-radius: var(--css-radius);\r\n    overflow: hidden;\r\n    margin-bottom: 56px;\r\n    background: #f8fafc;\r\n  }\r\n  .code-tab-bar {\r\n    background: var(--css-blue-pale);\r\n    border-bottom: 1.5px solid var(--css-blue-light);\r\n    padding: 0 14px;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 0;\r\n  }\r\n  .code-tab-dots {\r\n    display: flex;\r\n    gap: 6px;\r\n    margin-right: 10px;\r\n    padding: 10px 0;\r\n    flex-shrink: 0;\r\n  }\r\n  .cb-dot { width: 11px; height: 11px; border-radius: 50%; }\r\n  .cb-dot:nth-child(1) { background: #fca5a5; }\r\n  .cb-dot:nth-child(2) { background: #fcd34d; }\r\n  .cb-dot:nth-child(3) { background: #6ee7b7; }\r\n  .tab-btn {\r\n    background: none;\r\n    border: none;\r\n    border-bottom: 2.5px solid transparent;\r\n    padding: 10px 14px;\r\n    font-family: var(--css-mono);\r\n    font-size: 11.5px;\r\n    font-weight: 500;\r\n    color: var(--css-ink-muted);\r\n    cursor: pointer;\r\n    letter-spacing: 0.04em;\r\n    transition: color 0.15s, border-color 0.15s;\r\n    flex-shrink: 0;\r\n  }\r\n  .tab-btn:hover { color: var(--css-blue); }\r\n  .tab-btn.active { color: var(--css-blue-dark); border-bottom-color: var(--css-blue); }\r\n  .tab-panel { display: none; }\r\n  .tab-panel.active { display: block; }\r\n  .tab-panel pre {\r\n    padding: 22px 22px;\r\n    font-family: var(--css-mono);\r\n    font-size: 13px;\r\n    line-height: 1.85;\r\n    overflow-x: auto;\r\n    color: #334155;\r\n    margin: 0;\r\n    white-space: pre-wrap !important;\r\n    border: none !important;\r\n  }\r\n  .tab-panel pre .kw  { color: #2563eb; font-weight: 500; }\r\n  .tab-panel pre .fn  { color: #7c3aed; }\r\n  .tab-panel pre .str { color: #059669; }\r\n  .tab-panel pre .cm  { color: #94a3b8; font-style: italic; }\r\n  .tab-panel pre .num { color: #d97706; }\r\n  .tab-panel pre .sel { color: #0891b2; }\r\n  .tab-panel pre .val { color: #be185d; }\r\n  \/* \u2500\u2500 Copy-code button \u2500\u2500 *\/\r\n  .copy-code-btn {\r\n    margin-left: auto;\r\n    background: none;\r\n    border: 1px solid var(--css-blue-light);\r\n    border-radius: 6px;\r\n    padding: 5px 12px;\r\n    font-family: var(--css-mono);\r\n    font-size: 11px;\r\n    color: var(--css-blue-dark);\r\n    cursor: pointer;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 5px;\r\n    transition: background 0.15s, color 0.15s, border-color 0.15s;\r\n    white-space: nowrap;\r\n    flex-shrink: 0;\r\n  }\r\n  .copy-code-btn:hover { background: var(--css-blue-light); border-color: var(--css-blue-mid); }\r\n  .copy-code-btn.code-copied { background: #dcfce7; border-color: #86efac; color: #15803d; }\r\n  .copy-code-btn svg { width: 12px; height: 12px; flex-shrink: 0; }\r\n  \/* \u2500\u2500 Responsive \u2500\u2500 *\/\r\n  @media (max-width: 540px) {\r\n    .snippet-row { flex-direction: column; align-items: stretch; }\r\n    .copy-btn { justify-content: center; }\r\n    .toast-anchor, .confetti-anchor, .trace-wrap { width: 100%; }\r\n    .toast-anchor .copy-btn,\r\n    .confetti-anchor .copy-btn,\r\n    .trace-wrap .trace-inner { width: 100%; justify-content: center; }\r\n  }\r\n<\/style>\r\n<main>\r\n \r\n  <!-- \u2500\u2500 Intro \u2500\u2500 -->\r\n  <div class=\"prose\">\r\n    <p>Copy-to-clipboard is one of those interactions that <strong>deserves a little ceremony<\/strong>. The user performed an action \u2014 let them feel it. In a previous post we explored animation effects using clipboard.js. Today we&#8217;re stripping that dependency out entirely and doing everything with <code>navigator.clipboard.writeText()<\/code>, CSS animations, and a dash of vanilla JS.<\/p>\r\n    <p>Each demo below is completely self-contained. The Clipboard API is promise-based, so we hook our animations to the <code>.then()<\/code> callback \u2014 meaning they only fire when the copy actually succeeds. Click any button to see it in action, then grab the CSS and JS code using the copy buttons on each snippet.<\/p>\r\n    <div class=\"note-box\"><strong>Browser note:<\/strong> <code>navigator.clipboard<\/code> requires a secure context (HTTPS or localhost) and is supported in all modern browsers. No polyfill needed for most production uses.<\/div>\r\n  <\/div>\r\n \r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 1 \u2014 Ripple Burst\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">01<\/span>\r\n    <h2>Ripple Burst<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">The classic Material Design interaction, applied to copy. On click, a translucent circle expands outward from the button&#8217;s centre and fades \u2014 giving instant tactile feedback. It&#8217;s <strong>universally familiar<\/strong> and works on any coloured button since the ripple is semi-transparent white. Requires <code>overflow: hidden<\/code> on the button to clip the circle as it grows beyond the button bounds.<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box\">npm install @scope\/my-package<\/div>\r\n        <button class=\"copy-btn\" id=\"btn-ripple\" onclick=\"copyRipple(this, 'npm install @scope\/my-package')\">\r\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>Copy\r\n        <\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'ripple','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'ripple','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'ripple','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'ripple')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"ripple-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- Button needs position:relative + overflow:hidden --&gt;<\/span>\r\n&lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"copy-btn\"<\/span>\r\n        <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copyRipple(this, 'your text here')\"<\/span>&gt;\r\n  &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n       <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n    &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n  &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n  Copy\r\n&lt;\/<span class=\"sel\">button<\/span>&gt;\r\n \r\n<span class=\"cm\">&lt;!-- The .ripple-effect span is created and injected by JS --&gt;<\/span><\/pre><\/div>\r\n    <div id=\"ripple-css\" class=\"tab-panel\"><pre><span class=\"cm\">\/* Button must be position:relative + overflow:hidden *\/<\/span>\r\n<span class=\"sel\">.copy-btn<\/span> { <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>; <span class=\"kw\">overflow<\/span>: <span class=\"val\">hidden<\/span>; }\r\n \r\n<span class=\"sel\">.ripple-effect<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">border-radius<\/span>: <span class=\"val\">50%<\/span>;\r\n  <span class=\"kw\">background<\/span>: <span class=\"val\">rgba(255,255,255,0.55)<\/span>;\r\n  <span class=\"kw\">pointer-events<\/span>: <span class=\"val\">none<\/span>;\r\n  <span class=\"kw\">transform-origin<\/span>: <span class=\"val\">center<\/span>;\r\n  <span class=\"kw\">animation<\/span>: <span class=\"val\">ripple-out 0.6s ease-out forwards<\/span>;\r\n}\r\n \r\n<span class=\"kw\">@keyframes<\/span> ripple-out {\r\n  <span class=\"val\">0%<\/span>   { <span class=\"kw\">transform<\/span>: <span class=\"val\">scale(0)<\/span>;   <span class=\"kw\">opacity<\/span>: <span class=\"val\">0.5<\/span>; }\r\n  <span class=\"val\">100%<\/span> { <span class=\"kw\">transform<\/span>: <span class=\"val\">scale(3.5)<\/span>; <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>; }\r\n}<\/pre><\/div>\r\n    <div id=\"ripple-js\" class=\"tab-panel\"><pre><span class=\"kw\">function<\/span> <span class=\"fn\">copyRipple<\/span>(btn, text) {\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">catch<\/span>(() => {});\r\n  <span class=\"kw\">const<\/span> ripple = document.<span class=\"fn\">createElement<\/span>(<span class=\"str\">'span'<\/span>);\r\n  <span class=\"kw\">const<\/span> size = Math.<span class=\"fn\">max<\/span>(btn.offsetWidth, btn.offsetHeight);\r\n  ripple.className = <span class=\"str\">'ripple-effect'<\/span>;\r\n  ripple.style.cssText = <span class=\"str\">`width:${size}px; height:${size}px;\r\n    position:absolute; top:50%; left:50%;\r\n    margin:-${size\/2}px 0 0 -${size\/2}px`<\/span>;\r\n  btn.<span class=\"fn\">appendChild<\/span>(ripple);\r\n  ripple.<span class=\"fn\">addEventListener<\/span>(<span class=\"str\">'animationend'<\/span>, () => ripple.<span class=\"fn\">remove<\/span>());\r\n}<\/pre><\/div>\r\n  <\/div>\r\n \r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 2 \u2014 Checkmark Swap\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">02<\/span>\r\n    <h2>Checkmark Swap<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">The most universally understood copy confirmation \u2014 the button turns green and swaps its label for a checkmark. It&#8217;s <strong>honest and clear<\/strong>, with a debounce guard that prevents double-firing. The key is keeping two separate label spans inside the button and toggling their visibility with a class; no JS string manipulation needed after the initial click.<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box\">git clone https:\/\/github.com\/user\/repo.git<\/div>\r\n        <button class=\"copy-btn btn-check-swap\" id=\"btn-check\" onclick=\"copyCheck(this, 'git clone https:\/\/github.com\/user\/repo.git')\">\r\n          <span class=\"label-copy\">\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" width=\"15\" height=\"15\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n            Copy\r\n          <\/span>\r\n          <span class=\"label-done\">\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" width=\"15\" height=\"15\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg>\r\n            Copied!\r\n          <\/span>\r\n        <\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'check','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'check','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'check','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'check')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"check-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- Two spans inside the button \u2014 one for each state --&gt;<\/span>\r\n&lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"copy-btn btn-check-swap\"<\/span>\r\n        <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copyCheck(this, 'your text here')\"<\/span>&gt;\r\n \r\n  &lt;<span class=\"sel\">span<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"label-copy\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n         <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n      &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n      &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n    &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n    Copy\r\n  &lt;\/<span class=\"sel\">span<\/span>&gt;\r\n \r\n  &lt;<span class=\"sel\">span<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"label-done\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n         <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2.5\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n      &lt;<span class=\"sel\">polyline<\/span> <span class=\"kw\">points<\/span>=<span class=\"str\">\"20 6 9 17 4 12\"<\/span>\/&gt;\r\n    &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n    Copied!\r\n  &lt;\/<span class=\"sel\">span<\/span>&gt;\r\n \r\n&lt;\/<span class=\"sel\">button<\/span>&gt;<\/pre><\/div>\r\n    <div id=\"check-css\" class=\"tab-panel\"><pre><span class=\"sel\">.btn-check-swap .label-copy<\/span>,\r\n<span class=\"sel\">.btn-check-swap .label-done<\/span> { <span class=\"kw\">transition<\/span>: <span class=\"val\">all 0.2s<\/span>; }\r\n \r\n<span class=\"sel\">.btn-check-swap .label-done<\/span>        { <span class=\"kw\">display<\/span>: <span class=\"val\">none<\/span>; }\r\n<span class=\"sel\">.btn-check-swap.copied .label-copy<\/span> { <span class=\"kw\">display<\/span>: <span class=\"val\">none<\/span>; }\r\n<span class=\"sel\">.btn-check-swap.copied .label-done<\/span> {\r\n  <span class=\"kw\">display<\/span>: <span class=\"val\">flex<\/span>;\r\n  <span class=\"kw\">align-items<\/span>: <span class=\"val\">center<\/span>;\r\n  <span class=\"kw\">gap<\/span>: <span class=\"val\">6px<\/span>;\r\n}\r\n<span class=\"sel\">.btn-check-swap.copied<\/span> { <span class=\"kw\">background<\/span>: <span class=\"val\">#16a34a<\/span> !important; }<\/pre><\/div>\r\n    <div id=\"check-js\" class=\"tab-panel\"><pre><span class=\"kw\">function<\/span> <span class=\"fn\">copyCheck<\/span>(btn, text) {\r\n  <span class=\"kw\">if<\/span> (btn.classList.<span class=\"fn\">contains<\/span>(<span class=\"str\">'copied'<\/span>)) <span class=\"kw\">return<\/span>;\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">catch<\/span>(() => {});\r\n  btn.classList.<span class=\"fn\">add<\/span>(<span class=\"str\">'copied'<\/span>);\r\n  <span class=\"fn\">setTimeout<\/span>(() => btn.classList.<span class=\"fn\">remove<\/span>(<span class=\"str\">'copied'<\/span>), <span class=\"num\">2000<\/span>);\r\n}<\/pre><\/div>\r\n  <\/div>\r\n \r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 3 \u2014 Floating Toast\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">03<\/span>\r\n    <h2>Floating Toast<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">A small tooltip-style bubble rises from the button, lingers briefly, then fades away. It&#8217;s great for <strong>sensitive or truncated content<\/strong> like API keys where the text itself isn&#8217;t visible \u2014 the toast reassures the user that something was captured. The element is created and destroyed entirely in JS, so there&#8217;s nothing persistent in the DOM between interactions.<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box\">sk-ant-api03-\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022<\/div>\r\n        <div class=\"toast-anchor\">\r\n          <button class=\"copy-btn\" onclick=\"copyToast(this, 'sk-ant-api03-XXXXXXXXXXXX')\">\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" width=\"15\" height=\"15\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n            Copy\r\n          <\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'toast','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'toast','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'toast','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'toast')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"toast-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- Wrap the button in a relative-positioned container --&gt;<\/span>\r\n&lt;<span class=\"sel\">div<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"toast-anchor\"<\/span>&gt;\r\n  &lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"copy-btn\"<\/span>\r\n          <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copyToast(this, 'your text here')\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n         <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n      &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n      &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n    &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n    Copy\r\n  &lt;\/<span class=\"sel\">button<\/span>&gt;\r\n  <span class=\"cm\">&lt;!-- .toast-pop div is created and injected by JS --&gt;<\/span>\r\n&lt;\/<span class=\"sel\">div<\/span>&gt;<\/pre><\/div>\r\n    <div id=\"toast-css\" class=\"tab-panel\"><pre><span class=\"cm\">\/* Wrap your button in a position:relative container *\/<\/span>\r\n<span class=\"sel\">.toast-anchor<\/span> { <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>; <span class=\"kw\">display<\/span>: <span class=\"val\">inline-flex<\/span>; }\r\n \r\n<span class=\"sel\">.toast-pop<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">bottom<\/span>: <span class=\"val\">calc(100% + 8px)<\/span>;\r\n  <span class=\"kw\">left<\/span>: <span class=\"val\">50%<\/span>;\r\n  <span class=\"kw\">transform<\/span>: <span class=\"val\">translateX(-50%)<\/span>;\r\n  <span class=\"kw\">background<\/span>: <span class=\"val\">#0f172a<\/span>;\r\n  <span class=\"kw\">color<\/span>: <span class=\"val\">#fff<\/span>;\r\n  <span class=\"kw\">font-size<\/span>: <span class=\"val\">11.5px<\/span>;\r\n  <span class=\"kw\">padding<\/span>: <span class=\"val\">5px 12px<\/span>;\r\n  <span class=\"kw\">border-radius<\/span>: <span class=\"val\">6px<\/span>;\r\n  <span class=\"kw\">white-space<\/span>: <span class=\"val\">nowrap<\/span>;\r\n  <span class=\"kw\">pointer-events<\/span>: <span class=\"val\">none<\/span>;\r\n  <span class=\"kw\">animation<\/span>: <span class=\"val\">toast-rise 1.6s ease forwards<\/span>;\r\n}\r\n<span class=\"sel\">.toast-pop::after<\/span> {\r\n  <span class=\"kw\">content<\/span>: <span class=\"val\">''<\/span>;\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">top<\/span>: <span class=\"val\">100%<\/span>; <span class=\"kw\">left<\/span>: <span class=\"val\">50%<\/span>;\r\n  <span class=\"kw\">transform<\/span>: <span class=\"val\">translateX(-50%)<\/span>;\r\n  <span class=\"kw\">border<\/span>: <span class=\"val\">5px solid transparent<\/span>;\r\n  <span class=\"kw\">border-top-color<\/span>: <span class=\"val\">#0f172a<\/span>;\r\n}\r\n<span class=\"kw\">@keyframes<\/span> toast-rise {\r\n  <span class=\"val\">0%<\/span>   { <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>; <span class=\"kw\">transform<\/span>: <span class=\"val\">translateY(0) translateX(-50%) scale(0.85)<\/span>; }\r\n  <span class=\"val\">15%<\/span>  { <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>; <span class=\"kw\">transform<\/span>: <span class=\"val\">translateY(-12px) translateX(-50%) scale(1)<\/span>; }\r\n  <span class=\"val\">75%<\/span>  { <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>; <span class=\"kw\">transform<\/span>: <span class=\"val\">translateY(-14px) translateX(-50%) scale(1)<\/span>; }\r\n  <span class=\"val\">100%<\/span> { <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>; <span class=\"kw\">transform<\/span>: <span class=\"val\">translateY(-28px) translateX(-50%) scale(0.9)<\/span>; }\r\n}<\/pre><\/div>\r\n    <div id=\"toast-js\" class=\"tab-panel\"><pre><span class=\"kw\">function<\/span> <span class=\"fn\">copyToast<\/span>(btn, text) {\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">then<\/span>(() => {\r\n    <span class=\"kw\">const<\/span> existing = btn.parentElement.<span class=\"fn\">querySelector<\/span>(<span class=\"str\">'.toast-pop'<\/span>);\r\n    <span class=\"kw\">if<\/span> (existing) existing.<span class=\"fn\">remove<\/span>();\r\n    <span class=\"kw\">const<\/span> toast = document.<span class=\"fn\">createElement<\/span>(<span class=\"str\">'div'<\/span>);\r\n    toast.className = <span class=\"str\">'toast-pop'<\/span>;\r\n    toast.textContent = <span class=\"str\">'\u2713 Copied to clipboard'<\/span>;\r\n    btn.parentElement.<span class=\"fn\">appendChild<\/span>(toast);\r\n    toast.<span class=\"fn\">addEventListener<\/span>(<span class=\"str\">'animationend'<\/span>, () => toast.<span class=\"fn\">remove<\/span>());\r\n  });\r\n}<\/pre><\/div>\r\n  <\/div>\r\n \r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 4 \u2014 Particle Burst\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">04<\/span>\r\n    <h2>Particle Burst<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">Ten dots explode outward from the button&#8217;s centre in a starburst pattern, each on its own trajectory calculated with a bit of trigonometry. It&#8217;s <strong>energetic and playful<\/strong> \u2014 better suited to casual or marketing UIs than serious developer tools. Because the particles travel outside the button&#8217;s bounds, the button needs <code>overflow: visible<\/code> instead of the usual <code>hidden<\/code>.<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box\">const { data } = await axios.get(&#8216;\/api\/users&#8217;);<\/div>\r\n        <button class=\"copy-btn particle-btn\" onclick=\"copyParticles(this, &quot;const { data } = await axios.get('\/api\/users');&quot;)\">\r\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" width=\"15\" height=\"15\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n          Copy\r\n        <\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'particle','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'particle','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'particle','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'particle')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"particle-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- Add particle-btn class so overflow:visible is applied --&gt;<\/span>\r\n&lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"copy-btn particle-btn\"<\/span>\r\n        <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copyParticles(this, 'your text here')\"<\/span>&gt;\r\n  &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n       <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n    &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n  &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n  Copy\r\n&lt;\/<span class=\"sel\">button<\/span>&gt;\r\n \r\n<span class=\"cm\">&lt;!-- .particle spans are created and injected by JS --&gt;<\/span><\/pre><\/div>\r\n    <div id=\"particle-css\" class=\"tab-panel\"><pre><span class=\"cm\">\/* overflow:visible so particles escape the button bounds *\/<\/span>\r\n<span class=\"sel\">.particle-btn<\/span> { <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>; <span class=\"kw\">overflow<\/span>: <span class=\"val\">visible<\/span>; }\r\n \r\n<span class=\"sel\">.particle<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">width<\/span>: <span class=\"val\">6px<\/span>; <span class=\"kw\">height<\/span>: <span class=\"val\">6px<\/span>;\r\n  <span class=\"kw\">border-radius<\/span>: <span class=\"val\">50%<\/span>;\r\n  <span class=\"kw\">background<\/span>: <span class=\"val\">#93c5fd<\/span>;\r\n  <span class=\"kw\">pointer-events<\/span>: <span class=\"val\">none<\/span>;\r\n  <span class=\"kw\">animation<\/span>: <span class=\"val\">particle-fly 0.65s ease-out forwards<\/span>;\r\n}\r\n<span class=\"kw\">@keyframes<\/span> particle-fly {\r\n  <span class=\"val\">0%<\/span>   { <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>; <span class=\"kw\">transform<\/span>: <span class=\"val\">translate(0,0) scale(1)<\/span>; }\r\n  <span class=\"val\">100%<\/span> { <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>; <span class=\"kw\">transform<\/span>: <span class=\"val\">translate(var(--tx), var(--ty)) scale(0)<\/span>; }\r\n}\r\n<span class=\"cm\">\/* --tx and --ty are set per-particle in JS *\/<\/span><\/pre><\/div>\r\n    <div id=\"particle-js\" class=\"tab-panel\"><pre><span class=\"kw\">function<\/span> <span class=\"fn\">copyParticles<\/span>(btn, text) {\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">catch<\/span>(() => {});\r\n  <span class=\"kw\">const<\/span> count = <span class=\"num\">10<\/span>;\r\n  <span class=\"kw\">for<\/span> (<span class=\"kw\">let<\/span> i = <span class=\"num\">0<\/span>; i &lt; count; i++) {\r\n    <span class=\"kw\">const<\/span> p = document.<span class=\"fn\">createElement<\/span>(<span class=\"str\">'span'<\/span>);\r\n    p.className = <span class=\"str\">'particle'<\/span>;\r\n    <span class=\"kw\">const<\/span> angle = (i \/ count) * <span class=\"num\">360<\/span>;\r\n    <span class=\"kw\">const<\/span> dist  = <span class=\"num\">28<\/span> + Math.<span class=\"fn\">random<\/span>() * <span class=\"num\">14<\/span>;\r\n    p.style.<span class=\"fn\">setProperty<\/span>(<span class=\"str\">'--tx'<\/span>, <span class=\"str\">`${Math.cos(angle * Math.PI \/ 180) * dist}px`<\/span>);\r\n    p.style.<span class=\"fn\">setProperty<\/span>(<span class=\"str\">'--ty'<\/span>, <span class=\"str\">`${Math.sin(angle * Math.PI \/ 180) * dist}px`<\/span>);\r\n    p.style.left = <span class=\"str\">'50%'<\/span>; p.style.top = <span class=\"str\">'50%'<\/span>;\r\n    p.style.marginLeft = <span class=\"str\">'-3px'<\/span>; p.style.marginTop = <span class=\"str\">'-3px'<\/span>;\r\n    btn.<span class=\"fn\">appendChild<\/span>(p);\r\n    p.<span class=\"fn\">addEventListener<\/span>(<span class=\"str\">'animationend'<\/span>, () => p.<span class=\"fn\">remove<\/span>());\r\n  }\r\n}<\/pre><\/div>\r\n  <\/div>\r\n<div class=\"text-center mb-20 mt-20\">\n<script async src=\"https:\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js\"><\/script>\n<!-- CSS Responsive -->\n<ins class=\"adsbygoogle\"\n     style=\"display:block\"\n     data-ad-client=\"ca-pub-1356719463849900\"\n     data-ad-slot=\"5275015068\"\n     data-ad-format=\"horizontal\"\n     data-full-width-responsive=\"true\"><\/ins>\n<script>\n     (adsbygoogle = window.adsbygoogle || []).push({});\n<\/script>\n<\/div>\n<div class=\"adblock-message bg-main-50 rounded p-10 mb-20\">  \n\t<div class=\"d-flex align-items-center justify-content-between\">\n\t  <span class=\"text-gray-400\">If this site has been useful, we\u2019d love your support! Consider buying us a coffee to keep things going strong!<\/span>\n\t  <div class=\"buymeacoffee\">\n\t\t<a target=\"_blank\" href=\"https:\/\/buymeacoffee.com\/rpjs\"><img decoding=\"async\" width=\"180\" src=\"\/assets\/images\/coffee.png\"><\/a>\n\t  <\/div>\n\t<\/div>\n<\/div> \r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 5 \u2014 Scanner Sweep\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">05<\/span>\r\n    <h2>Scanner Sweep<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">A glowing blue laser line sweeps across the text field while it flashes a pale blue \u2014 mimicking the feeling of content being <strong>scanned and captured<\/strong>. This one is applied to the snippet box rather than the button, making it perfect for JWT tokens, hash strings, or any value that feels like it should be &#8220;read&#8221; by a machine. The scan line is a simple absolutely-positioned div animated with <code>left<\/code>.<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box scanner-box\" id=\"scanner-target\">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9<\/div>\r\n        <button class=\"copy-btn\" onclick=\"copyScanner(this, 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9')\">\r\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" width=\"15\" height=\"15\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n          Copy\r\n        <\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'scanner','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'scanner','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'scanner','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'scanner')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"scanner-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- scanner-box goes on the text field, not the button --&gt;<\/span>\r\n&lt;<span class=\"sel\">div<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"snippet-box scanner-box\"<\/span> <span class=\"kw\">id<\/span>=<span class=\"str\">\"scanner-target\"<\/span>&gt;\r\n  your text here\r\n&lt;\/<span class=\"sel\">div<\/span>&gt;\r\n \r\n&lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"copy-btn\"<\/span>\r\n        <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copyScanner(this, 'your text here')\"<\/span>&gt;\r\n  &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n       <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n    &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n  &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n  Copy\r\n&lt;\/<span class=\"sel\">button<\/span>&gt;\r\n \r\n<span class=\"cm\">&lt;!-- .scan-line div is created and injected by JS --&gt;<\/span><\/pre><\/div>\r\n    <div id=\"scanner-css\" class=\"tab-panel\"><pre><span class=\"cm\">\/* The text box needs position:relative + overflow:hidden *\/<\/span>\r\n<span class=\"sel\">.scanner-box<\/span> { <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>; <span class=\"kw\">overflow<\/span>: <span class=\"val\">hidden<\/span>; }\r\n \r\n<span class=\"sel\">.scan-line<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">top<\/span>: <span class=\"val\">0<\/span>; <span class=\"kw\">bottom<\/span>: <span class=\"val\">0<\/span>;\r\n  <span class=\"kw\">width<\/span>: <span class=\"val\">3px<\/span>;\r\n  <span class=\"kw\">background<\/span>: <span class=\"val\">linear-gradient(to bottom, transparent, #2563eb, transparent)<\/span>;\r\n  <span class=\"kw\">pointer-events<\/span>: <span class=\"val\">none<\/span>;\r\n  <span class=\"kw\">box-shadow<\/span>: <span class=\"val\">0 0 10px #2563eb, 0 0 20px #93c5fd<\/span>;\r\n  <span class=\"kw\">animation<\/span>: <span class=\"val\">scan-sweep 0.7s ease-in-out forwards<\/span>;\r\n}\r\n<span class=\"kw\">@keyframes<\/span> scan-sweep {\r\n  <span class=\"val\">0%<\/span>   { <span class=\"kw\">left<\/span>: <span class=\"val\">-4px<\/span>;             <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>; }\r\n  <span class=\"val\">5%<\/span>   { <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>; }\r\n  <span class=\"val\">95%<\/span>  { <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>; }\r\n  <span class=\"val\">100%<\/span> { <span class=\"kw\">left<\/span>: <span class=\"val\">calc(100% + 4px)<\/span>; <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>; }\r\n}\r\n<span class=\"sel\">.scanner-box.scanning<\/span> { <span class=\"kw\">animation<\/span>: <span class=\"val\">scan-flash 0.7s ease<\/span>; }\r\n<span class=\"kw\">@keyframes<\/span> scan-flash {\r\n  <span class=\"val\">0%<\/span>, <span class=\"val\">100%<\/span> { <span class=\"kw\">background<\/span>: <span class=\"val\">#ffffff<\/span>; }\r\n  <span class=\"val\">40%<\/span>       { <span class=\"kw\">background<\/span>: <span class=\"val\">#eff6ff<\/span>; }\r\n}<\/pre><\/div>\r\n    <div id=\"scanner-js\" class=\"tab-panel\"><pre><span class=\"kw\">function<\/span> <span class=\"fn\">copyScanner<\/span>(btn, text) {\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">catch<\/span>(() => {});\r\n  <span class=\"kw\">const<\/span> target = document.<span class=\"fn\">getElementById<\/span>(<span class=\"str\">'scanner-target'<\/span>);\r\n  <span class=\"kw\">if<\/span> (target.<span class=\"fn\">querySelector<\/span>(<span class=\"str\">'.scan-line'<\/span>)) <span class=\"kw\">return<\/span>;\r\n  target.classList.<span class=\"fn\">add<\/span>(<span class=\"str\">'scanning'<\/span>);\r\n  <span class=\"kw\">const<\/span> line = document.<span class=\"fn\">createElement<\/span>(<span class=\"str\">'div'<\/span>);\r\n  line.className = <span class=\"str\">'scan-line'<\/span>;\r\n  target.<span class=\"fn\">appendChild<\/span>(line);\r\n  line.<span class=\"fn\">addEventListener<\/span>(<span class=\"str\">'animationend'<\/span>, () => {\r\n    line.<span class=\"fn\">remove<\/span>();\r\n    target.classList.<span class=\"fn\">remove<\/span>(<span class=\"str\">'scanning'<\/span>);\r\n  });\r\n}<\/pre><\/div>\r\n  <\/div>\r\n\r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 6 \u2014 Slide-Up Label\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">06<\/span>\r\n    <h2>Slide-Up Label<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">The &#8220;Copy&#8221; label slides upward out of the button while &#8220;Done&#8221; rises in from below, meeting it in the middle. A springy <strong>cubic-bezier curve<\/strong> gives the incoming label a satisfying overshoot bounce. This is a great alternative to the checkmark swap when you want motion without a colour change \u2014 it works beautifully on both light and dark buttons.<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box\">docker pull node:20-alpine<\/div>\r\n        <button class=\"copy-btn slide-btn\" onclick=\"copySlide(this, 'docker pull node:20-alpine')\">\r\n          <span class=\"slide-default\">\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" width=\"15\" height=\"15\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n            Copy\r\n          <\/span>\r\n          <span class=\"slide-done\">\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" width=\"15\" height=\"15\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg>\r\n            Done\r\n          <\/span>\r\n        <\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'slide','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'slide','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'slide','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'slide')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"slide-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- Two spans inside the button \u2014 default label and confirmed label --&gt;<\/span>\r\n&lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"copy-btn slide-btn\"<\/span>\r\n        <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copySlide(this, 'your text here')\"<\/span>&gt;\r\n \r\n  &lt;<span class=\"sel\">span<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"slide-default\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n         <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n      &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n      &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n    &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n    Copy\r\n  &lt;\/<span class=\"sel\">span<\/span>&gt;\r\n \r\n  &lt;<span class=\"sel\">span<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"slide-done\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n         <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2.5\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n      &lt;<span class=\"sel\">polyline<\/span> <span class=\"kw\">points<\/span>=<span class=\"str\">\"20 6 9 17 4 12\"<\/span>\/&gt;\r\n    &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n    Done\r\n  &lt;\/<span class=\"sel\">span<\/span>&gt;\r\n \r\n&lt;\/<span class=\"sel\">button<\/span>&gt;<\/pre><\/div>\r\n    <div id=\"slide-css\" class=\"tab-panel\"><pre><span class=\"sel\">.slide-btn<\/span> { <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>; <span class=\"kw\">overflow<\/span>: <span class=\"val\">hidden<\/span>; }\r\n \r\n<span class=\"sel\">.slide-btn .slide-default<\/span>,\r\n<span class=\"sel\">.slide-btn .slide-done<\/span> {\r\n  <span class=\"kw\">display<\/span>: <span class=\"val\">flex<\/span>;\r\n  <span class=\"kw\">align-items<\/span>: <span class=\"val\">center<\/span>;\r\n  <span class=\"kw\">gap<\/span>: <span class=\"val\">6px<\/span>;\r\n  <span class=\"kw\">transition<\/span>: <span class=\"val\">transform 0.3s cubic-bezier(.34,1.56,.64,1), opacity 0.25s<\/span>;\r\n}\r\n<span class=\"sel\">.slide-btn .slide-done<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">inset<\/span>: <span class=\"val\">0<\/span>;\r\n  <span class=\"kw\">justify-content<\/span>: <span class=\"val\">center<\/span>;\r\n  <span class=\"kw\">transform<\/span>: <span class=\"val\">translateY(100%)<\/span>;\r\n  <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>;\r\n}\r\n<span class=\"sel\">.slide-btn.slid .slide-default<\/span> { <span class=\"kw\">transform<\/span>: <span class=\"val\">translateY(-110%)<\/span>; <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>; }\r\n<span class=\"sel\">.slide-btn.slid .slide-done<\/span>    { <span class=\"kw\">transform<\/span>: <span class=\"val\">translateY(0)<\/span>;     <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>; }\r\n<span class=\"sel\">.slide-btn.slid<\/span> { <span class=\"kw\">background<\/span>: <span class=\"val\">#1d4ed8<\/span> !important; }<\/pre><\/div>\r\n    <div id=\"slide-js\" class=\"tab-panel\"><pre><span class=\"kw\">function<\/span> <span class=\"fn\">copySlide<\/span>(btn, text) {\r\n  <span class=\"kw\">if<\/span> (btn.classList.<span class=\"fn\">contains<\/span>(<span class=\"str\">'slid'<\/span>)) <span class=\"kw\">return<\/span>;\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">catch<\/span>(() => {});\r\n  btn.classList.<span class=\"fn\">add<\/span>(<span class=\"str\">'slid'<\/span>);\r\n  <span class=\"fn\">setTimeout<\/span>(() => btn.classList.<span class=\"fn\">remove<\/span>(<span class=\"str\">'slid'<\/span>), <span class=\"num\">2200<\/span>);\r\n}<\/pre><\/div>\r\n  <\/div>\r\n \r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 7 \u2014 Border Trace\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">07<\/span>\r\n    <h2>Border Trace<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">A bright blue arc sweeps clockwise around the button&#8217;s border in under a second, using a <code>conic-gradient<\/code> animated via the Houdini <code>@property<\/code> API. It&#8217;s <strong>subtle but technically impressive<\/strong> \u2014 CSS alone can&#8217;t normally animate a gradient, so this trick requires registering a custom property to make the percentage value interpolatable. Note that <code>@property<\/code> requires a secure context (HTTPS).<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box\">https:\/\/api.example.com\/v2\/endpoint<\/div>\r\n        <div class=\"trace-wrap\" id=\"trace-wrap\">\r\n          <button class=\"trace-inner\" onclick=\"copyTrace(this, 'https:\/\/api.example.com\/v2\/endpoint')\">\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" width=\"15\" height=\"15\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n            Copy\r\n          <\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'trace','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'trace','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'trace','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'trace')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"trace-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- The wrapper div creates the animated border ring --&gt;<\/span>\r\n&lt;<span class=\"sel\">div<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"trace-wrap\"<\/span> <span class=\"kw\">id<\/span>=<span class=\"str\">\"trace-wrap\"<\/span>&gt;\r\n  &lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"trace-inner\"<\/span>\r\n          <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copyTrace(this, 'your text here')\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n         <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n      &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n      &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n    &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n    Copy\r\n  &lt;\/<span class=\"sel\">button<\/span>&gt;\r\n&lt;\/<span class=\"sel\">div<\/span>&gt;\r\n \r\n<span class=\"cm\">&lt;!-- The trace animation is on .trace-wrap::before via CSS --&gt;<\/span><\/pre><\/div>\r\n    <div id=\"trace-css\" class=\"tab-panel\"><pre><span class=\"cm\">\/* Requires @property for animating the CSS custom property *\/<\/span>\r\n<span class=\"kw\">@property<\/span> --p {\r\n  <span class=\"kw\">syntax<\/span>: <span class=\"str\">'&lt;percentage&gt;'<\/span>;\r\n  <span class=\"kw\">inherits<\/span>: <span class=\"val\">false<\/span>;\r\n  <span class=\"kw\">initial-value<\/span>: <span class=\"val\">0%<\/span>;\r\n}\r\n<span class=\"sel\">.trace-wrap<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>;\r\n  <span class=\"kw\">display<\/span>: <span class=\"val\">inline-flex<\/span>;\r\n  <span class=\"kw\">border-radius<\/span>: <span class=\"val\">10px<\/span>;\r\n  <span class=\"kw\">padding<\/span>: <span class=\"val\">3px<\/span>;\r\n  <span class=\"kw\">background<\/span>: <span class=\"val\">#e2e8f0<\/span>; <span class=\"cm\">\/* neutral grey ring at rest *\/<\/span>\r\n}\r\n<span class=\"sel\">.trace-wrap::before<\/span> {\r\n  <span class=\"kw\">content<\/span>: <span class=\"val\">''<\/span>;\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">inset<\/span>: <span class=\"val\">0<\/span>;\r\n  <span class=\"kw\">border-radius<\/span>: <span class=\"val\">inherit<\/span>;\r\n  <span class=\"kw\">background<\/span>: <span class=\"val\">conic-gradient(#2563eb var(--p, 0%), transparent 0%)<\/span>;\r\n  <span class=\"kw\">pointer-events<\/span>: <span class=\"val\">none<\/span>;\r\n  <span class=\"kw\">z-index<\/span>: <span class=\"val\">0<\/span>;\r\n  <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>;\r\n}\r\n<span class=\"sel\">.trace-wrap.tracing::before<\/span> {\r\n  <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>;\r\n  <span class=\"kw\">animation<\/span>: <span class=\"val\">trace-go 0.85s linear forwards<\/span>;\r\n}\r\n<span class=\"kw\">@keyframes<\/span> trace-go {\r\n  <span class=\"kw\">from<\/span> { --p: <span class=\"val\">0%<\/span>; }\r\n  <span class=\"kw\">to<\/span>   { --p: <span class=\"val\">100%<\/span>; }\r\n}\r\n<span class=\"sel\">.trace-wrap .trace-inner<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>;\r\n  <span class=\"kw\">z-index<\/span>: <span class=\"val\">1<\/span>;\r\n  <span class=\"kw\">border-radius<\/span>: <span class=\"val\">7px<\/span>;\r\n  <span class=\"kw\">background<\/span>: <span class=\"val\">#2563eb<\/span>;\r\n  <span class=\"kw\">color<\/span>: <span class=\"val\">#fff<\/span>;\r\n  <span class=\"kw\">border<\/span>: <span class=\"val\">none<\/span>;\r\n  <span class=\"kw\">padding<\/span>: <span class=\"val\">10px 18px<\/span>;\r\n  <span class=\"kw\">cursor<\/span>: <span class=\"val\">pointer<\/span>;\r\n}<\/pre><\/div>\r\n    <div id=\"trace-js\" class=\"tab-panel\"><pre><span class=\"kw\">function<\/span> <span class=\"fn\">copyTrace<\/span>(btn, text) {\r\n  <span class=\"kw\">const<\/span> wrap = btn.<span class=\"fn\">closest<\/span>(<span class=\"str\">'.trace-wrap'<\/span>);\r\n  <span class=\"kw\">if<\/span> (wrap.classList.<span class=\"fn\">contains<\/span>(<span class=\"str\">'tracing'<\/span>)) <span class=\"kw\">return<\/span>;\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">catch<\/span>(() => {});\r\n  wrap.classList.<span class=\"fn\">add<\/span>(<span class=\"str\">'tracing'<\/span>);\r\n  <span class=\"fn\">setTimeout<\/span>(() => wrap.classList.<span class=\"fn\">remove<\/span>(<span class=\"str\">'tracing'<\/span>), <span class=\"num\">950<\/span>);\r\n}<\/pre><\/div>\r\n  <\/div>\r\n \r\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n       EFFECT 8 \u2014 Confetti Shower\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n  <div class=\"section-label\">\r\n    <span class=\"section-num\">08<\/span>\r\n    <h2>Confetti Shower<\/h2>\r\n  <\/div>\r\n  <p class=\"effect-desc\">Eighteen coloured squares shower downward from the button in a burst of celebration \u2014 each with a randomised horizontal drift, fall distance, and rotation. It&#8217;s <strong>unashamedly joyful<\/strong> and best reserved for moments that genuinely warrant it: promo codes, referral links, successful completions. Using it on a plain code snippet would feel out of place, but on a &#8220;Share your invite link&#8221; button it&#8217;s perfect.<\/p>\r\n \r\n  <div class=\"demo-card\">\r\n    <div class=\"demo-card-header\">\r\n      <span class=\"demo-card-title\">Live Demo<\/span>\r\n      <span class=\"demo-badge\">click to copy<\/span>\r\n    <\/div>\r\n    <div class=\"demo-area\">\r\n      <div class=\"snippet-row\">\r\n        <div class=\"snippet-box\">\u2022 Your promo code: LAUNCH2025FREE<\/div>\r\n        <div class=\"confetti-anchor\">\r\n          <button class=\"copy-btn\" onclick=\"copyConfetti(this, 'LAUNCH2025FREE')\">\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" width=\"15\" height=\"15\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n            Copy Code\r\n          <\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n \r\n  <div class=\"code-tabs\">\r\n    <div class=\"code-tab-bar\">\r\n      <div class=\"code-tab-dots\"><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><div class=\"cb-dot\"><\/div><\/div>\r\n      <button class=\"tab-btn active\" onclick=\"switchTab(this,'confetti','html')\">HTML<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'confetti','css')\">CSS<\/button>\r\n      <button class=\"tab-btn\" onclick=\"switchTab(this,'confetti','js')\">JS<\/button>\r\n      <button class=\"copy-code-btn\" onclick=\"copyCode(this,'confetti')\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"\/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"\/><\/svg>\r\n        Copy code\r\n      <\/button>\r\n    <\/div>\r\n    <div id=\"confetti-html\" class=\"tab-panel active\"><pre><span class=\"cm\">&lt;!-- Wrap the button so confetti pieces have a reference point --&gt;<\/span>\r\n&lt;<span class=\"sel\">div<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"confetti-anchor\"<\/span>&gt;\r\n  &lt;<span class=\"sel\">button<\/span> <span class=\"kw\">class<\/span>=<span class=\"str\">\"copy-btn\"<\/span>\r\n          <span class=\"kw\">onclick<\/span>=<span class=\"str\">\"copyConfetti(this, 'your text here')\"<\/span>&gt;\r\n    &lt;<span class=\"sel\">svg<\/span> <span class=\"kw\">viewBox<\/span>=<span class=\"str\">\"0 0 24 24\"<\/span> <span class=\"kw\">fill<\/span>=<span class=\"str\">\"none\"<\/span> <span class=\"kw\">stroke<\/span>=<span class=\"str\">\"currentColor\"<\/span>\r\n         <span class=\"kw\">stroke-width<\/span>=<span class=\"str\">\"2\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"15\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"15\"<\/span>&gt;\r\n      &lt;<span class=\"sel\">rect<\/span> <span class=\"kw\">x<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">y<\/span>=<span class=\"str\">\"9\"<\/span> <span class=\"kw\">width<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">height<\/span>=<span class=\"str\">\"13\"<\/span> <span class=\"kw\">rx<\/span>=<span class=\"str\">\"2\"<\/span>\/&gt;\r\n      &lt;<span class=\"sel\">path<\/span> <span class=\"kw\">d<\/span>=<span class=\"str\">\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"<\/span>\/&gt;\r\n    &lt;\/<span class=\"sel\">svg<\/span>&gt;\r\n    Copy Code\r\n  &lt;\/<span class=\"sel\">button<\/span>&gt;\r\n  <span class=\"cm\">&lt;!-- .confetto divs are created and injected by JS --&gt;<\/span>\r\n&lt;\/<span class=\"sel\">div<\/span>&gt;<\/pre><\/div>\r\n    <div id=\"confetti-css\" class=\"tab-panel\"><pre><span class=\"cm\">\/* Wrap your button in a position:relative container *\/<\/span>\r\n<span class=\"sel\">.confetti-anchor<\/span> { <span class=\"kw\">position<\/span>: <span class=\"val\">relative<\/span>; <span class=\"kw\">display<\/span>: <span class=\"val\">inline-flex<\/span>; }\r\n \r\n<span class=\"sel\">.confetto<\/span> {\r\n  <span class=\"kw\">position<\/span>: <span class=\"val\">absolute<\/span>;\r\n  <span class=\"kw\">top<\/span>: <span class=\"val\">0<\/span>; <span class=\"kw\">left<\/span>: <span class=\"val\">50%<\/span>;\r\n  <span class=\"kw\">width<\/span>: <span class=\"val\">7px<\/span>; <span class=\"kw\">height<\/span>: <span class=\"val\">7px<\/span>;\r\n  <span class=\"kw\">border-radius<\/span>: <span class=\"val\">2px<\/span>;\r\n  <span class=\"kw\">pointer-events<\/span>: <span class=\"val\">none<\/span>;\r\n  <span class=\"kw\">z-index<\/span>: <span class=\"val\">10<\/span>;\r\n  <span class=\"kw\">animation<\/span>: <span class=\"val\">confetti-fall 0.9s ease-in forwards<\/span>;\r\n}\r\n<span class=\"cm\">\/* --cx, --cy, --cr are randomised per piece in JS *\/<\/span>\r\n<span class=\"kw\">@keyframes<\/span> confetti-fall {\r\n  <span class=\"val\">0%<\/span>   { <span class=\"kw\">opacity<\/span>: <span class=\"val\">1<\/span>;\r\n         <span class=\"kw\">transform<\/span>: <span class=\"val\">translate(var(--cx), -4px) rotate(var(--cr)) scale(1)<\/span>; }\r\n  <span class=\"val\">100%<\/span> { <span class=\"kw\">opacity<\/span>: <span class=\"val\">0<\/span>;\r\n         <span class=\"kw\">transform<\/span>: <span class=\"val\">translate(var(--cx), var(--cy))\r\n                    rotate(calc(var(--cr) + 360deg)) scale(0.3)<\/span>; }\r\n}<\/pre><\/div>\r\n    <div id=\"confetti-js\" class=\"tab-panel\"><pre><span class=\"kw\">const<\/span> confettiColors = [<span class=\"str\">'#2563eb'<\/span>,<span class=\"str\">'#93c5fd'<\/span>,<span class=\"str\">'#fbbf24'<\/span>,<span class=\"str\">'#34d399'<\/span>,<span class=\"str\">'#f87171'<\/span>];\r\n \r\n<span class=\"kw\">function<\/span> <span class=\"fn\">copyConfetti<\/span>(btn, text) {\r\n  navigator.clipboard.<span class=\"fn\">writeText<\/span>(text).<span class=\"fn\">catch<\/span>(() => {});\r\n  <span class=\"kw\">const<\/span> anchor = btn.parentElement;\r\n  <span class=\"kw\">for<\/span> (<span class=\"kw\">let<\/span> i = <span class=\"num\">0<\/span>; i &lt; <span class=\"num\">18<\/span>; i++) {\r\n    <span class=\"kw\">const<\/span> c = document.<span class=\"fn\">createElement<\/span>(<span class=\"str\">'div'<\/span>);\r\n    c.className = <span class=\"str\">'confetto'<\/span>;\r\n    c.style.background = confettiColors[i % confettiColors.length];\r\n    c.style.<span class=\"fn\">setProperty<\/span>(<span class=\"str\">'--cx'<\/span>, <span class=\"str\">`${(Math.random() - 0.5) * 90}px`<\/span>);\r\n    c.style.<span class=\"fn\">setProperty<\/span>(<span class=\"str\">'--cy'<\/span>, <span class=\"str\">`${40 + Math.random() * 40}px`<\/span>);\r\n    c.style.<span class=\"fn\">setProperty<\/span>(<span class=\"str\">'--cr'<\/span>, <span class=\"str\">`${Math.random() * 360}deg`<\/span>);\r\n    c.style.animationDelay = <span class=\"str\">`${Math.random() * 0.2}s`<\/span>;\r\n    anchor.<span class=\"fn\">appendChild<\/span>(c);\r\n    c.<span class=\"fn\">addEventListener<\/span>(<span class=\"str\">'animationend'<\/span>, () => c.<span class=\"fn\">remove<\/span>());\r\n  }\r\n}<\/pre><\/div>\r\n  <\/div>\r\n \r\n  <!-- \u2500\u2500 Wrap-up \u2500\u2500 -->\r\n  <hr class=\"divider\">\r\n  <div class=\"prose\">\r\n    <p>All eight of these effects share the same core pattern: call <code>navigator.clipboard.writeText(text)<\/code>, then inside the <code>.then()<\/code> callback, do your animation work. That single constraint \u2014 <strong>animate only on success<\/strong> \u2014 is what makes these feel honest rather than optimistic.<\/p>\r\n    <p>A few tips for production use: always debounce rapid clicks (the checkmark swap and slide-up examples show this with a class guard), clean up your DOM elements via <code>animationend<\/code> events rather than <code>setTimeout<\/code> to avoid memory leaks, and for the border trace effect, make sure you&#8217;re serving over HTTPS since <code>@property<\/code> and the Clipboard API both require a secure context.<\/p>\r\n    <p>Pick the effect that matches your UI&#8217;s energy \u2014 the confetti is perfect for promo codes or moments worth celebrating, the scanner sweep fits developer tools, and the subtle ripple or slide-up work anywhere without feeling out of place.<\/p>\r\n  <\/div>\r\n \r\n<\/main>\r\n<script>\r\n\/\/ \u2500\u2500 Clipboard write (best-effort, non-blocking) \u2500\u2500\r\nfunction writeToClipboard(text) {\r\n  try {\r\n    if (navigator.clipboard && navigator.clipboard.writeText) {\r\n      navigator.clipboard.writeText(text).catch(() => {});\r\n      return;\r\n    }\r\n    const ta = document.createElement('textarea');\r\n    ta.value = text;\r\n    ta.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0;';\r\n    document.body.appendChild(ta);\r\n    ta.focus(); ta.select();\r\n    document.execCommand('copy');\r\n    document.body.removeChild(ta);\r\n  } catch(e) {}\r\n}\r\n\/\/ \u2500\u2500 Tab switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction switchTab(btn, group, tab) {\r\n  const bar = btn.closest('.code-tab-bar');\r\n  bar.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));\r\n  btn.classList.add('active');\r\n  const block = btn.closest('.code-tabs');\r\n  block.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));\r\n  block.querySelector('#' + group + '-' + tab).classList.add('active');\r\n}\r\n\/\/ \u2500\u2500 Copy code panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copyCode(btn, group) {\r\n  const block = btn.closest('.code-tabs');\r\n  const activePanel = block.querySelector('.tab-panel.active');\r\n  const pre = activePanel.querySelector('pre');\r\n  \/\/ textContent works on hidden elements; innerText does not\r\n  const text = pre.textContent;\r\n  \/\/ Use a temporary textarea \u2014 reliable across all contexts (file:\/\/, http, https)\r\n  const ta = document.createElement('textarea');\r\n  ta.value = text;\r\n  ta.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0;font-size:16px;';\r\n  document.body.appendChild(ta);\r\n  ta.focus();\r\n  ta.select();\r\n  try { document.execCommand('copy'); } catch(e) {}\r\n  document.body.removeChild(ta);\r\n  \/\/ Also try modern API in parallel (works on https)\r\n  if (navigator.clipboard && navigator.clipboard.writeText) {\r\n    navigator.clipboard.writeText(text).catch(() => {});\r\n  }\r\n  \/\/ Visual feedback\r\n  btn.classList.add('code-copied');\r\n  const orig = btn.innerHTML;\r\n  btn.innerHTML = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" width=\"12\" height=\"12\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg> Copied!';\r\n  setTimeout(() => { btn.classList.remove('code-copied'); btn.innerHTML = orig; }, 2000);\r\n}\r\n\/\/ \u2500\u2500 Effect 1: Ripple \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copyRipple(btn, text) {\r\n  writeToClipboard(text);\r\n  const ripple = document.createElement('span');\r\n  const size = Math.max(btn.offsetWidth, btn.offsetHeight);\r\n  ripple.className = 'ripple-effect';\r\n  ripple.style.cssText = `width:${size}px;height:${size}px;top:50%;left:50%;margin:-${size\/2}px 0 0 -${size\/2}px;position:absolute;`;\r\n  btn.appendChild(ripple);\r\n  ripple.addEventListener('animationend', () => ripple.remove());\r\n}\r\n\/\/ \u2500\u2500 Effect 2: Checkmark Swap \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copyCheck(btn, text) {\r\n  if (btn.classList.contains('copied1')) return;\r\n  writeToClipboard(text);\r\n  btn.classList.add('copied1');\r\n  setTimeout(() => btn.classList.remove('copied1'), 2000);\r\n}\r\n\/\/ \u2500\u2500 Effect 3: Floating Toast \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copyToast(btn, text) {\r\n  writeToClipboard(text);\r\n  const existing = btn.parentElement.querySelector('.toast-pop');\r\n  if (existing) existing.remove();\r\n  const toast = document.createElement('div');\r\n  toast.className = 'toast-pop';\r\n  toast.textContent = '\u2713 Copied to clipboard';\r\n  btn.parentElement.appendChild(toast);\r\n  toast.addEventListener('animationend', () => toast.remove());\r\n}\r\n\/\/ \u2500\u2500 Effect 4: Particles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copyParticles(btn, text) {\r\n  writeToClipboard(text);\r\n  const count = 10;\r\n  for (let i = 0; i < count; i++) {\r\n    const p = document.createElement('span');\r\n    p.className = 'particle';\r\n    const angle = (i \/ count) * 360;\r\n    const dist = 28 + Math.random() * 14;\r\n    p.style.setProperty('--css-tx', `${Math.cos(angle * Math.PI \/ 180) * dist}px`);\r\n    p.style.setProperty('--css-ty', `${Math.sin(angle * Math.PI \/ 180) * dist}px`);\r\n    p.style.cssText += 'left:50%;top:50%;margin-left:-3px;margin-top:-3px;position:absolute;';\r\n    btn.appendChild(p);\r\n    p.addEventListener('animationend', () => p.remove());\r\n  }\r\n}\r\n\/\/ \u2500\u2500 Effect 5: Scanner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copyScanner(btn, text) {\r\n  writeToClipboard(text);\r\n  const target = document.getElementById('scanner-target');\r\n  if (target.querySelector('.scan-line')) return;\r\n  target.classList.add('scanning');\r\n  const line = document.createElement('div');\r\n  line.className = 'scan-line';\r\n  target.appendChild(line);\r\n  line.addEventListener('animationend', () => {\r\n    line.remove();\r\n    target.classList.remove('scanning');\r\n  });\r\n}\r\n\/\/ \u2500\u2500 Effect 6: Slide-Up \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copySlide(btn, text) {\r\n  if (btn.classList.contains('slid')) return;\r\n  writeToClipboard(text);\r\n  btn.classList.add('slid');\r\n  setTimeout(() => btn.classList.remove('slid'), 2200);\r\n}\r\n\/\/ \u2500\u2500 Effect 7: Border Trace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction copyTrace(btn, text) {\r\n  const wrap = btn.closest('.trace-wrap');\r\n  if (wrap.classList.contains('tracing')) return;\r\n  writeToClipboard(text);\r\n  wrap.classList.add('tracing');\r\n  setTimeout(() => wrap.classList.remove('tracing'), 950);\r\n}\r\n\/\/ \u2500\u2500 Effect 8: Confetti \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nconst confettiColors = ['#2563eb','#93c5fd','#fbbf24','#34d399','#f87171','#a78bfa'];\r\nfunction copyConfetti(btn, text) {\r\n  writeToClipboard(text);\r\n  const anchor = btn.parentElement;\r\n  for (let i = 0; i < 18; i++) {\r\n    const c = document.createElement('div');\r\n    c.className = 'confetto';\r\n    c.style.background = confettiColors[i % confettiColors.length];\r\n    c.style.setProperty('--css-cx', `${(Math.random() - 0.5) * 90}px`);\r\n    c.style.setProperty('--css-cy', `${40 + Math.random() * 40}px`);\r\n    c.style.setProperty('--css-cr', `${Math.random() * 360}deg`);\r\n    c.style.animationDelay = `${Math.random() * 0.2}s`;\r\n    anchor.appendChild(c);\r\n    c.addEventListener('animationend', () => c.remove());\r\n  }\r\n}\r\n<\/script>\r\n","protected":false},"excerpt":{"rendered":"Copy-to-clipboard is one of those interactions that deserves a little ceremony. The user performed an action \u2014 let them feel it. In a previous post we explored animation effects using clipboard.js. Today we&#8217;re stripping that dependency out entirely and doing everything with navigator.clipboard.writeText(), CSS animations, and a dash of vanilla JS. Each demo below is [&hellip;]","protected":false},"author":1,"featured_media":807,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,7,3],"tags":[],"class_list":["post-806","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-css","category-html","category-javascript","no-wpautop"],"_links":{"self":[{"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/posts\/806","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/comments?post=806"}],"version-history":[{"count":1,"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/posts\/806\/revisions"}],"predecessor-version":[{"id":808,"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/posts\/806\/revisions\/808"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/media\/807"}],"wp:attachment":[{"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/media?parent=806"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/categories?post=806"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cssportal.com\/blog\/wp-json\/wp\/v2\/tags?post=806"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}