HTML and CSS course Β· Module 5: Responsiveness
Main Project - Responsive Photographer Portfolio Gallery
In this lesson7
A photographer friend needs a website that shows his photos just as well on a client's phone as on the monitor in his office. In this project, we'll create a professional, fully responsive portfolio gallery for a photographer. We'll use all the techniques from this module: media queries, responsive units (vw, vh), viewport, image optimization, and the mobile-first approach. The gallery will include navigation, a hero section, a photo grid with hover effects, category filtering, and a lightbox for viewing photos.
Project description
Our portfolio gallery will have the following features:
- Responsive navigation - hamburger menu on mobile devices
- Hero Section - full-screen using viewport units
- Photo gallery - responsive grid with hover effects
- Category filtering - filter buttons with interactive design
- Lightbox - viewing enlarged photos
- Image optimization - different sizes for different devices
Step 1: HTML Structure with Mobile-First Approach
We start with an HTML structure written with phones in mind. Notice the viewport tag in the head and the picture elements in the gallery:
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>John Smith - Photographer Portfolio</title>
7 <link rel="stylesheet" href="styles.css">
8</head>
9<body>
10 <!-- Navigation -->
11 <nav class="navbar">
12 <div class="nav-container">
13 <div class="nav-logo">JS Photography</div>
14 <button class="nav-toggle" aria-label="Menu">
15 <span></span>
16 <span></span>
17 <span></span>
18 </button>
19 <ul class="nav-menu">
20 <li><a href="#home">Home</a></li>
21 <li><a href="#portfolio">Portfolio</a></li>
22 <li><a href="#about">About</a></li>
23 <li><a href="#contact">Contact</a></li>
24 </ul>
25 </div>
26 </nav>
27
28 <!-- Hero Section -->
29 <section id="home" class="hero">
30 <div class="hero-content">
31 <h1 class="hero-title">John Smith</h1>
32 <p class="hero-subtitle">Photography is my passion</p>
33 <a href="#portfolio" class="hero-button">View portfolio</a>
34 </div>
35 <div class="hero-overlay"></div>
36 </section>
37
38 <!-- Portfolio Section -->
39 <section id="portfolio" class="portfolio">
40 <div class="container">
41 <h2 class="section-title">My Portfolio</h2>
42
43 <!-- Category filters -->
44 <div class="filter-buttons">
45 <button class="filter-btn active" data-filter="all">All</button>
46 <button class="filter-btn" data-filter="nature">Nature</button>
47 <button class="filter-btn" data-filter="portrait">Portraits</button>
48 <button class="filter-btn" data-filter="architecture">Architecture</button>
49 </div>
50
51 <!-- Gallery -->
52 <div class="gallery">
53 <div class="gallery-item" data-category="nature">
54 <picture>
55 <source media="(max-width: 768px)" srcset="img/nature1-mobile.jpg">
56 <source media="(max-width: 1200px)" srcset="img/nature1-tablet.jpg">
57 <img src="img/nature1-desktop.jpg" alt="Mountain landscape">
58 </picture>
59 <div class="gallery-overlay">
60 <h3>Mountain landscape</h3>
61 <p>Nature</p>
62 </div>
63 </div>
64
65 <div class="gallery-item" data-category="portrait">
66 <picture>
67 <source media="(max-width: 768px)" srcset="img/portrait1-mobile.jpg">
68 <source media="(max-width: 1200px)" srcset="img/portrait1-tablet.jpg">
69 <img src="img/portrait1-desktop.jpg" alt="Woman portrait">
70 </picture>
71 <div class="gallery-overlay">
72 <h3>Portrait</h3>
73 <p>Portraits</p>
74 </div>
75 </div>
76
77 <!-- More gallery items... -->
78 </div>
79 </div>
80 </section>
81
82 <!-- Lightbox -->
83 <div class="lightbox" id="lightbox">
84 <span class="lightbox-close">×</span>
85 <img class="lightbox-content" id="lightbox-img">
86 <div class="lightbox-caption"></div>
87 </div>
88</body>
89</html>The nav-toggle button is the hamburger, and its aria-label tells screen readers what it is for. The data-category attributes prepare the filtering. The hamburger, the filters and the lightbox will come to life only with a script that you will write once you know JavaScript, while CSS prepares their states with the active class.
Step 2: Mobile-First CSS with Responsive Units
We start styling with phones and split the stylesheet into four stages. The first one is the reset, CSS variables written once in :root and inserted with var(), and the navigation with its menu hidden under the hamburger:
1/* Reset and basic styles */
2* {
3 margin: 0;
4 padding: 0;
5 box-sizing: border-box;
6}
7
8:root {
9 --primary-color: #333;
10 --secondary-color: #f4f4f4;
11 --accent-color: #ff6b6b;
12 --text-light: #fff;
13 --overlay-dark: rgba(0, 0, 0, 0.7);
14}
15
16body {
17 font-family: 'Arial', sans-serif;
18 line-height: 1.6;
19 color: var(--primary-color);
20}
21
22/* Navigation - Mobile First */
23.navbar {
24 background-color: var(--primary-color);
25 padding: 1rem;
26 position: fixed;
27 width: 100%;
28 top: 0;
29 z-index: 1000;
30}
31
32.nav-container {
33 display: flex;
34 justify-content: space-between;
35 align-items: center;
36}
37
38.nav-logo {
39 color: var(--text-light);
40 font-size: 1.5rem;
41 font-weight: bold;
42}
43
44/* Hamburger menu for mobile */
45.nav-toggle {
46 background: none;
47 border: none;
48 cursor: pointer;
49 display: flex;
50 flex-direction: column;
51 gap: 4px;
52}
53
54.nav-toggle span {
55 width: 25px;
56 height: 3px;
57 background-color: var(--text-light);
58 transition: all 0.3s ease;
59}
60
61.nav-menu {
62 position: absolute;
63 top: 100%;
64 left: 0;
65 width: 100%;
66 background-color: var(--primary-color);
67 list-style: none;
68 display: none;
69 flex-direction: column;
70}
71
72.nav-menu.active {
73 display: flex;
74}
75
76.nav-menu li {
77 padding: 1rem;
78 text-align: center;
79}
80
81.nav-menu a {
82 color: var(--text-light);
83 text-decoration: none;
84 transition: color 0.3s ease;
85}box-sizing: border-box keeps padding from widening elements. The bar with position: fixed stays at the top while scrolling, and the menu with display: none waits until a script adds the active class to it. The second stage is the hero section, the portfolio and the filters:
1/* Hero section with viewport units */
2.hero {
3 height: 100vh;
4 width: 100vw;
5 position: relative;
6 display: flex;
7 align-items: center;
8 justify-content: center;
9 background-image: url('img/hero-mobile.jpg');
10 background-size: cover;
11 background-position: center;
12}
13
14.hero-overlay {
15 position: absolute;
16 top: 0;
17 left: 0;
18 width: 100%;
19 height: 100%;
20 background-color: var(--overlay-dark);
21}
22
23.hero-content {
24 position: relative;
25 z-index: 1;
26 text-align: center;
27 color: var(--text-light);
28 padding: 0 1rem;
29}
30
31.hero-title {
32 font-size: clamp(2rem, 8vw, 4rem);
33 margin-bottom: 1rem;
34}
35
36.hero-subtitle {
37 font-size: clamp(1rem, 4vw, 1.5rem);
38 margin-bottom: 2rem;
39}
40
41.hero-button {
42 display: inline-block;
43 padding: 0.8rem 2rem;
44 background-color: var(--accent-color);
45 color: var(--text-light);
46 text-decoration: none;
47 border-radius: 5px;
48 transition: all 0.3s ease;
49}
50
51/* Portfolio section */
52.portfolio {
53 padding: 4rem 1rem;
54 background-color: var(--secondary-color);
55}
56
57.container {
58 max-width: 1200px;
59 margin: 0 auto;
60}
61
62.section-title {
63 text-align: center;
64 font-size: clamp(1.5rem, 5vw, 2.5rem);
65 margin-bottom: 2rem;
66}
67
68/* Filters */
69.filter-buttons {
70 display: flex;
71 flex-wrap: wrap;
72 justify-content: center;
73 gap: 0.5rem;
74 margin-bottom: 2rem;
75}
76
77.filter-btn {
78 padding: 0.5rem 1rem;
79 border: 2px solid var(--primary-color);
80 background-color: transparent;
81 cursor: pointer;
82 transition: all 0.3s ease;
83 border-radius: 25px;
84}
85
86.filter-btn.active,
87.filter-btn:hover {
88 background-color: var(--primary-color);
89 color: var(--text-light);
90}height: 100vh is the full height of the window. clamp(2rem, 8vw, 4rem) takes a minimum, a preferred value and a maximum, so the title grows with the screen but never drops below 2rem or exceeds 4rem. The container with max-width: 1200px keeps the content in the middle. The third stage is the gallery and the lightbox:
1/* Gallery - Mobile First Grid */
2.gallery {
3 display: grid;
4 grid-template-columns: 1fr;
5 gap: 1rem;
6}
7
8.gallery-item {
9 position: relative;
10 overflow: hidden;
11 cursor: pointer;
12 aspect-ratio: 1;
13}
14
15.gallery-item img {
16 width: 100%;
17 height: 100%;
18 object-fit: cover;
19 transition: transform 0.3s ease;
20}
21
22.gallery-overlay {
23 position: absolute;
24 bottom: 0;
25 left: 0;
26 right: 0;
27 background: linear-gradient(to top, var(--overlay-dark), transparent);
28 color: var(--text-light);
29 padding: 1rem;
30 transform: translateY(100%);
31 transition: transform 0.3s ease;
32}
33
34.gallery-item:hover .gallery-overlay {
35 transform: translateY(0);
36}
37
38.gallery-item:hover img {
39 transform: scale(1.1);
40}
41
42/* Lightbox */
43.lightbox {
44 display: none;
45 position: fixed;
46 z-index: 2000;
47 left: 0;
48 top: 0;
49 width: 100vw;
50 height: 100vh;
51 background-color: var(--overlay-dark);
52 align-items: center;
53 justify-content: center;
54}
55
56.lightbox.active {
57 display: flex;
58}
59
60.lightbox-content {
61 max-width: 90vw;
62 max-height: 90vh;
63 object-fit: contain;
64}
65
66.lightbox-close {
67 position: absolute;
68 top: 1rem;
69 right: 1rem;
70 color: var(--text-light);
71 font-size: 2rem;
72 cursor: pointer;
73}On a phone, the gallery has a single 1fr column. aspect-ratio: 1 turns each tile into a square, and object-fit: cover crops the photo without distortion. The lightbox with the active class becomes a flex container, and max-width: 90vw makes sure the photo always fits in the window. The fourth stage is the breakpoints for larger screens:
1/* Media Queries - Tablet */
2@media (min-width: 768px) {
3 /* Navigation for tablet */
4 .nav-toggle {
5 display: none;
6 }
7
8 .nav-menu {
9 position: static;
10 display: flex;
11 flex-direction: row;
12 width: auto;
13 }
14
15 .nav-menu li {
16 padding: 0 1rem;
17 }
18
19 /* Hero for tablet */
20 .hero {
21 background-image: url('img/hero-tablet.jpg');
22 }
23
24 /* Gallery - 2 columns */
25 .gallery {
26 grid-template-columns: repeat(2, 1fr);
27 }
28}
29
30/* Media Queries - Desktop */
31@media (min-width: 1024px) {
32 /* Hero for desktop */
33 .hero {
34 background-image: url('img/hero-desktop.jpg');
35 }
36
37 /* Gallery - 3 columns */
38 .gallery {
39 grid-template-columns: repeat(3, 1fr);
40 gap: 1.5rem;
41 }
42
43 /* Hover effects only on desktop */
44 .gallery-overlay {
45 opacity: 0;
46 transform: translateY(0);
47 background: var(--overlay-dark);
48 }
49
50 .gallery-item:hover .gallery-overlay {
51 opacity: 1;
52 }
53}
54
55/* Media Queries - Large screens */
56@media (min-width: 1440px) {
57 .gallery {
58 grid-template-columns: repeat(4, 1fr);
59 }
60}
61
62/* Landscape orientation for mobile */
63@media (max-width: 768px) and (orientation: landscape) {
64 .hero {
65 height: 100vw;
66 }
67
68 .hero-title {
69 font-size: 2rem;
70 }
71}
72
73/* High DPI displays */
74@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
75 .hero {
76 background-image: url('img/hero-mobile@2x.jpg');
77 }
78
79 @media (min-width: 768px) {
80 .hero {
81 background-image: url('img/hero-tablet@2x.jpg');
82 }
83 }
84
85 @media (min-width: 1024px) {
86 .hero {
87 background-image: url('img/hero-desktop@2x.jpg');
88 }
89 }
90}From 768 pixels up, the hamburger disappears, the menu lines up in a row and the gallery gets two columns, from 1024 three, and from 1440 four. The orientation: landscape condition catches a rotated phone, and min-resolution: 192dpi catches screens with double pixel density, which we serve higher-resolution photos.
Step 3: Optimization and best practices
Image optimization:
The picture element lets the browser choose a file: it checks the media condition and whether it supports the format given in type:
1<!-- Use the picture element for responsive images -->
2<picture>
3 <source media="(max-width: 768px)"
4 srcset="img/photo-mobile.webp"
5 type="image/webp">
6 <source media="(max-width: 768px)"
7 srcset="img/photo-mobile.jpg"
8 type="image/jpeg">
9 <source media="(max-width: 1200px)"
10 srcset="img/photo-tablet.webp"
11 type="image/webp">
12 <source media="(max-width: 1200px)"
13 srcset="img/photo-tablet.jpg"
14 type="image/jpeg">
15 <source srcset="img/photo-desktop.webp"
16 type="image/webp">
17 <img src="img/photo-desktop.jpg"
18 alt="Photo description"
19 loading="lazy">
20</picture>Modern browsers will download the lightweight WebP, older ones will fall back to JPEG, and loading="lazy" delays downloading photos that are off screen.
Additional styles for performance:
Finally, a few rules for performance, accessibility and dark mode:
1/* Use will-change for animated elements */
2.gallery-item {
3 will-change: transform;
4}
5
6/* Performance optimization */
7.gallery-item img {
8 will-change: transform;
9 backface-visibility: hidden;
10}
11
12/* Use CSS containment */
13.gallery-item {
14 contain: layout style;
15}
16
17/* Prefers reduced motion */
18@media (prefers-reduced-motion: reduce) {
19 * {
20 animation-duration: 0.01ms !important;
21 animation-iteration-count: 1 !important;
22 transition-duration: 0.01ms !important;
23 }
24}
25
26/* Dark mode support */
27@media (prefers-color-scheme: dark) {
28 :root {
29 --primary-color: #fff;
30 --secondary-color: #1a1a1a;
31 --text-light: #333;
32 }
33
34 body {
35 background-color: #1a1a1a;
36 color: #fff;
37 }
38}contain limits recalculations to a single tile, prefers-reduced-motion shortens animations for people who have turned off motion in their system, and prefers-color-scheme: dark switches on the dark colors.
Step 4: A Grid without media queries
The gallery uses CSS Grid, which you will learn in detail in the location devoted to it. grid-template-columns: 1fr 1fr 1fr creates three equal columns, because fr is a fraction of the free space, and repeat(3, 1fr) is the same thing written in short. Grid can also choose the number of columns on its own:
1.gallery {
2 display: grid;
3 grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
4 gap: 1rem;
5}minmax(250px, 1fr) gives each column at least 250 pixels, and auto-fit fits as many of them as there is room for, so no media queries are needed. Grid lays out elements in two dimensions at once, while Flexbox works in one, which is why a page skeleton is a job for Grid and its named areas:
1.page {
2 display: grid;
3 grid-template-columns: 200px 1fr 200px;
4 grid-template-areas:
5 "header header header"
6 "nav main aside"
7 "footer footer footer";
8}
9
10header { grid-area: header; }
11nav { grid-area: nav; }
12main { grid-area: main; }
13aside { grid-area: aside; }
14footer { grid-area: footer; }grid-template-areas draws the plan of the page from names, like the plan of a temple with a main hall and side chambers, and grid-area assigns an element to an area. On a phone, a single column with the areas stacked one below another is enough. You can also calculate widths with the calc() function, for example calc(100% - 20px). You can build the same gallery with Flexbox by changing the tiles' flex-basis in media queries from 100% to calc(50% - 10px) and calc(33.33% - 14px).
Complete code example
HTML (index.html):
Compared with step 1, the full file has a page description in a meta tag, preconnect links, sample photos from picsum.photos and a script.js script:
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta name="description" content="Photography portfolio of John Smith">
7 <title>John Smith - Photographer Portfolio</title>
8 <link rel="stylesheet" href="styles.css">
9 <link rel="preconnect" href="https://fonts.googleapis.com">
10 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11</head>
12<body>
13 <!-- Navigation -->
14 <nav class="navbar">
15 <div class="nav-container">
16 <div class="nav-logo">JS Photography</div>
17 <button class="nav-toggle" aria-label="Menu">
18 <span></span>
19 <span></span>
20 <span></span>
21 </button>
22 <ul class="nav-menu">
23 <li><a href="#home">Home</a></li>
24 <li><a href="#portfolio">Portfolio</a></li>
25 <li><a href="#about">About</a></li>
26 <li><a href="#contact">Contact</a></li>
27 </ul>
28 </div>
29 </nav>
30
31 <!-- Hero Section -->
32 <section id="home" class="hero">
33 <div class="hero-content">
34 <h1 class="hero-title">John Smith</h1>
35 <p class="hero-subtitle">Photography is my passion</p>
36 <a href="#portfolio" class="hero-button">View portfolio</a>
37 </div>
38 <div class="hero-overlay"></div>
39 </section>
40
41 <!-- Portfolio Section -->
42 <section id="portfolio" class="portfolio">
43 <div class="container">
44 <h2 class="section-title">My Portfolio</h2>
45
46 <!-- Category filters -->
47 <div class="filter-buttons">
48 <button class="filter-btn active" data-filter="all">All</button>
49 <button class="filter-btn" data-filter="nature">Nature</button>
50 <button class="filter-btn" data-filter="portrait">Portraits</button>
51 <button class="filter-btn" data-filter="architecture">Architecture</button>
52 </div>
53
54 <!-- Gallery -->
55 <div class="gallery">
56 <!-- Sample gallery items -->
57 <div class="gallery-item" data-category="nature">
58 <picture>
59 <source media="(max-width: 768px)" srcset="https://picsum.photos/400/400?random=1">
60 <source media="(max-width: 1200px)" srcset="https://picsum.photos/600/600?random=1">
61 <img src="https://picsum.photos/800/800?random=1" alt="Mountain landscape">
62 </picture>
63 <div class="gallery-overlay">
64 <h3>Mountain landscape</h3>
65 <p>Nature</p>
66 </div>
67 </div>
68
69 <div class="gallery-item" data-category="portrait">
70 <picture>
71 <source media="(max-width: 768px)" srcset="https://picsum.photos/400/400?random=2">
72 <source media="(max-width: 1200px)" srcset="https://picsum.photos/600/600?random=2">
73 <img src="https://picsum.photos/800/800?random=2" alt="Portrait">
74 </picture>
75 <div class="gallery-overlay">
76 <h3>Portrait</h3>
77 <p>Portraits</p>
78 </div>
79 </div>
80
81 <div class="gallery-item" data-category="architecture">
82 <picture>
83 <source media="(max-width: 768px)" srcset="https://picsum.photos/400/400?random=3">
84 <source media="(max-width: 1200px)" srcset="https://picsum.photos/600/600?random=3">
85 <img src="https://picsum.photos/800/800?random=3" alt="Architecture">
86 </picture>
87 <div class="gallery-overlay">
88 <h3>Modern architecture</h3>
89 <p>Architecture</p>
90 </div>
91 </div>
92
93 <div class="gallery-item" data-category="nature">
94 <picture>
95 <source media="(max-width: 768px)" srcset="https://picsum.photos/400/400?random=4">
96 <source media="(max-width: 1200px)" srcset="https://picsum.photos/600/600?random=4">
97 <img src="https://picsum.photos/800/800?random=4" alt="Forest">
98 </picture>
99 <div class="gallery-overlay">
100 <h3>Forest path</h3>
101 <p>Nature</p>
102 </div>
103 </div>
104
105 <div class="gallery-item" data-category="portrait">
106 <picture>
107 <source media="(max-width: 768px)" srcset="https://picsum.photos/400/400?random=5">
108 <source media="(max-width: 1200px)" srcset="https://picsum.photos/600/600?random=5">
109 <img src="https://picsum.photos/800/800?random=5" alt="Child portrait">
110 </picture>
111 <div class="gallery-overlay">
112 <h3>Childhood joy</h3>
113 <p>Portraits</p>
114 </div>
115 </div>
116
117 <div class="gallery-item" data-category="architecture">
118 <picture>
119 <source media="(max-width: 768px)" srcset="https://picsum.photos/400/400?random=6">
120 <source media="(max-width: 1200px)" srcset="https://picsum.photos/600/600?random=6">
121 <img src="https://picsum.photos/800/800?random=6" alt="Bridge">
122 </picture>
123 <div class="gallery-overlay">
124 <h3>Bridge at sunset</h3>
125 <p>Architecture</p>
126 </div>
127 </div>
128 </div>
129 </div>
130 </section>
131
132 <!-- Lightbox -->
133 <div class="lightbox" id="lightbox">
134 <span class="lightbox-close">×</span>
135 <img class="lightbox-content" id="lightbox-img">
136 <div class="lightbox-caption"></div>
137 </div>
138
139 <script src="script.js"></script>
140</body>
141</html>Summary
This project demonstrates all the key concepts of responsive design:
- Mobile-First Approach - we start from mobile styles
- Media Queries - we adapt the layout for different devices
- Viewport Units (vw, vh) - for full-screen sections
- Responsive images - picture element with different sources
- CSS Grid - responsive gallery grid
- Flexbox - flexible navigation
- Clamp() - responsive font sizes
- Optimization - lazy loading, will-change, contain
- Accessibility - semantic HTML, aria-labels
- Modern features - dark mode, reduced motion
The HTML and CSS layer is ready and easy to adapt for other purposes, while the menu, the filters and the lightbox still need a short script. My advice: before you send the project to your mentor, check it at widths of 320, 768, 1024 and 1440 pixels.
Remember: a responsive gallery is a temple courtyard that holds both a handful of priests and a crowd of pilgrims, because its layout grows together with the screen.
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. Which grid-template-columns value creates a responsive grid?
2. How do you create a CSS Grid with three equal columns?
These are 2 of 4 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Click in order
Arrange the CSS code to create a Grid with 3 columns:
- Code editor
Create a responsive grid of Egyptian gods with Flexbox. HTML: <div class='pantheon'> + 6 <div class='god'>God X</div> + </div>. Base CSS (mobile): .pantheon {display: flex; flex-wrap: wrap; gap: 20px; padding: 20px;} .god {flex-basis: 100%; background: #FFD700; padding: 30px; text-align: center; border: 2px solid #8B4513;}. Tablet: @media (min-width: 768px) {.god {flex-basis: calc(50% - 10px);}}. Desktop: @media (min-width: 1024px) {.god {flex-basis: calc(33.33% - 14px);}}. Watch how the elements reorganize!
- Vertical ordering
Arrange the CSS Grid declaration with automatic column fitting (from activation to the minmax value):
- Code editor
Create an auto-responsive grid using repeat(auto-fit, minmax(250px, 1fr)).
- Code editor
Complete the CSS: add grid-template-columns and grid-template-areas properties for the mobile view (1 column), then in a media query (min-width: 768px) set a 2-column layout with sidebar and main side by side.
- Horizontal ordering
Arrange the elements to create a correct use of calc():
- Code editor
Create a Holy Grail Layout using CSS Grid. HTML: <div class='temple-layout'><header class='header'>Header</header><nav class='sidebar-left'>Left</nav><main class='main-content'>Content</main><aside class='sidebar-right'>Right</aside><footer class='footer'>Footer</footer></div>. CSS: .temple-layout {display: grid; grid-template-areas: 'header header header' 'sidebar-left main-content sidebar-right' 'footer footer footer'; grid-template-columns: 200px 1fr 200px; grid-template-rows: auto 1fr auto; min-height: 100vh; gap: 10px;} .header {grid-area: header; background: #FFD700; padding: 20px;} .sidebar-left {grid-area: sidebar-left; background: #F4E4C1; padding: 20px;} .main-content {grid-area: main-content; background: #FFF8DC; padding: 20px;} .sidebar-right {grid-area: sidebar-right; background: #F4E4C1; padding: 20px;} .footer {grid-area: footer; background: #FFD700; padding: 20px;}.
- Code editor
Create a responsive card grid of Egyptian gods. HTML: <div class='cards-grid'><div class='card'><h2>Ra</h2><p>God of the Sun</p></div><div class='card'><h2>Anubis</h2><p>God of the Dead</p></div><div class='card'><h2>Isis</h2><p>Goddess of Magic</p></div><div class='card'><h2>Horus</h2><p>God of the Sky</p></div><div class='card'><h2>Thoth</h2><p>God of Knowledge</p></div><div class='card'><h2>Bastet</h2><p>Goddess of Cats</p></div></div>. CSS: .cards-grid {display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; padding: 20px;} .card {background: #FFD700; padding: 30px; text-align: center; border: 2px solid #8B4513; border-radius: 10px;}.