There is something undeniably cool about the Cyberpunk aesthetic. The neon lights and high-tech vibe scream future. In this tutorial, we will build a Cyberpunk Glitch Card that feels like it was ripped straight out of a sci-fi game UI.
The result? A 3D Interactive Profile Card that reacts to your mouse movement and features a jagged, glitching text animation.
In this tutorial, I’m going to show you exactly how I built it. We will use CSS clip-path for the angled corners and a few lines of JavaScript for that smooth 3D tilt effect.
Why Build a Cyberpunk Glitch Card?
This isn't just a static image. Here is what makes this card special:
Holographic Glitch Text: I used CSS keyframes and the clip property to make the text look like it's malfunctioning.
3D Tilt Effect: The card follows your mouse cursor in a 3D space.
Angled UI: Using clip-path, we cut the corners of the card to give it that sharp, industrial sci-fi look.
*The Source Code
*
You can copy-paste the code below to use this card in your own portfolio or project.
Below is the complete source code for the Cyberpunk Glitch Card. You can copy-paste it directly into your project.
- The HTML Structure We need a container for the 3D perspective and a wrapper for the glitch effect on the avatar. Notice the data-text attribute on the title—that's the secret to the glitch effect!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cyberpunk Glitch Card</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="card" id="cyber-card">
<div class="card-content">
<div class="glitch-wrapper">
<img src="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?q=80&w=1000" alt="Cyber Avatar" class="avatar">
<div class="glitch-effect"></div>
</div>
<h2 class="cyber-title" data-text="ALEX_MERCER">ALEX_MERCER</h2>
<p class="cyber-role">SYSTEM_ARCHITECT // LVL.99</p>
<div class="stats">
<div class="stat-box">
<span class="label">SPEED</span>
<span class="value">98%</span>
</div>
<div class="stat-box">
<span class="label">HACK</span>
<span class="value">100%</span>
</div>
<div class="stat-box">
<span class="label">STEALTH</span>
<span class="value">85%</span>
</div>
</div>
<button class="cyber-btn">INITIALIZE <i class="fas fa-bolt"></i></button>
</div>
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
</div>
</div>
</body>
</html>
- The CSS (The Magic) This is where the heavy lifting happens. I used CSS variables for the Neon Cyan and Pink colors so you can easily change the theme. The @keyframes glitch-anim handles the text distortion.
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Share+Tech+Mono&display=swap'); :root { --primary: #00f3ff; /* Cyan Neon */ --secondary: #ff0055; /* Pink Neon */ --bg: #050505; --card-bg: #111; } * { box-sizing: border-box; margin: 0; padding: 0; } body { background-color: var(--bg); /* Grid Background Pattern */ background-image: linear-gradient(rgba(0, 243, 255, 0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(0, 243, 255, 0.03) 1px, transparent 1px); background-size: 30px 30px; height: 100vh; display: flex; justify-content: center; align-items: center; font-family: 'Share Tech Mono', monospace; overflow: hidden; } .container { perspective: 1000px; } .card { width: 350px; padding: 40px 30px; background: var(--card-bg); border: 1px solid rgba(0, 243, 255, 0.2); position: relative; transform-style: preserve-3d; cursor: pointer; box-shadow: 0 0 20px rgba(0, 243, 255, 0.1); /* Angled corners using clip-path */ clip-path: polygon( 0 0, 100% 0, 100% 85%, 90% 100%, 0 100% ); } /* --- Avatar & Glitch --- */ .glitch-wrapper { width: 120px; height: 120px; margin: 0 auto 20px; position: relative; } .avatar { width: 100%; height: 100%; object-fit: cover; border: 2px solid var(--primary); filter: grayscale(100%); transition: 0.3s; } .card:hover .avatar { filter: grayscale(0%); border-color: var(--secondary); } /* --- Typography --- */ .cyber-title { font-family: 'Orbitron', sans-serif; color: #fff; text-align: center; font-size: 1.8rem; margin-bottom: 5px; position: relative; letter-spacing: 2px; } /* Glitch Text Effect */ .cyber-title::before, .cyber-title::after { content: attr(data-text); position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: var(--card-bg); } .cyber-title::before { left: 2px; text-shadow: -1px 0 var(--secondary); clip: rect(24px, 550px, 90px, 0); animation: glitch-anim-2 3s infinite linear alternate-reverse; } .cyber-title::after { left: -2px; text-shadow: -1px 0 var(--primary); clip: rect(85px, 550px, 140px, 0); animation: glitch-anim 2.5s infinite linear alternate-reverse; } .cyber-role { text-align: center; color: var(--primary); font-size: 0.9rem; margin-bottom: 30px; opacity: 0.8; } /* --- Stats Grid --- */ .stats { display: flex; justify-content: space-between; margin-bottom: 30px; border-top: 1px solid rgba(255,255,255,0.1); border-bottom: 1px solid rgba(255,255,255,0.1); padding: 15px 0; } .stat-box { text-align: center; } .stat-box .label { display: block; font-size: 0.7rem; color: #888; margin-bottom: 5px; } .stat-box .value { font-size: 1.1rem; color: #fff; font-weight: bold; } /* --- Button --- */ .cyber-btn { width: 100%; padding: 15px; background: transparent; border: 1px solid var(--primary); color: var(--primary); font-family: 'Orbitron', sans-serif; font-weight: bold; letter-spacing: 2px; cursor: pointer; position: relative; overflow: hidden; transition: 0.3s; } .cyber-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: var(--primary); transition: 0.3s; z-index: -1; } .cyber-btn:hover { color: #000; box-shadow: 0 0 15px var(--primary); } .cyber-btn:hover::before { left: 0; } /* --- Decorative Corners --- */ .corner { position: absolute; width: 10px; height: 10px; border: 2px solid var(--primary); transition: 0.3s; } .top-left { top: -2px; left: -2px; border-right: none; border-bottom: none; } .top-right { top: -2px; right: -2px; border-left: none; border-bottom: none; } .bottom-left { bottom: -2px; left: -2px; border-right: none; border-top: none; } .bottom-right { bottom: -2px; right: -2px; border-left: none; border-top: none; width: 20px; border-color: var(--secondary); } .card:hover .corner { width: 100%; height: 100%; opacity: 0.1; } /* --- Keyframes --- */ @keyframes glitch-anim { 0% { clip: rect(10px, 9999px, 30px, 0); transform: skew(0.5deg); } 10% { clip: rect(50px, 9999px, 70px, 0); transform: skew(0.2deg); } 20% { clip: rect(20px, 9999px, 60px, 0); transform: skew(0.8deg); } 100% { clip: rect(80px, 9999px, 100px, 0); transform: skew(0.1deg); } } @keyframes glitch-anim-2 { 0% { clip: rect(60px, 9999px, 80px, 0); transform: skew(0.6deg); } 10% { clip: rect(10px, 9999px, 30px, 0); transform: skew(0.3deg); } 100% { clip: rect(90px, 9999px, 100px, 0); transform: skew(0.1deg); } }
- The JavaScript (The Interaction) We don't need a heavy library like Three.js here. A simple event listener tracking the xAxis and yAxis of the mouse is enough to create a realistic tilt.
const card = document.getElementById('cyber-card'); document.addEventListener('mousemove', (e) => { let xAxis = (window.innerWidth / 2 - e.pageX) / 20; let yAxis = (window.innerHeight / 2 - e.pageY) / 20; card.style.transform = `rotateY(${xAxis}deg) rotateX(${yAxis}deg)`; }); card.addEventListener('mouseenter', () => { card.style.transition = 'none'; }); card.addEventListener('mouseleave', () => { card.style.transition = 'all 0.5s ease'; card.style.transform = `rotateY(0deg) rotateX(0deg)`; });
How the "Glitch" Works
If you look at the CSS for .cyber-title, you will see I used ::before and ::after pseudo-elements. These elements contain the exact same text as the title (grabbed via attr(data-text)).
By positioning them slightly apart and animating their clip property rapidly, we create the illusion that the text is splitting and twitching. It’s a classic trick, but it works perfectly for this style.
Conclusion
Building UI components like this is a great way to practice modern CSS properties like clip-path and transform-style. Plus, it looks awesome on a developer portfolio!
Feel free to grab the code, change the colors, and make it your own. If you build something cool with it, tag me—I’d love to see it.
Happy Coding! 👾

Top comments (0)