-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathResPortfolio.html
More file actions
391 lines (346 loc) · 16.1 KB
/
ResPortfolio.html
File metadata and controls
391 lines (346 loc) · 16.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Responsive portfolio template - customizable and forkable" />
<title>Your Name — Portfolio</title>
<style>
/* -----------------------------
CSS Variables & Reset
-----------------------------*/
:root{
--bg: #0f1724;
--card: #111827;
--muted: #9ca3af;
--text: #e6eef8;
--accent: #7c3aed;
--glass: rgba(255,255,255,0.03);
--radius: 14px;
--container: 1100px;
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
background: linear-gradient(180deg,var(--bg) 0%, #071026 100%);
color:var(--text);
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
line-height:1.5;
padding:24px 20px;
}
/* Container */
.wrap{max-width:var(--container);margin:0 auto}
/* NAV */
header{
display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:28px
}
.brand{display:flex;align-items:center;gap:12px}
.logo{width:44px;height:44px;border-radius:10px;background:linear-gradient(135deg,var(--accent),#06b6d4);display:flex;align-items:center;justify-content:center;font-weight:700}
nav{display:flex;gap:14px;align-items:center}
nav a{color:var(--muted);text-decoration:none;padding:8px;border-radius:8px}
nav a:hover{color:var(--text);background:var(--glass)}
.cta{background:var(--accent);color:white;padding:8px 12px;border-radius:10px;text-decoration:none}
/* mobile nav */
.hamburger{display:none;background:none;border:1px solid rgba(255,255,255,0.06);padding:8px;border-radius:8px}
/* HERO */
.hero{display:grid;grid-template-columns:1fr 360px;gap:28px;align-items:center;margin-bottom:32px}
.hero-card{background:linear-gradient(180deg, rgba(255,255,255,0.02), transparent);padding:26px;border-radius:var(--radius);box-shadow:0 6px 30px rgba(2,6,23,0.6)}
h1{margin:0;font-size:28px}
p.lead{color:var(--muted);margin-top:12px}
.socials{display:flex;gap:10px;margin-top:16px}
.socials a{color:var(--muted);text-decoration:none}
/* avatar */
.avatar{width:140px;height:140px;border-radius:12px;overflow:hidden;border:4px solid rgba(255,255,255,0.03)}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}
/* SECTIONS */
section{margin-bottom:28px}
.section-title{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.section-title h2{margin:0;font-size:18px}
.grid{display:grid;gap:16px}
/* Projects */
.projects{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
.project{background:var(--card);padding:16px;border-radius:12px;border:1px solid rgba(255,255,255,0.02);display:flex;flex-direction:column;gap:10px}
.project .thumb{height:130px;border-radius:10px;overflow:hidden;background:linear-gradient(90deg,#0b1220,#071431)}
.project h3{margin:0;font-size:16px}
.project p{margin:0;color:var(--muted);font-size:13px}
.tags{display:flex;gap:8px;flex-wrap:wrap}
.tag{font-size:12px;padding:6px 8px;border-radius:999px;background:rgba(255,255,255,0.03);color:var(--muted)}
.project .actions{margin-top:auto;display:flex;gap:8px}
/* Skills */
.skills{grid-template-columns:repeat(auto-fit,minmax(140px,1fr))}
.skill{background:var(--card);padding:10px;border-radius:10px;text-align:center}
/* Contact */
.contact-form{display:grid;gap:10px;grid-template-columns:1fr 1fr}
.contact-form input,.contact-form textarea{grid-column:span 2;padding:10px;border-radius:8px;border:1px solid rgba(255,255,255,0.04);background:transparent;color:var(--text)}
.contact-form input[type="email"],.contact-form input[type="text"]{height:42px}
.contact-form textarea{min-height:120px;resize:vertical}
.contact-form button{grid-column:span 2;padding:10px;border-radius:10px;border:none;background:var(--accent);color:white}
/* Footer */
footer{text-align:center;color:var(--muted);padding:18px}
/* Modal */
.modal{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(2,6,23,0.6);visibility:hidden;opacity:0;transition:all .18s}
.modal.show{visibility:visible;opacity:1}
.modal-inner{background:var(--card);padding:18px;border-radius:12px;max-width:880px;width:92%}
/* Responsive tweaks */
@media (max-width:900px){
.hero{grid-template-columns:1fr;}
.hero-card{order:2}
.avatar{width:120px;height:120px}
nav{display:none}
.hamburger{display:block}
.contact-form{grid-template-columns:1fr}
.contact-form input,.contact-form textarea, .contact-form button{grid-column:auto}
}
/* small devices */
@media (max-width:480px){
body{padding:18px 14px}
h1{font-size:22px}
}
/* simple focus styles */
a:focus,input:focus,button:focus{outline:3px solid rgba(124,58,237,0.18);outline-offset:2px}
</style>
</head>
<body>
<div class="wrap">
<header>
<div class="brand">
<div class="logo">YS</div>
<div>
<div style="font-weight:700">Your Name</div>
<div style="font-size:12px;color:var(--muted)">Frontend Developer • Open Source</div>
</div>
</div>
<nav aria-label="Main navigation">
<a href="#about">About</a>
<a href="#projects">Projects</a>
<a href="#skills">Skills</a>
<a href="#contact">Contact</a>
<a class="cta" href="#contact">Hire me</a>
</nav>
<button class="hamburger" aria-label="Open menu">☰</button>
</header>
<main>
<section class="hero">
<div class="hero-card">
<h1>Hi — I'm <span id="name">Your Name</span>.</h1>
<p class="lead">I build accessible, responsive web experiences. I specialize in frontend development with a focus on performance and clarity.</p>
<div class="socials" aria-hidden="false">
<a href="#" title="GitHub">GitHub</a>
<a href="#" title="Twitter">Twitter</a>
<a href="#" title="LinkedIn">LinkedIn</a>
</div>
<div style="margin-top:20px; display:flex; gap:12px; align-items:center;">
<a class="cta" href="#projects">See my work</a>
<button id="themeToggle" style="padding:8px;border-radius:8px;background:transparent;border:1px solid rgba(255,255,255,0.04);color:var(--text)">Toggle Theme</button>
</div>
<div style="margin-top:18px;color:var(--muted);font-size:13px">Quick tech: HTML • CSS • JavaScript</div>
</div>
<aside style="display:flex;flex-direction:column;gap:12px;align-items:center">
<div class="avatar">
<img src="https://images.unsplash.com/photo-1544005313-94ddf0286df2?q=80&w=800&auto=format&fit=crop&ixlib=rb-4.0.3&s=placeholder" alt="Your avatar">
</div>
<div style="text-align:center; color:var(--muted)">
<div style="font-weight:700">Location</div>
<div style="font-size:13px">City, Country</div>
</div>
</aside>
</section>
<section id="about">
<div class="section-title"><h2>About</h2></div>
<div class="hero-card">
<p>I’m a frontend developer who cares about clear UX, performance and maintainable code. I enjoy turning design ideas into delightful experiences and contributing to open source.</p>
<p style="color:var(--muted)">Tip: Fork this template and replace content (name, projects, images). The projects below are auto-generated from a small JS array — change them in the <code><script></code> at the bottom.</p>
</div>
</section>
<section id="projects">
<div class="section-title"><h2>Projects</h2></div>
<div class="grid projects" id="projectsGrid"></div>
</section>
<section id="skills">
<div class="section-title"><h2>Skills</h2></div>
<div class="grid skills">
<div class="skill">HTML & Semantics</div>
<div class="skill">CSS / Layouts</div>
<div class="skill">JavaScript (Vanilla)</div>
<div class="skill">Responsive Design</div>
<div class="skill">Accessibility (a11y)</div>
<div class="skill">Git & Open Source</div>
</div>
</section>
<section id="contact">
<div class="section-title"><h2>Contact</h2></div>
<div class="hero-card">
<form id="contactForm" class="contact-form" novalidate>
<input id="fullName" type="text" placeholder="Your full name" required />
<input id="email" type="email" placeholder="Email address" required />
<input id="subject" type="text" placeholder="Subject" />
<textarea id="message" placeholder="Message" required></textarea>
<button type="submit">Send message</button>
<div id="formMsg" style="grid-column:span 2;color:var(--muted);font-size:13px"></div>
</form>
</div>
</section>
</main>
<footer>
<div>© <span id="year"></span> Your Name — Built with ❤️. Fork and customize.</div>
</footer>
</div>
<!-- Modal for project details -->
<div class="modal" id="modal" role="dialog" aria-hidden="true">
<div class="modal-inner" role="document">
<button id="modalClose" style="float:right;background:none;border:none;color:var(--muted);font-size:18px">✕</button>
<div id="modalContent"></div>
</div>
</div>
<script>
// -----------------------------
// Basic interactive JS
// -----------------------------
document.getElementById('year').textContent = new Date().getFullYear();
// Projects data — replace or add your own projects here
const projects = [
{
id: 'p1',
title: 'Portfolio Template',
desc: 'A minimal, responsive portfolio template you can fork and personalize.',
img: 'https://images.unsplash.com/photo-1522202176988-66273c2fd55f?q=80&w=1200&auto=format&fit=crop&ixlib=rb-4.0.3&s=placeholder',
tags: ['HTML','CSS','JS'],
link: '#'
},
{
id: 'p2',
title: 'Open Data Visualizer',
desc: 'Dashboard that visualizes open datasets with charts and filters.',
img: 'https://images.unsplash.com/photo-1498050108023-c5249f4df085?q=80&w=1200&auto=format&fit=crop&ixlib=rb-4.0.3&s=placeholder',
tags: ['React','D3'],
link: '#'
},
{
id: 'p3',
title: 'Mini Habit Tracker',
desc: 'A small, local-storage based habit tracker with streaks and progress.',
img: 'https://images.unsplash.com/photo-1515879218367-8466d910aaa4?q=80&w=1200&auto=format&fit=crop&ixlib=rb-4.0.3&s=placeholder',
tags: ['Vanilla JS','LocalStorage'],
link: '#'
}
];
const projectsGrid = document.getElementById('projectsGrid');
function renderProjects(){
projectsGrid.innerHTML = '';
projects.forEach(p => {
const el = document.createElement('article');
el.className = 'project';
el.innerHTML = `
<div class="thumb" aria-hidden="true"><img style="width:100%;height:100%;object-fit:cover" src="${p.img}" alt="${p.title}"></div>
<h3>${p.title}</h3>
<p>${p.desc}</p>
<div class="tags">${p.tags.map(t => `<span class="tag">${t}</span>`).join('')}</div>
<div class="actions">
<a href="${p.link}" aria-label="Open project ${p.title}" style="text-decoration:none;padding:8px;border-radius:8px;border:1px solid rgba(255,255,255,0.04)">View</a>
<button data-id="${p.id}" style="padding:8px;border-radius:8px;border:none;background:var(--accent);color:white">Details</button>
</div>
`;
projectsGrid.appendChild(el);
});
// attach detail handlers
document.querySelectorAll('.project button').forEach(btn => btn.addEventListener('click', e=> openModal(e.target.dataset.id)));
}
function openModal(id){
const p = projects.find(x=>x.id===id);
if(!p) return;
const content = document.getElementById('modalContent');
content.innerHTML = `
<h3 style="margin-top:0">${p.title}</h3>
<p style="color:var(--muted)">${p.desc}</p>
<div style="margin:12px 0"><img src="${p.img}" alt="${p.title}" style="width:100%;border-radius:10px;max-height:320px;object-fit:cover"></div>
<p class="tags">${p.tags.map(t => `<span class="tag">${t}</span>`).join('')}</p>
<div style="margin-top:14px"><a href="${p.link}" class="cta">Open project</a></div>
`;
const modal = document.getElementById('modal');
modal.classList.add('show');
modal.setAttribute('aria-hidden','false');
}
document.getElementById('modalClose').addEventListener('click', ()=>{
const modal = document.getElementById('modal');
modal.classList.remove('show');
modal.setAttribute('aria-hidden','true');
});
document.getElementById('modal').addEventListener('click', (e)=>{
if(e.target.id === 'modal'){
document.getElementById('modal').classList.remove('show');
}
});
// Contact form handler (client-side only)
document.getElementById('contactForm').addEventListener('submit', (e)=>{
e.preventDefault();
const name = document.getElementById('fullName').value.trim();
const email = document.getElementById('email').value.trim();
const message = document.getElementById('message').value.trim();
const msgEl = document.getElementById('formMsg');
if(!name || !email || !message){
msgEl.textContent = 'Please fill required fields.';
return;
}
// For a real site, post to server or use Formspree / Netlify Forms / email API
msgEl.textContent = 'Thanks! Your message has been captured locally (demo). Replace this with a real backend.';
e.target.reset();
});
// Theme toggle — simple light/dark swap by inverting colors
const themeToggle = document.getElementById('themeToggle');
themeToggle.addEventListener('click', ()=>{
const root = document.documentElement;
if(root.style.getPropertyValue('--bg') === '#0f1724'){
// set light
root.style.setProperty('--bg','#f7fafc');
root.style.setProperty('--card','#ffffff');
root.style.setProperty('--text','#0b1220');
root.style.setProperty('--muted','#475569');
root.style.setProperty('--glass','rgba(11,17,32,0.03)');
} else {
// back to dark
root.style.setProperty('--bg','#0f1724');
root.style.setProperty('--card','#111827');
root.style.setProperty('--text','#e6eef8');
root.style.setProperty('--muted','#9ca3af');
root.style.setProperty('--glass','rgba(255,255,255,0.03)');
}
});
// Hamburger menu for small screens (simple toggle)
document.querySelector('.hamburger').addEventListener('click', ()=>{
const nav = document.querySelector('nav');
if(nav.style.display === 'flex') nav.style.display = 'none';
else nav.style.display = 'flex';
nav.style.flexDirection = 'column';
nav.style.position = 'absolute';
nav.style.right = '20px';
nav.style.top = '70px';
nav.style.background = 'var(--card)';
nav.style.padding = '10px';
nav.style.borderRadius = '10px';
nav.style.boxShadow = '0 8px 40px rgba(2,6,23,0.6)';
});
// Smooth scrolling for in-page links
document.querySelectorAll('a[href^="#"]').forEach(a=>{
a.addEventListener('click', e=>{
const href = a.getAttribute('href');
if(href.length>1){
e.preventDefault();
const el = document.querySelector(href);
if(el) el.scrollIntoView({behavior:'smooth',block:'start'});
}
})
});
// initial render
renderProjects();
// Accessibility: keyboard close on Esc
document.addEventListener('keydown', (e)=>{
if(e.key === 'Escape'){
document.getElementById('modal').classList.remove('show');
}
});
</script>
</body>
</html>