SynfraCore
Synfracore
Start Learning
Navigation

Academies

Platform

RoadmapsLabsCertificationsInterviewPYQsAI AssistantCareer
Start Learning Free Learning Roadmaps

CSS & Modern LayoutProjects

Portfolio-ready projects to demonstrate your skills

📄
Last updated Sep 2026
Expert Content

CSS — Portfolio Projects

Project 1: Responsive Card Grid (No Framework)

Level: Beginner | Time: 3-5 hours | GitHub repo name: css-responsive-card-grid

What you build: A gallery of product/article cards that reflows from a single column on mobile to a multi-column grid on desktop, entirely with CSS Grid's auto-fit/minmax() — zero media queries for the reflow itself.

css
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.5rem;
  padding: 1.5rem;
}

.card {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12);
}

.card img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.card-body {
  padding: 1rem;
}

Extend it: add a --card-min-width custom property so the minimum card width is configurable from one place, and confirm resizing the browser from 320px to 1440px never produces horizontal overflow at any width.


Project 2: CSS-Only Accordion / Tabs Component

Level: Intermediate | Time: 4-6 hours | GitHub repo name: css-only-accordion

What you build: An expand/collapse accordion (and a tabbed panel variant) using only HTML and CSS — no JavaScript — leveraging the

/ elements and the :checked pseudo-class with hidden radio inputs for the tabs version.

css
/* Accordion — native <details>/<summary>, styled */
details {
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  margin-bottom: 0.5rem;
}

summary {
  padding: 0.75rem 1rem;
  cursor: pointer;
  font-weight: 600;
  list-style: none; /* removes default disclosure triangle */
}

summary::-webkit-details-marker { display: none; }

summary::after {
  content: "+";
  float: right;
  transition: transform 0.2s ease;
}

details[open] summary::after {
  transform: rotate(45deg);
}

details > *:not(summary) {
  padding: 0 1rem 1rem;
}
css
/* Tabs — hidden radio inputs + sibling selectors, zero JavaScript */
.tabs input[type="radio"] { display: none; }
.tab-content { display: none; padding: 1rem; }

#tab1:checked ~ .panels #panel1,
#tab2:checked ~ .panels #panel2 {
  display: block;
}

.tab-label {
  display: inline-block;
  padding: 0.5rem 1rem;
  cursor: pointer;
  border-bottom: 2px solid transparent;
}

#tab1:checked ~ .tab-labels label[for="tab1"],
#tab2:checked ~ .tab-labels label[for="tab2"] {
  border-bottom-color: #2563eb;
  font-weight: 600;
}

Extend it: add prefers-reduced-motion handling for the rotate transition, and confirm the whole component is fully keyboard-navigable (tab to a summary/label, press Enter/Space to activate) without touching JavaScript.


Project 3: Full Responsive Layout Without a Framework

Level: Advanced | Time: 8-12 hours | GitHub repo name: css-full-responsive-layout

What you build: A complete, realistic page layout — sticky header, collapsible sidebar, main content area, footer — that adapts across mobile/tablet/desktop using Grid for structure, Flexbox for internal alignment, container queries for a reusable card component, and @layer to keep a small "design tokens" layer cleanly separated from component styles.

css
@layer tokens, base, layout, components;

@layer tokens {
  :root {
    --sidebar-width: 240px;
    --header-height: 64px;
    --gap: 1rem;
  }
}

@layer layout {
  .app-shell {
    display: grid;
    grid-template-columns: var(--sidebar-width) 1fr;
    grid-template-rows: var(--header-height) 1fr;
    grid-template-areas:
      "sidebar header"
      "sidebar main";
    min-height: 100vh;
  }

  @media (max-width: 767px) {
    .app-shell {
      grid-template-columns: 1fr;
      grid-template-areas:
        "header"
        "main";
    }
    .sidebar { display: none; } /* replaced by a mobile drawer, toggled via a checkbox hack or minimal JS */
  }

  .header  { grid-area: header;  display: flex; align-items: center; padding: 0 var(--gap); position: sticky; top: 0; }
  .sidebar { grid-area: sidebar; }
  .main    { grid-area: main;    padding: var(--gap); }
}

@layer components {
  .card-container { container-type: inline-size; }

  @container (min-width: 400px) {
    .card { display: grid; grid-template-columns: 120px 1fr; }
  }
}

Extend it: run the finished page through DevTools' Performance panel while resizing the browser, and confirm no unexpected layout-shift entries appear during the sidebar's mobile/desktop breakpoint transition.

Share:
Join our Community
Daily tips, job alerts, interview help — join engineers learning together
Up Next
💬
CSS & Modern LayoutInterview Q&A
Most asked interview questions with detailed answers
Also Worth Exploring
← Back to all CSS & Modern Layout modules
LabsInterview Q&A