Kurs HTML i CSS · Moduł 9: Nowoczesny CSS
Modern CSS Features - przyszłość stylow ania egipskich hieroglifów
W tej lekcji12
Witaj w przyszłości CSS! Podobnie jak starożytni Egipcjanie byli pionierami w architekturze, tak my jesteśmy świadkami rewolucji w CSS. Poznaj nowoczesne funkcje CSS z lat 2020-2024, które zmieniają sposób, w jaki stylujemy strony internetowe!
aspect-ratio - idealne proporcje
aspect-ratio pozwala na łatwe tworzenie elementów z zachowanymi proporcjami bez hacków z padding!
Przed aspect-ratio (stary sposób)
/* Stary hack z padding-bottom */
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 = 9/16 = 0.5625 = 56.25% */
height: 0;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}Z aspect-ratio (nowy sposób)
/* Nowoczesny sposób - prosty i czytelny */
.video-container {
aspect-ratio: 16 / 9;
width: 100%;
}
.video-container iframe {
width: 100%;
height: 100%;
}Analogia egipska: To jak idealne proporcje Wielkiej Piramidy (4:3) - zachowane niezależnie od skali!
Praktyczne przykłady aspect-ratio
1. Video responsive
.video-wrapper {
aspect-ratio: 16 / 9;
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.video-wrapper iframe {
width: 100%;
height: 100%;
border: none;
}2. Image cards
.card-image {
aspect-ratio: 4 / 3;
width: 100%;
object-fit: cover;
border-radius: 8px;
}3. Square avatars
.avatar {
aspect-ratio: 1; /* 1:1 = kwadrat */
width: 100px;
border-radius: 50%;
object-fit: cover;
}4. Golden ratio
.golden-box {
aspect-ratio: 1.618; /* Złoty podział */
width: 100%;
background: goldenrod;
}5. Instagram post
.instagram-post {
aspect-ratio: 1 / 1; /* Kwadrat Instagram */
width: 100%;
max-width: 600px;
}6. Mobile screens
.phone-mockup {
aspect-ratio: 9 / 19.5; /* Proporcje iPhone */
width: 375px;
border: 10px solid black;
border-radius: 30px;
}gap dla Flexbox i Grid
gap działa teraz zarówno w Grid jak i Flexbox! (od 2021)
/* Grid - od zawsze */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px; /* Row i column gap */
}
/* Flexbox - od 2021! */
.flex-container {
display: flex;
gap: 20px; /* Odstęp między items */
}Praktyczne przykłady gap
/* Navigation z gap */
.nav {
display: flex;
gap: 1.5rem;
align-items: center;
}
/* Button group */
.button-group {
display: flex;
gap: 0.5rem;
}
/* Form fields */
.form {
display: flex;
flex-direction: column;
gap: 1rem;
}
/* Card grid */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem 1rem; /* 2rem row, 1rem column */
}:is() i :where() - grupowanie selektorów
Nowe pseudo-classes pozwalają na eleganckie grupowanie!
:is() - z wagą specificity
/* Zamiast: */
h1 a,
h2 a,
h3 a,
h4 a,
h5 a,
h6 a {
color: goldenrod;
}
/* Użyj :is() */
:is(h1, h2, h3, h4, h5, h6) a {
color: goldenrod;
}Specificity :is(): Bierze najwyższą specificity z listy!
/* Specificity = ID (100) */
:is(#id, .class, div) {
color: red;
}:where() - bez wagi specificity
/* Specificity = 0! */
:where(h1, h2, h3) {
margin-top: 0;
}
/* Łatwo nadpisać */
h2 {
margin-top: 1rem; /* To wygra, bo :where() ma 0 specificity */
}Praktyczne przykłady
/* Reset dla headings */
:where(h1, h2, h3, h4, h5, h6) {
margin: 0;
font-weight: 600;
}
/* Link states */
:is(a:hover, a:focus) {
text-decoration: underline;
color: goldenrod;
}
/* Form inputs */
:is(input, textarea, select):focus {
outline: 2px solid #3498db;
outline-offset: 2px;
}
/* Lists */
:where(ul, ol):where(:not([class])) {
padding-left: 1.5em;
}:has() - parent selector!
:has() to rewolucja - pozwala stylować rodzica na podstawie dzieci!
/* Styluj article, który MA obrazek */
article:has(img) {
display: grid;
grid-template-columns: 1fr 2fr;
}
/* Styluj card, który MA button */
.card:has(.button) {
padding-bottom: 4rem;
}
/* Styluj form, który MA error */
form:has(.error) {
border: 2px solid red;
}Praktyczne przykłady :has()
1. Layout adaptation
/* Card z obrazkiem - inny layout */
.card:has(img) {
display: flex;
flex-direction: row;
}
/* Card bez obrazka - normalny layout */
.card:not(:has(img)) {
text-align: center;
}2. Form validation
/* Form field z errorem */
.form-field:has(input:invalid) {
border-color: red;
}
.form-field:has(input:valid) {
border-color: green;
}
/* Label gdy input ma fokus */
.form-field:has(input:focus) label {
color: #3498db;
font-weight: bold;
}3. Checkbox styling
/* Styluj label gdy checkbox zaznaczony */
.checkbox-wrapper:has(input:checked) label {
font-weight: bold;
color: green;
}
.checkbox-wrapper:has(input:checked) {
background: #e8f5e9;
}4. Navigation highlighting
/* Highlight section w navigation */
nav:has(~ main #section-1) .nav-link[href="#section-1"] {
color: goldenrod;
font-weight: bold;
}5. Empty state
/* Styluj container gdy pusty */
.list:not(:has(li)) {
display: flex;
align-items: center;
justify-content: center;
}
.list:not(:has(li))::before {
content: "Brak elementów";
color: #999;
}subgrid - zagnieżdżone siatki
subgrid pozwala dzieciom używać siatki rodzica!
.parent-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.child-grid {
display: grid;
/* Użyj kolumn z rodzica! */
grid-template-columns: subgrid;
grid-column: span 2;
}Praktyczny przykład
<div class="product-grid">
<article class="product">
<h3>Produkt 1</h3>
<div class="product-details">
<span class="price">$99</span>
<button>Kup</button>
</div>
</article>
</div>.product-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
}
.product {
display: grid;
/* Wyrównaj wszystkie .product-details w tej samej linii */
grid-template-rows: auto 1fr auto;
}
.product-details {
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
align-items: center;
}@layer - Cascade Layers
@layer pozwala kontrolować cascade bez specificity!
/* Zdefiniuj kolejność layers */
@layer reset, base, components, utilities;
/* Layer reset - najniższy priorytet */
@layer reset {
* {
margin: 0;
padding: 0;
}
}
/* Layer base */
@layer base {
body {
font-family: Arial, sans-serif;
}
}
/* Layer components */
@layer components {
.button {
background: #3498db;
color: white;
}
}
/* Layer utilities - najwyższy priorytet */
@layer utilities {
.text-center {
text-align: center;
}
}@container - Container Queries
Container Queries pozwalają stylować na podstawie rozmiaru kontenera, nie viewport!
.card-container {
container-type: inline-size;
container-name: card;
}
.card {
padding: 1rem;
}
/* Gdy kontener > 400px */
@container card (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
.card img {
width: 150px;
}
}
/* Gdy kontener > 600px */
@container card (min-width: 600px) {
.card {
padding: 2rem;
}
}color-mix() - mieszanie kolorów
.element {
/* Zmieszaj 50% blue z 50% red */
background: color-mix(in srgb, blue 50%, red);
/* Rozjaśnij kolor */
background: color-mix(in srgb, #3498db, white 20%);
/* Przyciemnij kolor */
background: color-mix(in srgb, #3498db, black 20%);
}accent-color - kolorowanie form controls
/* Zmień kolor checkboxów, radio, range */
input[type="checkbox"],
input[type="radio"],
input[type="range"] {
accent-color: goldenrod;
}
/* Globalnie */
:root {
accent-color: #3498db;
}Inne nowoczesne właściwości
overflow: clip
.element {
/* Jak overflow: hidden, ale nie tworzy scroll context */
overflow: clip;
}inset - skrót dla top/right/bottom/left
/* Zamiast: */
.element {
top: 0;
right: 0;
bottom: 0;
left: 0;
}
/* Użyj inset */
.element {
inset: 0;
}
/* Lub per-side */
.element {
inset: 10px 20px; /* top/bottom left/right */
}object-view-box - crop obrazków
img {
object-view-box: inset(10% 20% 10% 20%);
/* Przycina obrazek z wszystkich stron */
}content-visibility - performance
.long-section {
/* Nie renderuj poza viewport - OGROMNY boost performance! */
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}Wsparcie przeglądarek (2024)
| Feature | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| aspect-ratio | 88+ (2020) | 89+ (2021) | 15+ (2021) | 88+ |
| gap w Flexbox | 84+ (2020) | 63+ (2018) | 14.1+ (2021) | 84+ |
| :is() | 88+ | 78+ | 14+ | 88+ |
| :where() | 88+ | 78+ | 14+ | 88+ |
| :has() | 105+ (2022) | 121+ (2023) | 15.4+ (2022) | 105+ |
| subgrid | 117+ (2023) | 71+ (2019) | 16+ (2022) | 117+ |
| @container | 106+ (2022) | 110+ (2023) | 16+ (2022) | 106+ |
| @layer | 99+ (2022) | 97+ (2022) | 15.4+ (2022) | 99+ |
Podsumowanie
Najważniejsze nowoczesne features:
- aspect-ratio - idealne proporcje bez hacków
- gap - odstępy w Flexbox i Grid
- :is()/:where() - eleganckie grupowanie
- :has() - parent selector!
- subgrid - zagnieżdżone siatki
- @layer - kontrola cascade
- @container - responsive na poziomie komponentu
Dlaczego używać:
- Czystszy kod
- Mniej hacków
- Lepsza wydajność
- Łatwiejsze utrzymanie
Kod do tej lekcji: index.html
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Modern CSS - Projekt</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="page">
<header>
<h1>Swiatynia Nowoczesnego CSS</h1>
<p class="subtitle">Polacz wszystkie techniki w jednym projekcie</p>
</header>
<main class="grid-layout">
<div class="card-container">
<article class="card">
<div class="card-media">Container Queries</div>
<div class="card-body">
<h2>Adaptacyjne karty</h2>
<p>Reaguja na rozmiar kontenera.</p>
</div>
</article>
</div>
<div class="card-container">
<article class="card">
<div class="card-media">:has() + Nesting</div>
<div class="card-body">
<h2>Inteligentne selektory</h2>
<p>Rodzic stylowany przez dzieci.</p>
</div>
</article>
</div>
<section class="scroll-section">
<h2>Galeria scroll-snap</h2>
<div class="snap-gallery">
<div class="snap-item" style="background:#d4af37">Skarabeusz</div>
<div class="snap-item" style="background:#8b6914">Ankh</div>
<div class="snap-item" style="background:#1e3a5f">Oko Horusa</div>
<div class="snap-item" style="background:#b87333">Piramida</div>
</div>
</section>
<section class="form-section">
<h2>Formularz z accent-color</h2>
<label><input type="checkbox" checked> Opcja 1</label>
<label><input type="range" min="0" max="100" value="70"></label>
</section>
</main>
</div>
</body>
</html>Pamiętaj: Modern CSS to jak odkrycie nowych hieroglifów - nowe możliwości, prostsze rozwiązania, potężniejsze narzędzia!
Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Co zmieniło się w obsłudze właściwości gap od 2021 roku?
2. Czym jest właściwość inset: 0 w CSS?
To 2 z 3 pytań do tej lekcji. Pozostałe rozwiążesz w grze.
Zadania praktyczne w grze
- Układanie w poziomie
Ułóż w jednej linii poprawną deklarację overflow: clip: