Back to CSS Card Hover Effects Grain Texture Pure CSS
Share
HTML
<div class="card-20">
  <div class="card-20__noise"></div>
  <span class="card-20__tag">Texture</span>
  <h4 class="card-20__title">Grain Texture</h4>
  <p class="card-20__body">Film grain animates over the surface on hover.</p>
</div>
CSS
.card-20__tag {
  font-family: monospace;
  font-size: 10px;
  padding: 2px 8px;
  border-radius: 20px;
  background: rgba(124, 108, 255, 0.15);
  color: #7c6cff;
  border: 1px solid rgba(124, 108, 255, 0.3);
  display: inline-block;
  margin-bottom: 10px;
}
.card-20__title {
  font-size: 17px;
  font-weight: 700;
  color: #f0eeff;
  margin-bottom: 6px;
}
.card-20__body {
  font-size: 13px;
  color: #b8b6d4;
  line-height: 1.6;
}
.card-20 {
  width: 100%;
  max-width: 280px;
  position: relative;
  overflow: hidden;
  padding: 22px;
  border-radius: 14px;
  background: linear-gradient(135deg, #1a1228, #0d0d1a);
  border: 1px solid rgba(255, 255, 255, 0.08);
  cursor: pointer;
  transition:
    box-shadow 0.35s,
    transform 0.35s cubic-bezier(0.23, 1, 0.32, 1);
}
.card-20:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 42px rgba(0, 0, 0, 0.55);
}
.card-20__noise {
  position: absolute;
  inset: -50%;
  width: 200%;
  height: 200%;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
  opacity: 0;
  mix-blend-mode: overlay;
  pointer-events: none;
  transition: opacity 0.4s;
  animation: card-20-grain 6s steps(1) infinite paused;
}
.card-20:hover .card-20__noise {
  opacity: 0.45;
  animation-play-state: running;
}
@keyframes card-20-grain {
  0% { transform: translate(0, 0); }
  10% { transform: translate(-3%, -4%); }
  20% { transform: translate(2%, 3%); }
  30% { transform: translate(-4%, 2%); }
  40% { transform: translate(3%, -3%); }
  50% { transform: translate(-2%, 4%); }
  60% { transform: translate(4%, -2%); }
  70% { transform: translate(-3%, 3%); }
  80% { transform: translate(2%, -4%); }
  90% { transform: translate(-4%, -2%); }
  100% { transform: translate(0, 0); }
}
.card-20__tag,
.card-20__title,
.card-20__body {
  position: relative;
  z-index: 1;
}