A recreation of the amazing hover effect found here: https://linear.app/features
A Pen by Hyperplexed on CodePen.
| <div id="cards"> | |
| <div class="card"> | |
| <div class="card-content"> | |
| <div class="card-image"> | |
| <i class="fa-duotone fa-apartment"></i> | |
| </div> | |
| <div class="card-info-wrapper"> | |
| <div class="card-info"> | |
| <i class="fa-duotone fa-apartment"></i> | |
| <div class="card-info-title"> | |
| <h3>Apartments</h3> | |
| <h4>Places to be apart. Wait, what?</h4> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-content"> | |
| <div class="card-image"> | |
| <i class="fa-duotone fa-unicorn"></i> | |
| </div> | |
| <div class="card-info-wrapper"> | |
| <div class="card-info"> | |
| <i class="fa-duotone fa-unicorn"></i> | |
| <div class="card-info-title"> | |
| <h3>Unicorns</h3> | |
| <h4>A single corn. Er, I mean horn.</h4> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-content"> | |
| <div class="card-image"> | |
| <i class="fa-duotone fa-blender-phone"></i> | |
| </div> | |
| <div class="card-info-wrapper"> | |
| <div class="card-info"> | |
| <i class="fa-duotone fa-blender-phone"></i> | |
| <div class="card-info-title"> | |
| <h3>Blender Phones</h3> | |
| <h4>These absolutely deserve to exist.</h4> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-content"> | |
| <div class="card-image"> | |
| <i class="fa-duotone fa-person-to-portal"></i> | |
| </div> | |
| <div class="card-info-wrapper"> | |
| <div class="card-info"> | |
| <i class="fa-duotone fa-person-to-portal"></i> | |
| <div class="card-info-title"> | |
| <h3>Adios</h3> | |
| <h4>See you...</h4> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-content"> | |
| <div class="card-image"> | |
| <i class="fa-duotone fa-person-from-portal"></i> | |
| </div> | |
| <div class="card-info-wrapper"> | |
| <div class="card-info"> | |
| <i class="fa-duotone fa-person-from-portal"></i> | |
| <div class="card-info-title"> | |
| <h3>I mean hello</h3> | |
| <h4>...over here.</h4> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-content"> | |
| <div class="card-image"> | |
| <i class="fa-duotone fa-otter"></i> | |
| </div> | |
| <div class="card-info-wrapper"> | |
| <div class="card-info"> | |
| <i class="fa-duotone fa-otter"></i> | |
| <div class="card-info-title"> | |
| <h3>Otters</h3> | |
| <h4>Look at me, imma cute lil fella.</h4> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <a id="source-link" class="link" href="https://linear.app/features" target="_blank"> | |
| <i class="fa-solid fa-link"></i> | |
| <span class="roboto-mono">Source</span> | |
| </a> | |
| <a id="youtube-link" class="link" href="https://youtu.be/htGfnF1zN4g" target="_blank"> | |
| <i class="fa-brands fa-youtube"></i> | |
| <span>5 min Tutorial</span> | |
| </a> |
A recreation of the amazing hover effect found here: https://linear.app/features
A Pen by Hyperplexed on CodePen.
| document.getElementById("cards").onmousemove = e => { | |
| for(const card of document.getElementsByClassName("card")) { | |
| const rect = card.getBoundingClientRect(), | |
| x = e.clientX - rect.left, | |
| y = e.clientY - rect.top; | |
| card.style.setProperty("--mouse-x", `${x}px`); | |
| card.style.setProperty("--mouse-y", `${y}px`); | |
| }; | |
| } |
| <script src="https://codepen.io/Hyperplexed/pen/xxYJYjM/54407644e24173ad6019b766443bf2a6.js"></script> |
| :root { | |
| --bg-color: rgb(20, 20, 20); | |
| --card-color: rgb(23, 23, 23); | |
| } | |
| body { | |
| align-items: center; | |
| background-color: var(--bg-color); | |
| display: flex; | |
| height: 100vh; | |
| justify-content: center; | |
| margin: 0px; | |
| overflow: hidden; | |
| padding: 0px; | |
| } | |
| #cards { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 8px; | |
| max-width: 916px; | |
| width: calc(100% - 20px); | |
| } | |
| #cards:hover > .card::after { | |
| opacity: 1; | |
| } | |
| .card { | |
| background-color: rgba(255, 255, 255, 0.1); | |
| border-radius: 10px; | |
| cursor: pointer; | |
| display: flex; | |
| height: 260px; | |
| flex-direction: column; | |
| position: relative; | |
| width: 300px; | |
| } | |
| .card:hover::before { | |
| opacity: 1; | |
| } | |
| .card::before, | |
| .card::after { | |
| border-radius: inherit; | |
| content: ""; | |
| height: 100%; | |
| left: 0px; | |
| opacity: 0; | |
| position: absolute; | |
| top: 0px; | |
| transition: opacity 500ms; | |
| width: 100%; | |
| } | |
| .card::before { | |
| background: radial-gradient( | |
| 800px circle at var(--mouse-x) var(--mouse-y), | |
| rgba(255, 255, 255, 0.06), | |
| transparent 40% | |
| ); | |
| z-index: 3; | |
| } | |
| .card::after { | |
| background: radial-gradient( | |
| 600px circle at var(--mouse-x) var(--mouse-y), | |
| rgba(255, 255, 255, 0.4), | |
| transparent 40% | |
| ); | |
| z-index: 1; | |
| } | |
| .card > .card-content { | |
| background-color: var(--card-color); | |
| border-radius: inherit; | |
| display: flex; | |
| flex-direction: column; | |
| flex-grow: 1; | |
| inset: 1px; | |
| padding: 10px; | |
| position: absolute; | |
| z-index: 2; | |
| } | |
| /* -- ↓ ↓ ↓ extra card content styles ↓ ↓ ↓ -- */ | |
| h1, h2, h3, h4, span { | |
| color: rgb(240, 240, 240); | |
| font-family: "Rubik", sans-serif; | |
| font-weight: 400; | |
| margin: 0px; | |
| } | |
| i { | |
| color: rgb(240, 240, 240); | |
| } | |
| .card-image { | |
| align-items: center; | |
| display: flex; | |
| height: 140px; | |
| justify-content: center; | |
| overflow: hidden; | |
| } | |
| .card-image > i { | |
| font-size: 6em; | |
| opacity: 0.25; | |
| } | |
| .card-info-wrapper { | |
| align-items: center; | |
| display: flex; | |
| flex-grow: 1; | |
| justify-content: flex-start; | |
| padding: 0px 20px; | |
| } | |
| .card-info { | |
| align-items: flex-start; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .card-info > i { | |
| font-size: 1em; | |
| height: 20px; | |
| line-height: 20px; | |
| } | |
| .card-info-title > h3 { | |
| font-size: 1.1em; | |
| line-height: 20px; | |
| } | |
| .card-info-title > h4 { | |
| color: rgba(255, 255, 255, 0.5); | |
| font-size: 0.85em; | |
| margin-top: 8px; | |
| } | |
| /* -- ↓ ↓ ↓ some responsiveness ↓ ↓ ↓ -- */ | |
| @media(max-width: 1000px) { | |
| body { | |
| align-items: flex-start; | |
| overflow: auto; | |
| } | |
| #cards { | |
| max-width: 1000px; | |
| padding: 10px 0px; | |
| } | |
| .card { | |
| flex-shrink: 1; | |
| width: calc(50% - 4px); | |
| } | |
| } | |
| @media(max-width: 500px) { | |
| .card { | |
| height: 180px; | |
| } | |
| .card-image { | |
| height: 80px; | |
| } | |
| .card-image > i { | |
| font-size: 3em; | |
| } | |
| .card-info-wrapper { | |
| padding: 0px 10px; | |
| } | |
| .card-info > i { | |
| font-size: 0.8em; | |
| } | |
| .card-info-title > h3 { | |
| font-size: 0.9em; | |
| } | |
| .card-info-title > h4 { | |
| font-size: 0.8em; | |
| margin-top: 4px; | |
| } | |
| } | |
| @media(max-width: 320px) { | |
| .card { | |
| width: 100%; | |
| } | |
| } | |
| /* -- ↓ ↓ ↓ YouTube link styles ↓ ↓ ↓ -- */ | |
| #youtube-link { | |
| bottom: 10px; | |
| } | |
| #youtube-link > i { | |
| color: rgb(239, 83, 80); | |
| } | |
| #source-link { | |
| bottom: 60px; | |
| } | |
| #source-link > i { | |
| color: rgb(94, 106, 210); | |
| } | |
| .link { | |
| align-items: center; | |
| backdrop-filter: blur(3px); | |
| background-color: rgba(255, 255, 255, 0.05); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| border-radius: 6px; | |
| box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); | |
| cursor: pointer; | |
| display: inline-flex; | |
| gap: 5px; | |
| left: 10px; | |
| padding: 10px 20px; | |
| position: fixed; | |
| text-decoration: none; | |
| z-index: 100; | |
| } | |
| .link:hover { | |
| background-color: rgba(255, 255, 255, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .link > i, .link > span { | |
| height: 20px; | |
| line-height: 20px; | |
| } | |
| .link > span { | |
| color: white; | |
| } |