← Back to course

Mini Projekt Końcowy: Responsive Landing Page

Mini Projekt Końcowy: Responsive Landing Page

Witaj w ostatniej lekcji tego kursu CSS.

Dotarłeś tutaj.

Twój browser przeżył.

Twój CSS przeżył.

Prawdopodobnie.

W tej lekcji połączymy wszystko, czego nauczyłeś się wcześniej, w jeden mini projekt.

Zbudujemy responsive landing page.

Będzie zawierać:

Tutaj CSS przestaje być zbiorem losowych properties i zaczyna wyglądać jak prawdziwa strona.

Małe kawałki CSS wreszcie spotykają się razem.

Jak frontendowa kolacja rodzinna.

Oby z mniejszą liczbą kłótni.

Co Zbudujesz

Stworzysz landing page dla fikcyjnej usługi webowej o nazwie FastSite Studio.

Strona będzie miała:

Ten projekt używa wielu rzeczy z poprzednich lekcji:

Dzisiaj nie ma nowego potwora.

Tylko składamy narzędzia razem.

Jak montowanie mebli, ale z mniejszą liczbą tajemniczych śrubek.

Stwórz Projekt

Stwórz folder dla końcowego projektu:

mkdir css-lesson10
cd css-lesson10
touch index.html
touch style.css

Powinieneś mieć:

css-lesson10/
  index.html
  style.css

Otwórz folder w swoim editor.

To jest nasz final CSS playground.

Bez strachu.

Tylko semicolons.

I może jeden dramatyczny refresh.

Napisz HTML

Otwórz index.html i dodaj to:

<!DOCTYPE html>
<html lang="pl">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>FastSite Studio</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="hero">
    <nav class="navbar">
      <h1 class="logo">FastSite Studio</h1>

      <div class="nav-links">
        <a href="#">Home</a>
        <a href="#">Funkcje</a>
        <a href="#">Cennik</a>
        <a href="#">Kontakt</a>
      </div>
    </nav>

    <section class="hero-content">
      <p class="eyebrow">Modern CSS Project</p>
      <h2>Zbuduj Szybką, Czystą i Responsive Stronę</h2>
      <p>
        Przećwicz CSS layout, responsive design, cards, buttons, shadows i transitions w jednym kompletnym mini projekcie.
      </p>

      <div class="hero-actions">
        <a href="#" class="button primary-button">Zacznij Budować</a>
        <a href="#" class="button secondary-button">Zobacz Funkcje</a>
      </div>
    </section>
  </header>

  <main>
    <section class="section intro-section">
      <div class="section-header">
        <p class="eyebrow dark">Co Ćwiczysz</p>
        <h2>Tutaj Wszystko Się Łączy</h2>
        <p>
          Ten projekt łączy najważniejsze początkujące umiejętności CSS w layout, który możesz wykorzystać na prawdziwych stronach.
        </p>
      </div>

      <div class="feature-grid">
        <article class="feature-card">
          <div class="icon">⚡</div>
          <h3>Szybki Layout</h3>
          <p>Użyj Grid i Flexbox, aby tworzyć sekcje czyste, uporządkowane i łatwe do modyfikacji.</p>
        </article>

        <article class="feature-card">
          <div class="icon">📱</div>
          <h3>Responsive Design</h3>
          <p>Spraw, żeby strona dopasowywała się do laptopów, tabletów i telefonów bez chaosu poziomego scrolla.</p>
        </article>

        <article class="feature-card">
          <div class="icon">🎨</div>
          <h3>Polished Styling</h3>
          <p>Dodaj colors, borders, shadows, spacing i hover effects, żeby strona wyglądała na skończoną.</p>
        </article>
      </div>
    </section>

    <section class="section pricing-section">
      <div class="section-header">
        <p class="eyebrow dark">Cennik</p>
        <h2>Wybierz Swoją CSS Przygodę</h2>
        <p>
          Te pricing cards są tylko ćwiczeniem, ale ten layout pattern jest używany na prawdziwych landing pages wszędzie.
        </p>
      </div>

      <div class="pricing-grid">
        <article class="pricing-card">
          <h3>Basic</h3>
          <p class="price">€99</p>
          <p>Idealny do ćwiczenia podstaw layoutu.</p>
          <ul>
            <li>One-page layout</li>
            <li>Proste cards</li>
            <li>Basic responsive design</li>
          </ul>
          <a href="#" class="button card-button">Wybierz Basic</a>
        </article>

        <article class="pricing-card featured-card">
          <p class="badge">Popularne</p>
          <h3>Standard</h3>
          <p class="price">€199</p>
          <p>Najlepszy do budowania polished responsive page.</p>
          <ul>
            <li>Responsive sections</li>
            <li>Cards i buttons</li>
            <li>Hover transitions</li>
          </ul>
          <a href="#" class="button card-button">Wybierz Standard</a>
        </article>

        <article class="pricing-card">
          <h3>Premium</h3>
          <p class="price">€299</p>
          <p>Dla momentu, kiedy twój CSS jest gotowy założyć garnitur.</p>
          <ul>
            <li>Advanced layout</li>
            <li>Polished visual style</li>
            <li>Reusable structure</li>
          </ul>
          <a href="#" class="button card-button">Wybierz Premium</a>
        </article>
      </div>
    </section>
  </main>

  <footer class="site-footer">
    <p>Stworzone z HTML, CSS, cierpliwością i kilkoma odważnymi średnikami.</p>
  </footer>
</body>
</html>

Ten HTML daje nam pełną strukturę.

Teraz potrzebujemy CSS.

Na razie strona to raw HTML.

Użyteczne, ale bez uroku.

Jak makaron bez sosu.

Technicznie jedzenie.

Emocjonalnie niedokończone.

Dodaj Bazowe Style

Otwórz style.css i dodaj:

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f3f4f6;
  color: #111827;
}

a {
  color: inherit;
  text-decoration: none;
}

ul {
  padding-left: 20px;
}

To daje nam:

Dobra baza.

Final project potrzebuje stabilnej podstawy.

Inaczej CSS zaczyna zachowywać się jak wózek sklepowy z jednym zepsutym kółkiem.

Stylizuj Hero

Dodaj:

.hero {
  background: linear-gradient(135deg, #111827, #1e3a8a);
  color: white;
}

To tworzy dark hero background.

Teraz stylizuj navbar:

.navbar {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.logo {
  margin: 0;
  font-size: 24px;
}

.nav-links {
  display: flex;
  gap: 20px;
  font-weight: 700;
}

Navbar używa teraz Flexbox.

Logo po lewej.

Links po prawej.

Clean.

Simple.

Na tyle profesjonalne, że CSS może poprosić o profil LinkedIn.

Stylizuj Hero Content

Dodaj:

.hero-content {
  max-width: 850px;
  margin: 0 auto;
  padding: 90px 24px 110px;
  text-align: center;
}

.eyebrow {
  margin: 0 0 16px;
  color: #bfdbfe;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.hero-content h2 {
  margin: 0 0 20px;
  font-size: 58px;
  line-height: 1.1;
}

.hero-content p {
  margin: 0 auto;
  max-width: 700px;
  color: #dbeafe;
  font-size: 20px;
  line-height: 1.7;
}

Teraz hero ma:

To jest visual hierarchy.

User widzi najpierw to, co najważniejsze.

Heading first.

Text second.

Button next.

Dobry layout nie zmusza usera do szukania sensu z latarką.

Stylizuj Buttons

Dodaj:

.hero-actions {
  display: flex;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 28px;
}

.button {
  display: inline-block;
  padding: 14px 22px;
  border-radius: 999px;
  font-weight: 700;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.button:hover {
  transform: translateY(-3px);
}

.primary-button {
  background-color: white;
  color: #1e3a8a;
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.22);
}

.secondary-button {
  border: 2px solid rgba(255, 255, 255, 0.5);
  color: white;
}

Teraz hero ma dwa buttons.

Jeden primary.

Jeden secondary.

Primary button jest mocniejszy.

Secondary button jest spokojniejszy.

To ważne.

Nie każdy button powinien krzyczeć.

Jeśli każdy button krzyczy, page staje się meetingiem, gdzie wszyscy mówią naraz.

Koszmar.

Stwórz Reusable Section Styles

Dodaj:

.section {
  max-width: 1100px;
  margin: 0 auto;
  padding: 72px 24px;
}

.section-header {
  max-width: 760px;
  margin: 0 auto 36px;
  text-align: center;
}

.eyebrow.dark {
  color: #2563eb;
}

.section-header h2 {
  margin: 0 0 16px;
  font-size: 38px;
  line-height: 1.2;
}

.section-header p {
  color: #4b5563;
  font-size: 18px;
  line-height: 1.7;
}

Teraz sections mają consistent spacing.

Consistency ma znaczenie.

Website z random spacing wygląda nerwowo.

Jakby CSS próbował sobie przypomnieć, gdzie zaparkował samochód.

Stwórz Feature Cards

Dodaj:

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.feature-card {
  background-color: white;
  padding: 28px;
  border: 2px solid #e5e7eb;
  border-radius: 24px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.06);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.feature-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.1);
}

.icon {
  width: 52px;
  height: 52px;
  border-radius: 18px;
  background-color: #dbeafe;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin-bottom: 18px;
}

.feature-card h3 {
  margin: 0 0 12px;
  font-size: 24px;
}

.feature-card p {
  color: #4b5563;
  font-size: 18px;
  line-height: 1.7;
}

To używa CSS Grid dla cards.

Three columns na desktop.

Nice spacing.

Soft shadows.

Hover movement.

Page zaczyna wyglądać, jakby wiedziała, co robi.

Niebezpiecznie professional.

Stylizuj Pricing Section

Dodaj:

.pricing-section {
  padding-top: 40px;
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.pricing-card {
  position: relative;
  background-color: white;
  padding: 32px;
  border: 2px solid #e5e7eb;
  border-radius: 28px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.06);
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.pricing-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.1);
  border-color: #2563eb;
}

.pricing-card h3 {
  margin: 0 0 12px;
  font-size: 26px;
}

.price {
  margin: 0 0 16px;
  font-size: 42px;
  font-weight: 800;
  color: #1e3a8a;
}

.pricing-card p {
  color: #4b5563;
  font-size: 18px;
  line-height: 1.6;
}

.pricing-card li {
  margin-bottom: 8px;
  color: #374151;
}

Teraz pricing cards wyglądają structured.

Price jest duży.

Text readable.

Cards mają depth.

Pricing card musi być easy to scan.

Users nie powinni potrzebować mapy skarbów, żeby znaleźć cenę.

Featured Pricing Card

Dodaj:

.featured-card {
  border-color: #2563eb;
  background-color: #eff6ff;
}

.badge {
  display: inline-block;
  margin: 0 0 16px;
  background-color: #2563eb;
  color: white !important;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 14px !important;
  font-weight: 700;
}

Middle card teraz się wyróżnia.

Ma badge.

Ma blue border.

Ma soft blue background.

Mówi:

“Spójrz tutaj.”

Nie:

“PATRZ TUTAJ, BO ZARAZ ZACZNĘ MIGAĆ.”

Dobrze.

Card Buttons

Dodaj:

.card-button {
  margin-top: 18px;
  background-color: #2563eb;
  color: white;
  text-align: center;
  width: 100%;
}

.card-button:hover {
  box-shadow: 0 12px 25px rgba(37, 99, 235, 0.3);
}

Teraz każda pricing card ma full-width button.

To common pattern w pricing sections.

Easy to click.

Easy to understand.

No mystery.

Mystery jest dobre dla detective novels.

Nie dla pricing cards.

Footer

Dodaj:

.site-footer {
  text-align: center;
  padding: 36px 24px;
  color: #6b7280;
}

Simple footer.

No drama.

Final projects nie potrzebują dramatic footers.

Footer nie jest main character.

Zrób To Responsive

Teraz dodaj media queries.

Najpierw dla tablets:

@media (max-width: 850px) {
  .hero-content h2 {
    font-size: 44px;
  }

  .feature-grid,
  .pricing-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

Teraz cards stają się two columns na medium screens.

Potem dla phones:

@media (max-width: 600px) {
  .navbar {
    flex-direction: column;
    align-items: flex-start;
  }

  .nav-links {
    flex-direction: column;
    gap: 12px;
  }

  .hero-content {
    text-align: left;
    padding: 64px 20px 80px;
  }

  .hero-content h2 {
    font-size: 36px;
  }

  .hero-content p {
    font-size: 18px;
  }

  .hero-actions {
    justify-content: flex-start;
  }

  .section {
    padding: 56px 20px;
  }

  .section-header {
    text-align: left;
  }

  .section-header h2 {
    font-size: 30px;
  }

  .feature-grid,
  .pricing-grid {
    grid-template-columns: 1fr;
  }
}

Teraz page działa na phones.

Navbar stacks.

Cards stają się one column.

Text gets smaller.

Spacing becomes more compact.

To responsive design doing its job.

No sideways scrolling.

No tiny unreadable cards.

No user rage.

Excellent.

Dodaj Reduced Motion Support

Dodaj to na końcu:

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none;
  }
}

To pomaga users, którzy wolą less motion.

To mały detail.

Ale good websites care about details.

I users.

Mostly users.

CSS istnieje dla ludzi, nie tylko dla screenshots.

Pełny CSS

Twój style.css powinien wyglądać tak:

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f3f4f6;
  color: #111827;
}

a {
  color: inherit;
  text-decoration: none;
}

ul {
  padding-left: 20px;
}

.hero {
  background: linear-gradient(135deg, #111827, #1e3a8a);
  color: white;
}

.navbar {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.logo {
  margin: 0;
  font-size: 24px;
}

.nav-links {
  display: flex;
  gap: 20px;
  font-weight: 700;
}

.hero-content {
  max-width: 850px;
  margin: 0 auto;
  padding: 90px 24px 110px;
  text-align: center;
}

.eyebrow {
  margin: 0 0 16px;
  color: #bfdbfe;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.hero-content h2 {
  margin: 0 0 20px;
  font-size: 58px;
  line-height: 1.1;
}

.hero-content p {
  margin: 0 auto;
  max-width: 700px;
  color: #dbeafe;
  font-size: 20px;
  line-height: 1.7;
}

.hero-actions {
  display: flex;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 28px;
}

.button {
  display: inline-block;
  padding: 14px 22px;
  border-radius: 999px;
  font-weight: 700;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.button:hover {
  transform: translateY(-3px);
}

.primary-button {
  background-color: white;
  color: #1e3a8a;
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.22);
}

.secondary-button {
  border: 2px solid rgba(255, 255, 255, 0.5);
  color: white;
}

.section {
  max-width: 1100px;
  margin: 0 auto;
  padding: 72px 24px;
}

.section-header {
  max-width: 760px;
  margin: 0 auto 36px;
  text-align: center;
}

.eyebrow.dark {
  color: #2563eb;
}

.section-header h2 {
  margin: 0 0 16px;
  font-size: 38px;
  line-height: 1.2;
}

.section-header p {
  color: #4b5563;
  font-size: 18px;
  line-height: 1.7;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.feature-card {
  background-color: white;
  padding: 28px;
  border: 2px solid #e5e7eb;
  border-radius: 24px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.06);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.feature-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.1);
}

.icon {
  width: 52px;
  height: 52px;
  border-radius: 18px;
  background-color: #dbeafe;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin-bottom: 18px;
}

.feature-card h3 {
  margin: 0 0 12px;
  font-size: 24px;
}

.feature-card p {
  color: #4b5563;
  font-size: 18px;
  line-height: 1.7;
}

.pricing-section {
  padding-top: 40px;
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.pricing-card {
  position: relative;
  background-color: white;
  padding: 32px;
  border: 2px solid #e5e7eb;
  border-radius: 28px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.06);
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.pricing-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.1);
  border-color: #2563eb;
}

.pricing-card h3 {
  margin: 0 0 12px;
  font-size: 26px;
}

.price {
  margin: 0 0 16px;
  font-size: 42px;
  font-weight: 800;
  color: #1e3a8a;
}

.pricing-card p {
  color: #4b5563;
  font-size: 18px;
  line-height: 1.6;
}

.pricing-card li {
  margin-bottom: 8px;
  color: #374151;
}

.featured-card {
  border-color: #2563eb;
  background-color: #eff6ff;
}

.badge {
  display: inline-block;
  margin: 0 0 16px;
  background-color: #2563eb;
  color: white !important;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 14px !important;
  font-weight: 700;
}

.card-button {
  margin-top: 18px;
  background-color: #2563eb;
  color: white;
  text-align: center;
  width: 100%;
}

.card-button:hover {
  box-shadow: 0 12px 25px rgba(37, 99, 235, 0.3);
}

.site-footer {
  text-align: center;
  padding: 36px 24px;
  color: #6b7280;
}

@media (max-width: 850px) {
  .hero-content h2 {
    font-size: 44px;
  }

  .feature-grid,
  .pricing-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 600px) {
  .navbar {
    flex-direction: column;
    align-items: flex-start;
  }

  .nav-links {
    flex-direction: column;
    gap: 12px;
  }

  .hero-content {
    text-align: left;
    padding: 64px 20px 80px;
  }

  .hero-content h2 {
    font-size: 36px;
  }

  .hero-content p {
    font-size: 18px;
  }

  .hero-actions {
    justify-content: flex-start;
  }

  .section {
    padding: 56px 20px;
  }

  .section-header {
    text-align: left;
  }

  .section-header h2 {
    font-size: 30px;
  }

  .feature-grid,
  .pricing-grid {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none;
  }
}

Zapisz file.

Odśwież browser.

Zmień rozmiar window.

Najedź mouse na cards i buttons.

Masz teraz complete responsive landing page.

Gratulacje.

To już nie jest tylko CSS practice.

To reusable website structure.

Możesz użyć tego patternu dla:

Teraz twój CSS ma pracę.

Wreszcie.

Co Przećwiczyłeś

W tym final project przećwiczyłeś:

To dużo.

Nie udawaj, że to nic.

CSS wygląda prosto, dopóki nie zaczyna kłócić się z screen size.

Poradziłeś sobie z tym.

Dobrze.

Typowe Błędy

Próba Zrobienia Wszystkiego Perfekcyjnie Od Razu

Nie próbuj zrobić page perfect przy pierwszej próbie.

Buduj etapami:

  1. HTML structure.
  2. Base CSS.
  3. Layout.
  4. Cards.
  5. Responsive design.
  6. Polish.

Jeśli próbujesz zrobić wszystko naraz, CSS wyczuje strach.

Zapomnienie o Mobile

Zawsze resize browser.

Zawsze testuj smaller screens.

Page, która działa tylko na desktop, nie jest finished.

Ona tylko udaje.

Dodanie Zbyt Dużo Decoration

Clean page jest lepsza niż noisy page.

Używaj:

Nie potrzebujesz 19 gradients i buttona, który tańczy jakby słyszał muzykę.

Mini Wyzwanie

Dostosuj ten projekt.

Zmień:

Potem zrób z tego swoją landing page.

Możesz zamienić ją w:

Tak zaczynają się real web projects.

Simple structure.

Then customization.

Then improvement.

Then coffee.

Podsumowanie

Ukończyłeś CSS course.

Nauczyłeś się:

CSS to nie tylko decoration.

CSS to layout.

Structure.

Readability.

Responsiveness.

User experience.

I czasem emotional damage.

Ale teraz jesteś mocniejszy.

Ostatnie Słowa

Ćwicz dalej.

Weź ten project i odbuduj go z pamięci.

Potem zmień go.

Zepsuj go.

Napraw go.

Zrób następny.

Tak CSS staje się naturalny.

Nie przez czytanie tysiąca properties.

Tylko przez budowanie rzeczy, aż twoje palce same wiedzą, gdzie mieszka display: grid.

Gratulacje.

Twoja CSS toolbox jest gotowa.

Teraz idź zbudować coś fast, clean, responsive i trochę mniej chaotic, niż internet na to zasługuje.