Build a Portfolio from Scratch
Portfolio Website Tutorial: Build from Scratch with Vanilla JavaScript
Master web fundamentals with this portfolio website tutorial that teaches you to create a professional portfolio with pure HTML, CSS, and vanilla JavaScript. Learn core frontend skills including responsive design, DOM manipulation, and modern CSS techniques without framework dependencies. Perfect for developers who want complete control and deep understanding of web technologies.
What You'll Build
- Professional portfolio showcase with responsive design
- Project gallery with filtering and animations
- Skills section with progress indicators
- Contact form with validation
- Smooth scrolling and interactive navigation
- Dark mode toggle with CSS variables
Core Frontend Skills You'll Learn
- Semantic HTML5: Proper document structure and accessibility
- Modern CSS: Flexbox, Grid, custom properties, and animations
- Responsive Design: Mobile-first approach with media queries
- Vanilla JavaScript: DOM manipulation and event handling
- CSS Animations: Transitions, keyframes, and smooth effects
- Form Validation: Client-side validation without libraries
- Performance: Optimized loading and minimal dependencies
Prerequisites
- Basic HTML knowledge (tags, attributes, document structure)
- CSS fundamentals (selectors, box model, basic styling)
- JavaScript basics (variables, functions, DOM basics)
- Code editor (VS Code recommended)
- Modern web browser with developer tools
Time Commitment: 5-7 hours. Build a portfolio that showcases both your work and your coding fundamentals.
Why This Portfolio Website Tutorial Works
Building without frameworks demonstrates mastery of web fundamentals that many developers lack. This approach shows employers you understand how things work under the hood, not just how to use framework CLIs. A vanilla JavaScript portfolio proves you can solve problems without reaching for dependenciesβa crucial skill for performance-critical applications.
This approach creates ultra-fast, lightweight portfolios that load instantly and work everywhere. No build step means instant previews and easy deployment. Plus, you'll understand exactly what frameworks like React do for you, making you a better developer regardless of which tools you eventually use.
Build a Portfolio from Scratch
There's something pure about building a portfolio from scratch - just you, HTML, CSS, and vanilla JavaScript. No build steps, no dependencies, no framework overhead. Every animation, every interaction, every style decision is yours. This approach showcases mastery of web fundamentals that frameworks often abstract away. you will create a fast, accessible portfolio that works everywhere and demonstrates deep understanding of how the web actually works. Perfect for showcasing frontend skills, personal branding, or proving you can build without training wheels.
Web Development Portfolio Setup: Installation and Project Configuration
Create folder structure
Create a well-organized folder structure for your portfolio website built from scratch Create main project directory, then subdirectories: css/ for stylesheets, js/ for JavaScript files, images/ for photos and graphics (with subdirectories projects/, icons/), data/ for JSON files if storing project data Create index.html as the main page (containing all sections: hero, projects, about, contact), create separate HTML files if using multi-page approach (projects.html, about.html, contact.html) Initialize git repository with git init Create .gitignore to exclude unnecessary files (node_modules/, .DS_Store, *.log) Create README.md documenting your portfolio structure and setup instructions Plan your single-page vs multi-page architecture If using build tools, create package.json Organize assets logically for easy maintenance.
Configure VS Code with Live Server
Set up VS Code for efficient HTML/CSS/JavaScript portfolio development Install essential extensions: Live Server by Ritwick Dey (for live preview), HTML CSS Support for IntelliSense, Auto Rename Tag for paired HTML tag editing, Prettier for code formatting, Live Sass Compiler if using Sass/SCSS Configure VS Code settings: create .vscode/settings.json with auto-save enabled, format on save with Prettier, set tab size to 2 for HTML/CSS/JS Set up Emmet for fast HTML writing (built into VS Code) Configure Live Server: right-click index.html and "Open with Live Server" for auto-refreshing preview Install optional extensions: CSS Peek for navigation, IntelliSense for CSS class names, Path Intellisense for file paths Set up code snippets for common HTML patterns Configure browser sync for testing across devices.
Build semantic layout
Build semantic HTML5 structure for your portfolio in index.html. Start with <!DOCTYPE html>, <html lang="en">, <head> with meta tags (charset UTF-8, viewport for responsive design, description for SEO, title with your name). Link CSS file in head (<link rel="stylesheet" href="css/style.css">). Structure body with semantic elements: <header> with navigation (<nav> with logo and menu links), <main> containing all content sections: <section id="hero"> for landing area with name/title/tagline, <section id="projects"> for projects showcase, <section id="about"> for bio and skills, <section id="contact"> for contact form and info Add <footer> with social links and copyright Use proper heading hierarchy (h1 for name in hero, h2 for section titles, h3 for subsections) Include alt text for all images Add ARIA labels for accessibility where needed. Keep HTML clean and well-commented. Link JavaScript before closing </body> tag (<script src="js/main.js"></script>).
Database and Environment Configuration for Web Development
Vanilla CSS or framework CDN
Decide on CSS approach for styling your portfolio. Option 1 - Vanilla CSS: create css/style.css, write all styles from scratch for full control and learning, organize with CSS sections (reset, variables, typography, layout, components, utilities, media queries). Option 2 - Tailwind CSS via CDN: add Tailwind CDN link in HTML head (<script src="https://cdn.tailwindcss.com"></script>), use utility classes directly in HTML, optionally configure theme in inline script tag. Option 3 - Bootstrap via CDN: add Bootstrap CSS and JS links, use Bootstrap grid system and components, customize with custom CSS For all options: implement CSS reset or normalize.css for consistent cross-browser styling Use CSS custom properties (variables) for colors, fonts, spacing for easy theming. Choose mobile-first responsive approach Consider CSS preprocessor (Sass/SCSS) if building more complex styles Organize CSS with clear comments and logical sections. Optimize for performance: minimize unused CSS, use efficient selectors.
Define colors and typography
Establish a cohesive design system for your portfolio using CSS custom properties in css/style.css Define color palette in :root: --color-primary (main brand color), --color-secondary (accent), --color-text (body text, dark gray), --color-text-light (muted text), --color-background (white or light), --color-background-alt (light gray for sections). Choose 2-3 colors maximum plus neutrals Ensure WCAG AA contrast ratios (4.5:1 for text) Define typography: import Google Fonts in CSS or HTML head (e.g., Inter, Poppins for headings; Open Sans, Roboto for body). Set CSS variables: --font-heading, --font-body, --font-size-base (16px), --font-size-h1 through h6 Create spacing scale: --space-xs (0.25rem) through --space-xl (4rem) for consistent padding/margins Define shadows: --shadow-sm, --shadow-md, --shadow-lg for depth. Set border-radius variables for consistent corners Define breakpoints for responsive design: mobile (<768px), tablet (768px-1024px), desktop (>1024px) Apply design system throughout CSS with var() function Create utility classes for common patterns.
Building Portfolio Features: Core Functionality and Admin Panel
Build landing with name and title
Create an impactful hero section in the #hero section of index.html Build HTML structure: container div with hero content including h1 with your name, p or h2 with your title/role (Web Developer, Designer, etc.), p with short tagline or elevator pitch (1-2 sentences about what you do), div with CTA buttons (View My Work, Contact Me), optional professional photo or illustration Style in css/style.css: make hero full viewport height (min-height: 100vh), center content with flexbox or grid (display: flex; align-items: center; justify-content: center), add background gradient or solid color, make name/title prominent with large font size, add animations for entrance (CSS @keyframes fadeInUp, apply to elements with animation property) Add background effects: gradient overlay, geometric shapes with CSS clip-path, or subtle pattern Include scroll indicator (down arrow) with animation Style CTA buttons with hover effects (transform: translateY(-2px), box-shadow increase) Make fully responsive: stack content vertically on mobile, reduce font sizes, adjust spacing Test across devices and browsers.
Create responsive grid
Build a comprehensive projects showcase section in #projects Create HTML structure: section heading (h2 "My Projects"), optional filter buttons for categories (All, Web Apps, Websites, etc.) using button elements with data-category attributes, div.projects-grid container, multiple article.project-card elements each containing: img with project screenshot, h3 with project title, p with brief description, div.tech-stack with span badges for each technology, div.project-links with links to live demo and GitHub (use <a> tags with target="_blank" rel="noopener") Style in CSS: use CSS Grid for responsive layout (display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem), style project cards with background, border-radius, box-shadow, add hover effects (transform: scale(1.03), box-shadow increase), style tech badges with pills/badges design, ensure images have aspect-ratio and object-fit: cover Create data/projects.json with project data (id, title, description, image, technologies, liveUrl, githubUrl, category) Write JavaScript in js/main.js to: fetch projects data, dynamically generate project cards, implement filter functionality (listen for button clicks, filter by category, show/hide projects) Add loading animation Make fully responsive with proper breakpoints Consider lazy loading images for performance.
Add bio and skills list
Create an engaging About section in #about Build HTML structure: section heading (h2 "About Me"), div.about-content with two-column layout - div.about-text with multiple p tags containing your bio (background, interests, goals, what drives you), div.about-image with professional photo or avatar (img with alt text). Below, create div.skills section with h3 "Skills", organize skills by category in div.skill-category containers: h4 for category name (Frontend, Backend, Tools), ul with li.skill-item for each skill containing icon (Font Awesome or emoji) and skill name Style in CSS: use flexbox or grid for two-column layout (reverse on mobile), style bio text with readable line-length (max-width: 60ch), make image circular or rounded with border-radius, add shadow, style skills with CSS Grid for multi-column layout, create skill badges or cards with icons, use consistent spacing. Optional: add skill proficiency bars (div.skill-bar with nested div.skill-level using width percentage), create visual interest with background color or shapes, add entrance animations on scroll (use Intersection Observer in JavaScript) Make responsive: stack columns on mobile, adjust skill grid columns. Keep bio authentic and concise (2-3 paragraphs).
Add contact info and form
Implement a functional contact section in #contact Build HTML structure: section heading (h2 "Get In Touch"), div.contact-content with two-column layout - div.contact-info with paragraph about availability, ul.contact-methods with li containing icons and links for email (mailto:), LinkedIn, GitHub, Twitter (use Font Awesome icons or SVG), location if desired, div.contact-form with <form> element containing: label and input for name (type="text", required), label and input for email (type="email", required), label and input for subject (optional), label and textarea for message (required, rows="5"), button for submit Style in CSS: use flexbox for layout, style form inputs with consistent padding, border, border-radius, focus states (:focus with outline), style button with primary color, hover/active states, ensure proper spacing between fields, make links in contact info styled as buttons or inline with icons For form functionality: Option 1 - Use Formspree or Formsubmit (set form action to service URL), Option 2 - Implement JavaScript validation in js/main.js (check required fields, validate email format, show error messages), add form submission handler, show success/error messages, clear form on success Add honeypot field for spam prevention (hidden input that bots fill) Make fully responsive: stack columns on mobile Consider add subtle animations or transitions for better UX.
Add hover effects and transitions
Enhance portfolio UX with smooth CSS animations and transitions
Add transitions to interactive elements in css/style.css: buttons (transition: all 0.3s ease), links (transition: color 0.2s), project cards (transition: transform 0.3s, box-shadow 0.3s), images (transition: transform 0.3s)
Create hover effects: buttons scale slightly (transform: scale(1.05)) and change box-shadow, project cards lift (transform: translateY(-5px) and increase shadow), links change color or add underline animation (use ::after pseudo-element with width transition)
Implement entrance animations using CSS @keyframes: fadeIn, fadeInUp, slideInLeft, slideInRight, define animations with opacity and transform changes
Apply animations to elements with animation property or create utility classes (.animate-on-scroll)
For scroll-triggered animations, write JavaScript in js/main.js: use Intersection Observer API, observe elements with animation classes, add .active or .visible class when in viewport triggering CSS animations
Add smooth scrolling: html { scroll-behavior: smooth; }, or implement custom smooth scroll in JS for better control
Create loading animation for page load
Add micro-interactions: form input focus highlights, nav link active states, skill bars animate width on scroll. Respect user preferences: @media (prefers-reduced-motion: reduce) { /* disable animations */ }. Keep animations subtle and purposeful - enhance UX without distraction. Target 60fps performance.Mobile, tablet, desktop layouts
Implement comprehensive responsive design for all devices in css/style.css using mobile-first approach. Start with mobile base styles (320px+): single column layouts, full-width elements, larger tap targets (min 44x44px), readable font sizes (16px+), adequate spacing Define breakpoints in CSS comments: /* Mobile: < 768px (base styles) */, /* Tablet: 768px - 1024px */, /* Desktop: > 1024px */ Use @media queries for larger screens: tablet (@media (min-width: 768px)) - introduce two-column layouts for about/contact, adjust grid columns for projects (grid-template-columns: repeat(2, 1fr)), increase container width, adjust typography scale. Desktop (@media (min-width: 1024px)) - use three-column grid for projects, add max-width to content (1200px) with margin auto for centering, larger hero section, full horizontal navigation Make navigation responsive: mobile shows hamburger menu (β°), create .nav-toggle button with JS toggle for mobile menu, desktop shows horizontal menu inline Test layouts on actual devices or browser dev tools at various sizes. Optimize images with srcset for different screen densities Use relative units (rem, em, %, vh/vw) over fixed pixels Test touch interactions on mobile Ensure form inputs are usable on mobile Test in portrait and landscape orientations Validate responsive design in Chrome DevTools device emulator and real devices Ensure text remains readable at all sizes (min 14px on mobile).
Image Optimization & Project Gallery
Implement image optimization and project galleries for portfolio.
Organize images directory structure: images/projects/ for project screenshots, images/hero/ for hero section backgrounds, images/gallery/ for multi-image displays, images/profile/ for personal photos.
Optimize all images before adding: compress using TinyPNG, Squoosh, or ImageOptim to reduce file sizes, convert large images to WebP format with JPG/PNG fallback for broader support, resize images to actual display dimensions (no 4K images for 600px containers), create multiple sizes: thumbnail (400px), medium (800px), large (1200px), aim for file sizes under 200KB for project screenshots, under 100KB for thumbnails.
Implement responsive images using picture element and srcset: <picture> <source srcset="images/projects/project1-800.webp 800w, images/projects/project1-1200.webp 1200w" type="image/webp"> <img src="images/projects/project1-800.jpg" srcset="images/projects/project1-400.jpg 400w, images/projects/project1-800.jpg 800w, images/projects/project1-1200.jpg 1200w" sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px" alt="Project Name Screenshot" loading="lazy"> </picture>.
Add native lazy loading to all images below fold with loading="lazy" attribute for instant performance gains.
Create project gallery data structure in projects.json: { "id": "project1", "title": "...", "images": [ { "thumbnail": "./images/projects/p1-thumb.jpg", "medium": "./images/projects/p1-medium.jpg", "large": "./images/projects/p1-large.jpg", "webp": { "medium": "./images/projects/p1-medium.webp", "large": "./images/projects/p1-large.webp" }, "alt": "Description", "caption": "Optional caption" } ] }.
Build JavaScript image gallery: create gallery component that renders multiple images per project, implement lightbox for full-size viewing using vanilla JS or library (PhotoSwipe, GLightbox), add image carousel/slider with prev/next navigation using CSS scroll-snap or Swiper.js, include captions and image metadata.
Implement lazy loading with Intersection Observer for custom control: const imageObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; imageObserver.unobserve(img); } }); }), apply to all images with data-src attribute.
Add image loading states with CSS: show placeholder background color or blur effect while loading, implement blur-up technique using tiny base64 placeholder images, add smooth fade-in animation when image loads.
Create hero section with background images: implement parallax scrolling effect with background-attachment or transform, add gradient overlay for text readability, use CSS background-size: cover with proper positioning.
For project detail pages: create multi-image showcase section, implement image zoom on hover (CSS transform: scale), add before/after image slider for design projects using CSS clip-path or JavaScript, include image captions and descriptions.
Add image preloading for critical images: use <link rel="preload" as="image" href="hero.jpg"> for above-fold images.
Ensure accessibility: provide descriptive alt text for all images, use empty alt="" for decorative images, implement keyboard navigation for gallery lightbox, ensure proper focus management.Testing Your Web Development Portfolio Application
Create manual testing checklist
Create a comprehensive manual testing checklist for your portfolio website Create TESTING.md file documenting all test scenarios. Browser compatibility testing: test in Chrome, Firefox, Safari, Edge, check for layout issues, verify all features work, test on different OS (Windows, macOS, iOS, Android). Device testing: test on mobile phone (iOS and Android), tablet, laptop, desktop, verify responsive breakpoints, test touch interactions. Functionality testing checklist: [ ] All navigation links work and scroll to correct sections or pages, [ ] Project cards display correctly with images and descriptions, [ ] Project links (live demo, GitHub) open in new tabs, [ ] Filter buttons work if implemented, [ ] Contact form submits successfully, [ ] Form validation works (required fields, email format), [ ] Form shows success/error messages, [ ] Social media links in footer work, [ ] All images load and have alt text, [ ] Smooth scrolling works, [ ] Animations trigger correctly, [ ] Hover effects work on interactive elements. Performance testing: check Lighthouse score in Chrome DevTools (aim 90+ on Performance, Accessibility, Best Practices, SEO), verify page loads in under 3 seconds, check image sizes are optimized, ensure no console errors. Accessibility testing: test keyboard navigation (Tab through all interactive elements), verify focus states are visible, check color contrast (use browser extension), test with screen reader if possible, validate HTML (W3C validator), verify semantic HTML structure. Visual testing: check typography consistency, verify color scheme throughout, ensure spacing is consistent, check alignment of elements, test at multiple screen sizes Create checklist of fixes needed and prioritize by severity.
Test all sections display
Perform your first comprehensive test of the portfolio website. Open index.html in browser with Live Server or directly. Visual inspection checklist: [ ] Hero section displays with name, title, tagline, and CTA buttons visible and properly styled, [ ] Navigation bar shows all menu items (Projects, About, Contact), [ ] Projects section displays project cards in grid layout with images, [ ] Each project card shows title, description, tech stack, and links, [ ] About section shows bio text and photo side by side (desktop) or stacked (mobile), [ ] Skills are displayed and organized by category, [ ] Contact section shows contact information and form, [ ] Form has all required fields (name, email, message, submit button), [ ] Footer displays social media links and copyright Interaction testing: click each navigation link and verify smooth scroll to correct section, hover over project cards and buttons to see hover effects, click project links to verify they open (use # placeholder if projects not deployed yet), test form by filling fields and submitting (check console or network tab for submission if using service), verify error messages appear when submitting empty form. Responsive testing: resize browser window from mobile (320px) to desktop (1920px), verify layout changes at breakpoints, ensure text remains readable at all sizes, check that hamburger menu appears on mobile if implemented, verify no horizontal scroll at any size, test on actual mobile device if available Developer tools check: open browser DevTools Console, verify no JavaScript errors appear, check Network tab shows all resources load successfully (CSS, JS, images), use Lighthouse audit and check scores. Document any issues found: layout problems, broken links, styling inconsistencies, accessibility issues. Fix critical issues before proceeding. This test validates your basic portfolio structure and functionality.
Test on all screen sizes
Conduct thorough responsive design testing across all device sizes Use Chrome DevTools Device Toolbar (toggle with Ctrl/Cmd+Shift+M) to simulate different devices Test on standard breakpoints and devices: Mobile phones - iPhone SE (375px), iPhone 12 Pro (390px), Samsung Galaxy S20 (360px), test in both portrait and landscape, verify single-column layouts, check touch target sizes (buttons, links at least 44x44px), ensure text is readable (min 16px for body), verify navigation shows hamburger menu, test form inputs are large enough for touch. Tablets - iPad (768px), iPad Pro (1024px), test two-column layouts appear, verify project grid shows 2 columns, check navigation layout, test both orientations. Desktop - 1366px (standard laptop), 1920px (full HD), verify three-column project grid, check max-width containers are centered, ensure navigation is horizontal inline menu, verify large hero section Test responsive images: verify images scale properly, check for distortion (should maintain aspect ratio), ensure images don't exceed container widths. Test responsive typography: verify font sizes scale appropriately at each breakpoint, check line lengths are readable (45-75 characters), ensure headings maintain hierarchy. Test navigation at each size: mobile shows hamburger menu that toggles, tablet shows appropriate menu (inline or hamburger based on design), desktop shows full horizontal menu. Test forms at each size: verify inputs are full-width on mobile, check labels are visible and aligned, ensure submit button is prominent. Test spacing and padding: ensure adequate spacing between elements at all sizes, verify sections aren't cramped on mobile, check that content isn't too spread on large screens. Document issues found: elements overlapping, text too small/large, images distorted, horizontal scrolling, broken layouts. Fix all responsive issues before deploying. Test on real devices in addition to browser simulation for final validation.
Deploying Your Web Development Portfolio to Production
Deploy to GitHub Pages
Deploy your portfolio website to GitHub Pages for free hosting. Setup GitHub repository: create repository on GitHub (e.g., username.github.io for user site or portfolio for project site), initialize local repository if not done (git init), add remote (git remote add origin [repository-URL]), commit all files (git add . && git commit -m "Initial portfolio commit"), push to GitHub (git push -u origin main or master) Configure GitHub Pages: go to repository Settings > Pages, select source branch (main or master), select folder (/ root or /docs if using docs folder), save settings, wait few minutes for deployment. Access deployed site at https://username.github.io (for user site) or https://username.github.io/portfolio (for project site). Custom domain (optional): purchase domain from registrar, add CNAME file to root with your domain name, configure DNS records at registrar: add A records pointing to GitHub IPs (185.199.108-111.153), or add CNAME record pointing to username.github.io, enable HTTPS in GitHub Pages settings (automatic with Let's Encrypt). Pre-deployment checklist: [ ] All links work correctly, [ ] Images use relative paths (./images/...), [ ] No references to localhost, [ ] Forms use proper action URLs (Formspree, etc), [ ] Meta tags are filled (title, description), [ ] Favicon is included, [ ] Remove console.logs and debug code, [ ] Optimize images (compress, use modern formats), [ ] Minify CSS/JS if applicable, [ ] Test locally one final time. Post-deployment testing: visit deployed URL, test all functionality works in production, verify forms submit correctly, check images load, test on mobile device, run Lighthouse audit, check SSL certificate loads (https://). Update README with deployed URL. Share portfolio link on social media, LinkedIn, resume. Set up analytics (Google Analytics or Plausible) to track visitors. Monitor for issues and iterate based on feedback.
