🐐
This commit is contained in:
@@ -54,7 +54,6 @@
|
||||
<!-- HERO -->
|
||||
<section id="home" class="hero">
|
||||
<div class="hero-content">
|
||||
<p class="hero-greeting">// Hello, world. I'm</p>
|
||||
<h1 class="hero-name" >Nikolaj Gade</h1>
|
||||
<p class="hero-role">Software Developer</p>
|
||||
<p class="hero-pronouns">they/them · he/him</p>
|
||||
|
||||
51
script.js
51
script.js
@@ -1,14 +1,55 @@
|
||||
// ── Hero typewriter ────────────────────────────────────────────
|
||||
function startHeroTypewriter(nameEl, fullName, restEls) {
|
||||
const cursor = document.createElement('span');
|
||||
cursor.className = 'hero-cursor';
|
||||
nameEl.appendChild(cursor);
|
||||
|
||||
let i = 0;
|
||||
function typeNext() {
|
||||
if (i < fullName.length) {
|
||||
nameEl.insertBefore(document.createTextNode(fullName[i]), cursor);
|
||||
i++;
|
||||
setTimeout(typeNext, 95);
|
||||
} else {
|
||||
// Cursor done — fade it out, then reveal the rest
|
||||
cursor.style.transition = 'opacity 0.3s';
|
||||
cursor.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
cursor.remove();
|
||||
restEls.forEach((el, idx) => {
|
||||
setTimeout(() => el.classList.add('visible'), idx * 110);
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
typeNext();
|
||||
}
|
||||
|
||||
// ── Loader ────────────────────────────────────────────────────
|
||||
(function () {
|
||||
const loader = document.getElementById('loader');
|
||||
const pctEl = document.getElementById('loaderPct');
|
||||
const loader = document.getElementById('loader');
|
||||
const pctEl = document.getElementById('loaderPct');
|
||||
const nameEl = document.querySelector('.hero-name');
|
||||
const restEls = [...document.querySelectorAll('.hero-role, .hero-pronouns, .hero-links, .hero-visual')];
|
||||
|
||||
// Store the name and clear it immediately (loader covers the page anyway)
|
||||
const fullName = nameEl.textContent.trim();
|
||||
nameEl.textContent = '';
|
||||
|
||||
// Hide hero elements that reveal after typing
|
||||
restEls.forEach(el => el.classList.add('fade-up'));
|
||||
|
||||
let pct = 0;
|
||||
const tick = setInterval(() => {
|
||||
pct += Math.random() * 20;
|
||||
pct += Math.random() * 15;
|
||||
if (pct >= 100) {
|
||||
pct = 100;
|
||||
clearInterval(tick);
|
||||
setTimeout(() => loader.classList.add('hide'), 300);
|
||||
setTimeout(() => {
|
||||
loader.classList.add('hide');
|
||||
// Wait for the loader fade-out (0.6s), then start typing
|
||||
setTimeout(() => startHeroTypewriter(nameEl, fullName, restEls), 600);
|
||||
}, 300);
|
||||
}
|
||||
pctEl.textContent = Math.floor(pct) + '%';
|
||||
}, 110);
|
||||
@@ -166,7 +207,7 @@
|
||||
(function () {
|
||||
const targets = document.querySelectorAll(
|
||||
'.section-header, .about-grid, .skill-card, .timeline-item, ' +
|
||||
'.project-card, .edu-card, .hero-content, .hero-visual'
|
||||
'.project-card, .edu-card'
|
||||
);
|
||||
targets.forEach(el => el.classList.add('fade-up'));
|
||||
|
||||
|
||||
21
style.css
21
style.css
@@ -71,7 +71,7 @@ button { font-family: var(--font); cursor: pointer; border: none; background: no
|
||||
@keyframes lcFade { to { opacity: 1; transform: none; } }
|
||||
|
||||
.loader-bar-wrap { width: 200px; height: 3px; background: rgba(255,255,255,0.1); border-radius: 99px; margin: 0 auto 0.75rem; overflow: hidden; }
|
||||
.loader-bar { height: 100%; background: var(--grad); width: 0%; animation: barFill 2.2s var(--ease) forwards; animation-delay: 0.5s; }
|
||||
.loader-bar { height: 100%; background: var(--grad); width: 0%; animation: barFill 2.5s var(--ease) forwards; animation-delay: 0.5s; }
|
||||
@keyframes barFill { to { width: 100%; } }
|
||||
.loader-pct { font-family: var(--mono); font-size: 0.8rem; color: var(--orange); }
|
||||
|
||||
@@ -165,11 +165,27 @@ main { position: relative; z-index: 1; }
|
||||
.fade-up { opacity: 0; transform: translateY(28px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
|
||||
.fade-up.visible { opacity: 1; transform: none; }
|
||||
|
||||
/* Hero typewriter cursor */
|
||||
.hero-cursor {
|
||||
display: inline-block;
|
||||
width: 5px;
|
||||
height: 0.8em;
|
||||
background: var(--ink);
|
||||
margin-left: 5px;
|
||||
vertical-align: baseline;
|
||||
border-radius: 1px;
|
||||
animation: cursorBlink 0.7s step-end infinite;
|
||||
}
|
||||
@keyframes cursorBlink {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0; }
|
||||
}
|
||||
|
||||
/* ── Hero ───────────────────────────────────────────────────── */
|
||||
.hero {
|
||||
min-height: 100vh;
|
||||
display: flex; align-items: center;
|
||||
padding: calc(var(--nav-h) + 1rem) 2rem 15rem;
|
||||
padding: calc(var(--nav-h) + 1rem) 2rem 10rem;
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto 250px auto;
|
||||
gap: 4rem;
|
||||
@@ -184,6 +200,7 @@ main { position: relative; z-index: 1; }
|
||||
font-weight: 900;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.03em;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
.hero-role {
|
||||
|
||||
Reference in New Issue
Block a user