This note is from 8 months ago. You're viewing content from a previous lesson.
At the start of every class, please:
<!DOCTYPE html>
<html lang="en">
<head>
<!--
TITLE: Tailwind "Club Website" — Single Contiguous, Heavily Commented File
READ THIS FIRST (Tailwind + Layout Guide):
• Utility-first CSS: You compose styles by stacking utility classes directly on elements.
• Mobile-first breakpoints (defaults): sm ≥640px, md ≥768px, lg ≥1024px, xl ≥1280px.
- Unprefixed classes apply to all sizes.
- sm:/md:/lg:/xl: add or override styles at that width and up.
• Core layout primitives you’ll see below:
- max-w-* + mx-auto → fixed-width centered page content
- px-* / py-* → horizontal / vertical padding
- flex + items-* + gap-*→ 1-D layout (rows/columns), alignment, spacing
- grid + *:grid-cols-* → 2-D layout (rows & columns), responsive column counts
- gap-* → gutter between grid/flex children
- col-span-* → how many columns a grid child spans
- sticky top-0 → stick an element to the top on scroll
- aspect-[W/H] → maintain aspect ratio boxes
• Mental model:
1) Build a good single-column mobile layout.
2) Add md:*, lg:* to enhance to multi-column on larger screens.
-->
<meta charset="utf-8" />
<!-- Ensures proper scaling on mobile devices -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Your Club – Home</title>
<!-- Tailwind via CDN (quick start). For production, prefer a build that purges unused CSS. -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Optional: sensible default font stack -->
<style>
:root { color-scheme: light dark; }
html { font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif; }
</style>
</head>
<!--
BODY:
• min-h-screen : at least full viewport height, lets the footer sit at the bottom on short pages
• bg-slate-50 : subtle light gray background
• text-slate-800 : high-contrast dark text for readability
-->
<body class="min-h-screen bg-slate-50 text-slate-800">
<!--
SKIP LINK (accessibility): invisible until focused by keyboard users
• sr-only : visually hidden off-screen
• focus:not-sr-only + focus:*: reveal and position when focused
-->
<a href="#main"
class="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 focus:bg-white focus:text-slate-900 focus:px-3 focus:py-2 focus:rounded focus:shadow">
Skip to main content
</a>
<!--
FULL-WIDTH ANNOUNCEMENT BAR:
• Spans the viewport because it is not inside a width-constrained container
• text-center: center the inline content within the bar
-->
<div class="bg-indigo-600 text-white text-sm text-center px-4 py-2">
Welcome back! First meeting of the semester: <strong>Wednesday @ 15:45, Room 204</strong>.
</div>
<!--
HEADER / NAV:
• bg-white border-b : visual separation from page content
• sticky top-0 z-50 : keeps header pinned during scroll and above other content
INNER CONTAINER:
• max-w-6xl mx-auto : fixed max width and center on the page
• px-4 : horizontal padding so content doesn’t touch viewport edges
• h-16 flex items-center justify-between : 1-D row layout with vertical centering and space-between
-->
<header class="bg-white border-b sticky top-0 z-50">
<nav class="max-w-6xl mx-auto px-4 h-16 flex items-center justify-between" aria-label="Primary">
<!-- BRAND GROUP (inline flex) -->
<a href="#" class="flex items-center gap-2 focus:outline-none focus:ring-2 focus:ring-indigo-600 rounded">
<span class="inline-block w-8 h-8 rounded-full bg-indigo-600" aria-hidden="true"></span>
<span class="font-semibold">Your Club</span>
</a>
<!-- DESKTOP NAV LINKS:
• hidden md:flex: collapsed on small screens; becomes flex row at md+ (≥768px)
• items-center gap-6 text-sm: horizontally aligned items with 1.5rem gaps and compact type
-->
<div class="hidden md:flex items-center gap-6 text-sm">
<a href="#about" class="hover:text-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-600 rounded px-1">About</a>
<a href="#events" class="hover:text-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-600 rounded px-1">Events</a>
<a href="#officers" class="hover:text-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-600 rounded px-1">Officers</a>
<a href="#join" class="hover:text-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-600 rounded px-1">Join</a>
<a href="#join"
class="inline-flex items-center rounded-lg bg-indigo-600 px-3 py-2 font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-600">
Become a member
</a>
</div>
<!-- MOBILE MENU BUTTON (visible only below md) -->
<button type="button"
class="md:hidden inline-flex items-center justify-center rounded-lg border border-slate-300 px-2.5 py-2 hover:bg-slate-100 focus:outline-none focus:ring-2 focus:ring-indigo-600"
aria-controls="mobile-menu"
aria-expanded="false"
id="mobile-menu-button">
<span class="sr-only">Open menu</span>
<span class="block w-5 h-0.5 bg-slate-800 mb-1"></span>
<span class="block w-5 h-0.5 bg-slate-800 mb-1"></span>
<span class="block w-5 h-0.5 bg-slate-800"></span>
</button>
</nav>
<!--
MOBILE COLLAPSIBLE MENU:
• md:hidden : only present below md breakpoint
• hidden : start closed; toggled by JS to show/hide
• Links are block-level so they stack vertically and are easy to tap
-->
<div id="mobile-menu" class="md:hidden hidden px-4 py-2 border-t bg-white" role="region" aria-label="Mobile">
<a href="#about" class="block rounded px-2 py-2 hover:bg-slate-100">About</a>
<a href="#events" class="block rounded px-2 py-2 hover:bg-slate-100">Events</a>
<a href="#officers" class="block rounded px-2 py-2 hover:bg-slate-100">Officers</a>
<a href="#join" class="block rounded px-2 py-2 hover:bg-slate-100">Join</a>
<a href="#join"
class="mt-1 inline-flex w-full items-center justify-center rounded-lg bg-indigo-600 px-3 py-2 font-medium text-white hover:bg-indigo-700">
Become a member
</a>
</div>
</header>
<!--
HERO SECTION (INTRO PANEL)
LAYOUT: RESPONSIVE GRID
• max-w-6xl mx-auto px-4 : centered, constrained container with side padding
• py-12 md:py-16 : vertical rhythm (more space on larger screens)
• grid : turns the section into a 2-D layout context
• md:grid-cols-2 : at md+ → two columns; on mobile (default) → single column
• gap-8 : gutters between the two grid children (text & image)
• items-center : vertically center grid items within their rows
RESULT:
• Mobile: Text ABOVE image (natural source order).
• Desktop: Text left, image right (two columns).
-->
<section class="max-w-6xl mx-auto px-4 py-12 md:py-16 grid md:grid-cols-2 gap-8 items-center">
<!-- LEFT: TEXT (grid item #1) -->
<div>
<h1 class="text-3xl md:text-4xl font-bold leading-tight">
Build, Learn, and Compete with <span class="text-indigo-700">Your Club</span>
</h1>
<p class="mt-4 text-slate-600">
We’re a community of students who meet weekly to collaborate, learn new skills, and run fun events.
Everyone is welcome—no experience required.
</p>
<!-- Simple button row using flex (independent from grid above) -->
<div class="mt-6 flex flex-wrap gap-3">
<a href="#join"
class="rounded-lg bg-indigo-600 px-4 py-2 font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-600">
Join the club
</a>
<a href="#events"
class="rounded-lg border border-slate-300 px-4 py-2 font-medium hover:bg-slate-100 focus:outline-none focus:ring-2 focus:ring-indigo-600">
See upcoming events
</a>
</div>
</div>
<!-- RIGHT: IMAGE / ILLUSTRATION (grid item #2) -->
<!--
aspect-[16/10] : preserves a 16:10 box ratio (prevents layout shift before image loads)
rounded-2xl : soft corners
shadow : mild elevation
bg-gradient-* : decorative gradient for the placeholder
flex items-center justify-center : centers the placeholder glyph
Replace the span with a real <img> later.
-->
<div class="aspect-[16/10] rounded-2xl shadow bg-gradient-to-br from-indigo-50 to-slate-100 flex items-center justify-center">
<span class="text-6xl" aria-hidden="true">★</span>
<span class="sr-only">Club illustration</span>
</div>
</section>
<!-- MAIN CONTENT -->
<main id="main" tabindex="-1">
<!-- ABOUT SECTION -->
<!--
GRID OF FEATURE CARDS:
• grid : enable 2-D layout
• sm:grid-cols-2 : 2 columns from 640px+
• lg:grid-cols-3 : 3 columns from 1024px+
• gap-6 : gutters between cards
EFFECT:
• Mobile: 1 column (cards stack)
• Small tablets: 2 columns
• Laptops+: 3 columns
-->
<section id="about" class="max-w-6xl mx-auto px-4 py-12">
<h2 class="text-2xl font-semibold">About the Club</h2>
<p class="mt-3 text-slate-700 leading-relaxed">
Our mission is to create a welcoming space for students to explore interests, develop leadership,
and build lasting friendships. We meet every <strong>Wednesday</strong> after school.
</p>
<div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
<div class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<h3 class="font-semibold">Learn</h3>
<p class="mt-2 text-sm text-slate-600">
Beginner-friendly sessions and advanced workshops to grow your skills step by step.
</p>
</div>
<div class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<h3 class="font-semibold">Build</h3>
<p class="mt-2 text-sm text-slate-600">
Work on real projects together. Present your work at the end of term showcases.
</p>
</div>
<div class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<h3 class="font-semibold">Compete</h3>
<p class="mt-2 text-sm text-slate-600">
Friendly in-club competitions and events to challenge yourself and have fun.
</p>
</div>
</div>
</section>
<!-- EVENTS SECTION -->
<!--
TWO-COLUMN CARD LIST ON MD+:
• grid md:grid-cols-2 : 1 column on mobile, 2 columns from md (≥768px)
• gap-6 : space between the two columns and rows
Each article card is a grid child; inside the card we use flex to align header elements.
-->
<section id="events" class="max-w-6xl mx-auto px-4 py-12">
<h2 class="text-2xl font-semibold">Upcoming Events</h2>
<p class="mt-3 text-slate-700">Here’s what’s happening next.</p>
<div class="mt-8 grid gap-6 md:grid-cols-2">
<article class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<!-- Nested flex row inside a grid item -->
<div class="flex items-start justify-between gap-4">
<div>
<h3 class="font-semibold">Welcome & Kickoff</h3>
<p class="text-sm text-slate-600 mt-1">Wed, Sep 24 · Room 204</p>
</div>
<div class="shrink-0 rounded-lg bg-indigo-50 px-3 py-1 text-xs font-medium text-indigo-700">Week 1</div>
</div>
<p class="mt-3 text-sm text-slate-700">
Meet the officers, plan the term, and share your goals. Snacks provided.
</p>
<a href="#" class="mt-4 inline-block text-sm font-medium text-indigo-700 hover:underline">Details</a>
</article>
<article class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<div class="flex items-start justify-between gap-4">
<div>
<h3 class="font-semibold">Project Sprint</h3>
<p class="text-sm text-slate-600 mt-1">Wed, Oct 1 · Room 204</p>
</div>
<div class="shrink-0 rounded-lg bg-indigo-50 px-3 py-1 text-xs font-medium text-indigo-700">Week 2</div>
</div>
<p class="mt-3 text-sm text-slate-700">
Form small teams and start building. Mentors available for guidance.
</p>
<a href="#" class="mt-4 inline-block text-sm font-medium text-indigo-700 hover:underline">Details</a>
</article>
</div>
</section>
<!-- OFFICERS SECTION -->
<!--
RESPONSIVE GRID 2→3 COLUMNS:
• grid sm:grid-cols-2 md:grid-cols-3 : 1 col on mobile, 2 on small screens, 3 on md+
• gap-6 : gutters between cards
-->
<section id="officers" class="max-w-6xl mx-auto px-4 py-12">
<h2 class="text-2xl font-semibold">Club Officers</h2>
<p class="mt-3 text-slate-700">Reach out if you have questions or ideas.</p>
<div class="mt-8 grid gap-6 sm:grid-cols-2 md:grid-cols-3">
<div class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<div class="w-14 h-14 rounded-full bg-slate-200"></div>
<h3 class="mt-3 font-semibold">Alex Johnson</h3>
<p class="text-sm text-slate-600">President</p>
<a href="mailto:[email protected]" class="mt-2 inline-block text-sm text-indigo-700 hover:underline">[email protected]</a>
</div>
<div class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<div class="w-14 h-14 rounded-full bg-slate-200"></div>
<h3 class="mt-3 font-semibold">Brianna Lee</h3>
<p class="text-sm text-slate-600">Vice President</p>
<a href="mailto:[email protected]" class="mt-2 inline-block text-sm text-indigo-700 hover:underline">[email protected]</a>
</div>
<div class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
<div class="w-14 h-14 rounded-full bg-slate-200"></div>
<h3 class="mt-3 font-semibold">Carlos Diaz</h3>
<p class="text-sm text-slate-600">Secretary</p>
<a href="mailto:[email protected]" class="mt-2 inline-block text-sm text-indigo-700 hover:underline">[email protected]</a>
</div>
</div>
</section>
<!-- JOIN / CONTACT FORM -->
<!--
FORM LAYOUT WITH GRID:
• max-w-3xl mx-auto : narrower centered container (forms are easier to read when narrow)
• Inside the form:
- grid gap-4 : place fields on a grid with vertical/horizontal spacing
- md:grid-cols-2 : at md+, use two columns for some fields (first/last name)
- md:col-span-2 : make a field span both columns (email, interests, checkbox row)
WHY GRID HERE:
• Grid makes aligning multi-column forms precise and responsive.
-->
<section id="join" class="max-w-3xl mx-auto px-4 py-12">
<h2 class="text-2xl font-semibold">Join the Club</h2>
<p class="mt-3 text-slate-700">Fill out this quick form and we’ll contact you with details.</p>
<form class="mt-8 rounded-xl border border-slate-200 bg-white p-6 shadow-sm" action="#" method="post">
<div class="grid gap-4 md:grid-cols-2">
<div>
<label for="first_name" class="block text-sm font-medium">First name</label>
<input id="first_name" name="first_name" type="text" required
class="mt-1 block w-full rounded-lg border border-slate-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-600"
placeholder="Ada" />
</div>
<div>
<label for="last_name" class="block text-sm font-medium">Last name</label>
<input id="last_name" name="last_name" type="text" required
class="mt-1 block w-full rounded-lg border border-slate-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-600"
placeholder="Lovelace" />
</div>
<!-- Spans across both columns at md+ -->
<div class="md:col-span-2">
<label for="email" class="block text-sm font-medium">Email</label>
<input id="email" name="email" type="email" required
class="mt-1 block w-full rounded-lg border border-slate-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-600"
placeholder="[email protected]" />
</div>
<!-- Spans across both columns at md+ -->
<div class="md:col-span-2">
<label for="interests" class="block text-sm font-medium">Interests</label>
<textarea id="interests" name="interests" rows="4"
class="mt-1 block w-full rounded-lg border border-slate-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-600"
placeholder="Tell us what you’re excited to do..."></textarea>
</div>
<!-- Spans across both columns at md+; checkbox row uses flex for alignment -->
<div class="md:col-span-2 flex items-center gap-2">
<input id="newsletter" name="newsletter" type="checkbox"
class="h-4 w-4 rounded border-slate-300 focus:outline-none focus:ring-2 focus:ring-indigo-600" />
<label for="newsletter" class="text-sm">Subscribe to updates</label>
</div>
</div>
<div class="mt-6 flex items-center gap-3">
<button type="submit"
class="rounded-lg bg-indigo-600 px-4 py-2 font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-600">
Submit
</button>
<p class="text-sm text-slate-600">We’ll never share your email.</p>
</div>
</form>
</section>
</main>
<!-- FOOTER -->
<!--
PAGE-EDGE SEPARATOR + FLEX WRAP:
• bg-white border-t : visually separates footer from content above
• Inside container: max-w-6xl mx-auto px-4 py-8
• flex flex-wrap items-center justify-between gap-4 :
- becomes a single row on wide screens
- wraps onto multiple rows on narrow screens
-->
<footer class="bg-white border-t">
<div class="max-w-6xl mx-auto px-4 py-8 flex flex-wrap items-center justify-between gap-4">
<p class="text-sm text-slate-600">
© <span id="year"></span> Your Club. All rights reserved.
</p>
<div class="flex items-center gap-4 text-sm">
<a href="#" class="hover:text-indigo-700">Code of Conduct</a>
<a href="#" class="hover:text-indigo-700">Privacy</a>
<a href="#" class="hover:text-indigo-700">Contact</a>
</div>
</div>
</footer>
<!--
TINY VANILLA JS:
• Toggles mobile menu visibility by adding/removing the "hidden" class
• Updates © year automatically
-->
<script>
(function () {
const btn = document.getElementById('mobile-menu-button');
const menu = document.getElementById('mobile-menu');
btn?.addEventListener('click', () => {
const isOpen = !menu.classList.contains('hidden');
menu.classList.toggle('hidden');
btn.setAttribute('aria-expanded', String(!isOpen));
});
const year = document.getElementById('year');
if (year) year.textContent = new Date().getFullYear();
})();
</script>
</body>
</html>