This post is a detailed guide on how to implement a fascinating glowy card hover effect on your website. By leveraging HTML, CSS, and JavaScript, you’ll learn to craft an engaging interaction that enchants users when they interact with your content.
The tutorial focuses on the step-by-step process of creating these glowing cards. It begins with structuring your content using HTML, defining the cards you want to highlight. Then, using CSS, you’ll add styles and animations that bring these cards to life, emitting a subtle yet mesmerizing glow when users hover over them.
The aim here is to elevate your website’s user experience by adding a touch of magic. This effect captivates attention and draws users to interact more with your content, making your cards stand out in a visually appealing and enchanting way.
HTML :
This HTML code sets up a webpage displaying a pricing section with three subscription tiers: Basic, Pro, and Ultimate. It structures the content using headings, prices, feature lists, and call-to-action links within <div>
elements. The <main>
section holds the primary content, and classes like .main__cards
and .cards__card
likely denote styling details for these elements
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <title>Glowy Card Hover Effect | Coding Stella</title> <link rel="stylesheet" href="./style.css"> </head> <body> <main class="main flow"> <h1 class="main__heading">Pricing</h1> <div class="main__cards cards"> <div class="cards__inner"> <div class="cards__card card"> <h2 class="card__heading">Basic</h2> <p class="card__price">$9.99</p> <ul role="list" class="card__bullets flow"> <li>Access to standard workouts and nutrition plans</li> <li>Email support</li> </ul> <a href="#basic" class="card__cta cta">Get Started</a> </div> <div class="cards__card card"> <h2 class="card__heading">Pro</h2> <p class="card__price">$19.99</p> <ul role="list" class="card__bullets flow"> <li>Access to advanced workouts and nutrition plans</li> <li>Priority Email support</li> <li>Exclusive access to live Q&A sessions</li> </ul> <a href="#pro" class="card__cta cta">Upgrade to Pro</a> </div> <div class="cards__card card"> <h2 class="card__heading">Ultimate</h2> <p class="card__price">$29.99</p> <ul role="list" class="card__bullets flow"> <li>Access to all premium workouts and nutrition plans</li> <li>24/7 Priority support</li> <li>1-on-1 virtual coaching session every month</li> <li>Exclusive content and early access to new features</li> </ul> <a href="#ultimate" class="card__cta cta">Go Ultimate</a> </div> </div> <div class="overlay cards__inner"></div> </div> </main> </body> </html>
CSS :
This CSS code defines the styles for a pricing section with subscription cards. It sets up the layout, typography, and colors for the elements. The code uses Flexbox for card arrangement and defines variables to control the color schemes for each card tier. The card__bullets
class displays checkmark icons before list items using inline SVGs.
Additionally, it creates an overlay effect that appears on hover, adjusting the card’s background color and border when interacted with, enhancing the visual appeal and interactivity of the cards.
@import url("https://fonts.googleapis.com/css2?family=League+Spartan:wght@400;500;600;700;800;900&display=swap"); *, *::after, *::before { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; min-height: 100vh; } body { display: grid; place-items: center; font-family: "League Spartan", system-ui, sans-serif; font-size: 1.1rem; line-height: 1.2; background-color: #212121; color: #ddd; } ul { list-style: none; } .main { max-width: 75rem; padding: 3em 1.5em; } .main__heading { font-weight: 600; font-size: 2.25em; margin-bottom: 0.75em; text-align: center; color: #eceff1; } .cards { position: relative; } .cards__inner { display: flex; flex-wrap: wrap; gap: 2.5em; } .card { --flow-space: 0.5em; --hsl: var(--hue), var(--saturation), var(--lightness); flex: 1 1 14rem; padding: 1.5em 2em; display: grid; grid-template-rows: auto auto auto 1fr; align-items: start; gap: 1.25em; color: #eceff1; background-color: #2b2b2b; border: 1px solid #eceff133; border-radius: 15px; } .card:nth-child(1) { --hue: 165; --saturation: 82.26%; --lightness: 51.37%; } .card:nth-child(2) { --hue: 291.34; --saturation: 95.9%; --lightness: 61.76%; } .card:nth-child(3) { --hue: 338.69; --saturation: 100%; --lightness: 48.04%; } .card__bullets { line-height: 1.4; } .card__bullets li::before { display: inline-block; content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' width='16' title='check' fill='%23dddddd'%3E%3Cpath d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z' /%3E%3C/svg%3E"); transform: translatey(0.25ch); margin-right: 1ch; } .card__heading { font-size: 1.05em; font-weight: 600; } .card__price { font-size: 1.75em; font-weight: 700; } .flow > * + * { margin-top: var(--flow-space, 1.25em); } .cta { display: block; align-self: end; margin: 1em 0 0.5em 0; text-align: center; text-decoration: none; color: #fff; background-color: #0d0d0d; padding: 0.7em; border-radius: 10px; font-size: 1rem; font-weight: 600; } .overlay { position: absolute; inset: 0; pointer-events: none; user-select: none; opacity: var(--opacity, 0); -webkit-mask: radial-gradient( 25rem 25rem at var(--x) var(--y), #000 1%, transparent 50% ); mask: radial-gradient( 25rem 25rem at var(--x) var(--y), #000 1%, transparent 50% ); transition: 400ms mask ease; will-change: mask; } .overlay .card { background-color: hsla(var(--hsl), 0.15); border-color: hsla(var(--hsl), 1); box-shadow: 0 0 0 1px inset hsl(var(--hsl)); } .overlay .cta { display: block; grid-row: -1; width: 100%; background-color: hsl(var(--hsl)); box-shadow: 0 0 0 1px hsl(var(--hsl)); } :not(.overlay) > .card { transition: 400ms background ease; will-change: background; } :not(.overlay) > .card:hover { --lightness: 95%; background: hsla(var(--hsl), 0.1); }
JavaScript :
This JavaScript code adds interactivity to a pricing section with subscription cards. It tracks cursor movement within the card container, creating an overlay effect that mimics the cards’ positions and sizes. Functions like applyOverlayMask
adjust the overlay position based on cursor coordinates, while createOverlayCta
dynamically generates call-to-action elements within the overlay to mirror the original cards.
Using a ResizeObserver
, it ensures the overlay elements match the corresponding card dimensions, resulting in an interactive hover effect that dynamically adapts to user interaction within the pricing section.
console.clear(); const cardsContainer = document.querySelector(".cards"); const cardsContainerInner = document.querySelector(".cards__inner"); const cards = Array.from(document.querySelectorAll(".card")); const overlay = document.querySelector(".overlay"); const applyOverlayMask = (e) => { const overlayEl = e.currentTarget; const x = e.pageX - cardsContainer.offsetLeft; const y = e.pageY - cardsContainer.offsetTop; overlayEl.style = `--opacity: 1; --x: ${x}px; --y:${y}px;`; }; const createOverlayCta = (overlayCard, ctaEl) => { const overlayCta = document.createElement("div"); overlayCta.classList.add("cta"); overlayCta.textContent = ctaEl.textContent; overlayCta.setAttribute("aria-hidden", true); overlayCard.append(overlayCta); }; const observer = new ResizeObserver((entries) => { entries.forEach((entry) => { const cardIndex = cards.indexOf(entry.target); let width = entry.borderBoxSize[0].inlineSize; let height = entry.borderBoxSize[0].blockSize; if (cardIndex >= 0) { overlay.children[cardIndex].style.width = `${width}px`; overlay.children[cardIndex].style.height = `${height}px`; } }); }); const initOverlayCard = (cardEl) => { const overlayCard = document.createElement("div"); overlayCard.classList.add("card"); createOverlayCta(overlayCard, cardEl.lastElementChild); overlay.append(overlayCard); observer.observe(cardEl); }; cards.forEach(initOverlayCard); document.body.addEventListener("pointermove", applyOverlayMask);
In short, we’ve made glowing cards using HTML, CSS, and JavaScript. HTML sets up the cards, CSS makes them glow, and JavaScript adds the hover effect. Now, it’s your turn to play around and give them your personal touch!
If you encounter any difficulties while working on your glowing cards, fear not. You can freely obtain the source code files for this project. Simply click the Download button to kickstart your journey. Enjoy coding!