پیشنمایش زنده
کد HTML
<button class="plush-btn" type="button" aria-label="Continue">
<span class="plush-btn__inner">
<span class="plush-btn__label">Continue</span>
<svg class="plush-btn__icon" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M9 5l7 7-7 7"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
></path>
</svg>
</span>
</button>
کد CSS
/* Component: Plush Button (scoped, no globals) */
.plush-btn {
/* Scoped design tokens */
--btn-h: 258; /* hue */
--btn-s: 70%; /* saturation */
--btn-l: 46%; /* lightness */
--btn-bg: hsl(var(--btn-h) var(--btn-s) var(--btn-l));
--btn-bg-hi: hsl(
var(--btn-h) calc(var(--btn-s) + 10%) calc(var(--btn-l) + 6%)
);
--btn-bg-lo: hsl(
var(--btn-h) calc(var(--btn-s) - 8%) calc(var(--btn-l) - 8%)
);
--btn-txt: #fff;
--btn-radius: 1.75em;
--btn-pad-y: 0.9em;
--btn-pad-x: 1.4em;
--btn-gap: 0.65em;
--btn-shadow: 0 0.35em 1.1em -0.25em rgba(30, 22, 70, 0.45),
0 0.08em 0.4em -0.05em rgba(30, 22, 70, 0.35);
--btn-shadow-hover: 0 0.6em 1.4em -0.25em rgba(30, 22, 70, 0.55),
0 0.1em 0.5em -0.05em rgba(30, 22, 70, 0.4);
--btn-inset-hi: inset 0 0.07em 0.18em rgba(255, 255, 255, 0.75);
--btn-inset-lo: inset 0 -0.12em 0.6em rgba(0, 0, 0, 0.25);
--btn-ring: 0 0 0 0.22em rgba(255, 255, 255, 0.95),
0 0 0 0.44em hsl(var(--btn-h) 85% 78% / 0.9);
appearance: none;
border: 0;
outline: none;
cursor: pointer;
user-select: none;
display: inline-flex;
align-items: center;
padding: var(--btn-pad-y) var(--btn-pad-x);
border-radius: var(--btn-radius);
background: linear-gradient(180deg, var(--btn-bg-hi), var(--btn-bg));
color: var(--btn-txt);
font: inherit;
line-height: 1;
box-shadow: var(--btn-shadow), var(--btn-inset-hi), var(--btn-inset-lo);
position: relative;
transform: translateY(0);
transition:
transform 120ms ease,
box-shadow 200ms ease,
background 200ms ease,
letter-spacing 160ms ease;
}
/* Soft plush “glare” */
.plush-btn::before {
content: "";
position: absolute;
inset: 0.12em;
border-radius: calc(var(--btn-radius) - 0.12em);
background: radial-gradient(
120% 80% at 50% -10%,
rgba(255, 255, 255, 0.55),
transparent 55%
),
linear-gradient(
180deg,
rgba(255, 255, 255, 0.28),
rgba(255, 255, 255, 0) 45%
);
pointer-events: none;
mix-blend-mode: screen;
}
/* Subtle inner cushion */
.plush-btn::after {
content: "";
position: absolute;
inset: 0;
border-radius: var(--btn-radius);
box-shadow: inset 0 0.18em 0.6em rgba(0, 0, 0, 0.18);
opacity: 0.5;
pointer-events: none;
}
.plush-btn .plush-btn__inner {
display: inline-flex;
align-items: center;
gap: var(--btn-gap);
letter-spacing: 0.01em;
transition: letter-spacing 160ms ease;
}
.plush-btn .plush-btn__label {
font-weight: 600;
white-space: nowrap;
}
.plush-btn .plush-btn__icon {
width: 1.1em;
height: 1.1em;
flex: 0 0 auto;
transition:
transform 160ms ease,
opacity 160ms ease;
opacity: 0.95;
}
/* Hover: lift, deepen shadow, nudge icon */
.plush-btn:hover {
transform: translateY(-0.06em);
box-shadow: var(--btn-shadow-hover), var(--btn-inset-hi), var(--btn-inset-lo);
}
.plush-btn:hover .plush-btn__icon {
transform: translateX(0.12em);
}
/* Active: press into cushion */
.plush-btn:active {
transform: translateY(0);
box-shadow:
0 0.18em 0.7em -0.2em rgba(30, 22, 70, 0.5),
inset 0 0.16em 0.4em rgba(0, 0, 0, 0.3),
inset 0 -0.08em 0.22em rgba(255, 255, 255, 0.3);
}
.plush-btn:active .plush-btn__icon {
transform: translateX(0.02em) scale(0.98);
opacity: 0.9;
}
/* Focus: clear high-contrast ring */
.plush-btn:focus-visible {
box-shadow: var(--btn-ring), var(--btn-shadow), var(--btn-inset-hi),
var(--btn-inset-lo);
}
/* Disabled state */
.plush-btn:disabled,
.plush-btn[aria-disabled="true"] {
opacity: 0.6;
cursor: not-allowed;
filter: grayscale(10%);
transform: none;
}
/* Motion preference */
@media (prefers-reduced-motion: reduce) {
.plush-btn,
.plush-btn .plush-btn__icon,
.plush-btn .plush-btn__inner {
transition: none;
}
}
/* Optional variant examples (still scoped) */
.plush-btn[data-variant="mint"] {
--btn-h: 162;
--btn-s: 55%;
--btn-l: 42%;
}
.plush-btn[data-variant="sun"] {
--btn-h: 38;
--btn-s: 90%;
--btn-l: 48%;
}