پیش‌نمایش زنده
کد HTML
<div class="stat-widget" aria-hidden="false">
  <button class="stat-pill variant-green" aria-label="67 percent sales by day">
    <div class="ring-wrap" aria-hidden="true">
      <div class="ring" role="presentation">
        <div class="core"></div>
      </div>
    </div>
    <div class="meta">
      <div class="value">67%</div>
      <div class="label">Sales by Day</div>
    </div>
    <span class="ground-shadow" aria-hidden="true"></span>
  </button>

  <button class="stat-pill variant-pink" aria-label="$234 sales by day">
    <div class="ring-wrap" aria-hidden="true">
      <div class="ring" role="presentation">
        <div class="core"></div>
      </div>
    </div>
    <div class="meta">
      <div class="value">$ 234</div>
      <div class="label">Sales by Day</div>
    </div>
    <span class="ground-shadow" aria-hidden="true"></span>
  </button>
</div>
کد CSS
/* Entire component scoped under .stat-widget to avoid global selectors */
.stat-widget {
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: 28px;
  min-height: 140px;
  align-items: center;
  justify-content: center;
  font-family:
    Inter,
    system-ui,
    -apple-system,
    "Segoe UI",
    Roboto,
    "Helvetica Neue",
    Arial;
  perspective: 900px; /* gives 3D depth for children */
}

.stat-widget .stat-pill {
  width: 320px;
  height: 96px;
  border-radius: 48px;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.03),
    rgba(255, 255, 255, 0.01)
  );
  box-shadow:
    0 8px 18px rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.02);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 20px;
  position: relative;
  transform-style: preserve-3d;
  transition:
    transform 300ms cubic-bezier(0.2, 0.9, 0.3, 1),
    box-shadow 300ms;
  cursor: pointer;
  user-select: none;
  border: none;
  outline: none;
  background-clip: padding-box;
}

.stat-widget .stat-pill:before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 6px;
  height: 36px;
  border-radius: 48px 48px 0 0;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.03),
    rgba(255, 255, 255, 0)
  );
  pointer-events: none;
  mix-blend-mode: overlay;
}

.stat-widget .ring-wrap {
  width: 64px;
  height: 64px;
  position: relative;
  flex: 0 0 64px;
  transform-style: preserve-3d;
}

/* Ring has a rotating transform to simulate fill animation (CSS-only) */
.stat-widget .ring {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  display: grid;
  place-items: center;
  box-shadow:
    0 6px 12px rgba(0, 0, 0, 0.4),
    inset 0 -6px 18px rgba(0, 0, 0, 0.35);
  transform-origin: 50% 50%;
  transition: transform 350ms cubic-bezier(0.2, 0.9, 0.3, 1);
  will-change: transform;
  /* animation: rotateIn to give impression of progress filling */
  animation: ringRotate 900ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}

.stat-widget .ring .core {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  display: grid;
  place-items: center;
  color: #fff;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: -0.02em;
  box-shadow:
    0 2px 6px rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.02);
}

.stat-widget .meta {
  color: #e9eef9;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  transform: translateZ(6px);
}
.stat-widget .meta .value {
  font-size: 20px;
  font-weight: 700;
  line-height: 1;
}
.stat-widget .meta .label {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.65);
  font-weight: 500;
}

/* ground shadow for 3D depth */
.stat-widget .stat-pill .ground-shadow {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: -12px;
  height: 14px;
  border-radius: 50%;
  filter: blur(18px);
  opacity: 0.45;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.35));
  transform: translateZ(-40px);
  transition: opacity 220ms;
}

.stat-widget .stat-pill:hover .ground-shadow {
  opacity: 0.9;
}

/* hover/active tilt purely with CSS to create 3D interaction */
.stat-widget .stat-pill:hover {
  transform: translateY(-10px) rotateX(6deg) rotateY(8deg) scale(1.01);
  box-shadow: 0 18px 40px rgba(2, 6, 23, 0.6);
}
.stat-widget .stat-pill:active {
  transform: translateY(-4px) rotateX(2deg) rotateY(3deg) scale(0.995);
  transition-duration: 120ms;
}

.stat-widget .stat-pill:focus {
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
}

/* subtle breathing animation for the pill itself */
@keyframes floaty {
  0% {
    transform: translateY(0) translateZ(0);
  }
  50% {
    transform: translateY(-4px) translateZ(4px);
  }
  100% {
    transform: translateY(0) translateZ(0);
  }
}
.stat-widget .stat-pill {
  animation: floaty 4200ms ease-in-out infinite;
}

/* ring rotate animation to simulate fill */
@keyframes ringRotate {
  0% {
    transform: rotate(-120deg);
  }
  70% {
    transform: rotate(8deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

/* color variants: the conic-gradient is hard-coded to show a desired percentage
       67% => angle 241.2deg (67*3.6)
       72% => angle 259.2deg (72*3.6)
    */

.stat-widget .stat-pill.variant-green .ring {
  background-image: conic-gradient(
    #2ee6a6 0deg,
    #2ee6a6 241.2deg,
    rgba(255, 255, 255, 0.06) 241.2deg 360deg
  );
}

.stat-widget .stat-pill.variant-pink .ring {
  background-image: conic-gradient(
    #ff6ad5 0deg,
    #ff6ad5 259.2deg,
    rgba(255, 255, 255, 0.06) 259.2deg 360deg
  );
}

/* place core text centrally and ensure percentage formatting */
.stat-widget .stat-pill .core-percent {
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}

/* responsive tweak for narrow screens */
@media (max-width: 360px) {
  .stat-widget {
    padding: 18px;
  }
  .stat-widget .stat-pill {
    width: 280px;
    height: 92px;
  }
  .stat-widget .ring-wrap {
    width: 58px;
    height: 58px;
  }
  .stat-widget .ring .core {
    width: 42px;
    height: 42px;
  }
}
نوع: button
تاریخ ایجاد: 2026/06/05
آخرین بروزرسانی: 2026/06/05