Kurs HTML i CSS · Moduł 9: Nowoczesny CSS

State of CSS - Przyszłość i trendy CSS

14 min czytania ·
W tej lekcji10

CSS co roku przynosi tyle nowości, że trudno odróżnić chwilową modę od rzeczy na lata, a potrzebujesz mapy jak kartograf faraona. State of CSS to coroczne badanie społeczności web developerów, które mapuje trendy, preferencje i kierunki rozwoju CSS. Badanie pyta, czy znasz i używasz danej funkcji, a przy narzędziach także o zadowolenie. Wyniki znajdziesz na stateofcss.com.

Aktualny stan CSS

Nowe funkcjonalności w CSS

CSS nieustannie ewoluuje, wprowadzając coraz bardziej zaawansowane możliwości. Oto przegląd funkcji, które poznałeś w tym module:

/* Container Queries - responsywność oparta na kontenerze */
@container sidebar (min-width: 250px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

/* CSS Nesting - zagnieżdżanie w natywnym CSS */
.card {
  background: white;
  border-radius: 8px;

  &:hover {
    background: #f8f9fa;
  }

  .title {
    font-size: 1.2rem;
    font-weight: bold;

    &.highlight {
      color: #007bff;
    }
  }
}

/* CSS Cascade Layers - kontrola nad kaskadą */
@layer reset, base, theme, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; }
}

@layer theme {
  :root {
    --primary: #007bff;
    --secondary: #6c757d;
  }
}

/* Subgrid - dziedziczenie siatki grid */
.main-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.card {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
}

Container Queries, zagnieżdżanie, warstwy kaskady i subgrid działają dziś we wszystkich głównych przeglądarkach.

CSS Houdini - nowa era customizacji

CSS Houdini pozwala programistom na dostęp do CSS Object Model, czyli wnętrza silnika stylów. CSS.registerProperty() to javascriptowy odpowiednik reguły @property, a Paint Worklet rysuje tło kodem:

// Rejestracja custom property
CSS.registerProperty({
  name: '--gradient-angle',
  syntax: '<angle>',
  inherits: false,
  initialValue: '0deg'
});

// Paint Worklet - custom drawing
class CircleGradient {
  static get inputProperties() {
    return ['--start-color', '--end-color'];
  }

  paint(ctx, size, properties) {
    const gradient = ctx.createRadialGradient(
      size.width / 2, size.height / 2, 0,
      size.width / 2, size.height / 2, size.width / 2
    );

    gradient.addColorStop(0, properties.get('--start-color'));
    gradient.addColorStop(1, properties.get('--end-color'));

    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, size.width, size.height);
  }
}

registerPaint('circle-gradient', CircleGradient);

Klasa trafia do osobnego pliku wczytywanego przez CSS.paintWorklet.addModule(), a inputProperties wymienia zmienne, które worklet odczyta. W arkuszu używasz go funkcją paint():

/* Użycie Paint Worklet */
.custom-background {
  --start-color: #667eea;
  --end-color: #764ba2;
  background: paint(circle-gradient);
}

Paint API działa dziś tylko w przeglądarkach opartych na Chromium, więc traktuj je jako ulepszenie z fallbackiem.

Trendy i statystyki z State of CSS

Najpopularniejsze funkcjonalności CSS

Tak mogłoby wyglądać zestawienie użycia, zadowolenia i zainteresowania funkcjami zapisane jako dane:

const cssFeatureUsage = {
  flexbox: {
    usage: "94%",
    satisfaction: "92%",
    interest: "65%"
  },
  grid: {
    usage: "89%",
    satisfaction: "94%",
    interest: "71%"
  },
  customProperties: {
    usage: "87%",
    satisfaction: "89%",
    interest: "68%"
  },
  containerQueries: {
    usage: "23%",
    satisfaction: "91%",
    interest: "89%"
  },
  cssNesting: {
    usage: "31%",
    satisfaction: "87%",
    interest: "84%"
  },
  cascadeLayers: {
    usage: "8%",
    satisfaction: "73%",
    interest: "76%"
  }
};

// Trendy wzrostowe
const emergingFeatures = [
  'Container Queries',
  'CSS Nesting',
  'Cascade Layers',
  'CSS Subgrid',
  'CSS Scroll-Driven Animations',
  'View Transitions API'
];

Liczby są przykładowe i pokazują format danych, a nie wyniki konkretnej edycji badania.

Frameworks CSS - preferencje deweloperów

Badanie porównuje też frameworki utility-first, komponentowe i CSS-in-JS, tu w tym samym formacie:

const cssFrameworksRanking = {
  // Utility-first frameworks
  tailwind: {
    usage: "78%",
    satisfaction: "84%",
    retention: "87%",
    trend: "rising"
  },

  // Component frameworks
  bootstrap: {
    usage: "45%",
    satisfaction: "43%",
    retention: "38%",
    trend: "declining"
  },

  materialUI: {
    usage: "32%",
    satisfaction: "67%",
    retention: "62%",
    trend: "stable"
  },

  // CSS-in-JS solutions
  styledComponents: {
    usage: "41%",
    satisfaction: "71%",
    retention: "68%",
    trend: "stable"
  },

  emotion: {
    usage: "23%",
    satisfaction: "73%",
    retention: "69%",
    trend: "stable"
  }
};

Te liczby również są ilustracyjne. Tailwind CSS to sztandarowy przykład podejścia utility-first i od lat należy do najpopularniejszych frameworków w badaniu.

Przyszłość CSS - nadchodzące funkcjonalności

1. CSS Anchor Positioning

Anchor Positioning pozwala przypiąć element, na przykład dymek z podpowiedzią, do innego elementu bez JavaScriptu:

/* Pozycjonowanie względem anchora */
.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  position-anchor: --my-anchor;
  top: anchor(bottom);
  left: anchor(center);
  margin-top: 10px;
}

/* Anchor queries - responsywność oparta na anchor */
@position-try --fallback {
  top: anchor(top);
  bottom: auto;
  margin-top: -10px;
}

.positioned {
  position-try-fallbacks: --fallback;
}

Kotwica dostaje nazwę przez anchor-name, a funkcja anchor() wskazuje jej krawędzie. @position-try opisuje pozycję zapasową na wypadek braku miejsca, a position-try-fallbacks (wcześniej position-try-options) ją podpina. Chromium obsługuje to od 2024 roku, inne przeglądarki stopniowo dołączają.

2. View Transitions API

View Transitions API służy do płynnych, animowanych przejść między stanami lub widokami strony. W CSS animujesz pseudoelementy starego i nowego widoku:

/* Animacje między widokami */
::view-transition-old(root) {
  animation: slide-out 0.3s ease-out;
}

::view-transition-new(root) {
  animation: slide-in 0.3s ease-in;
}

@keyframes slide-out {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}

@keyframes slide-in {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}

/* Named view transitions */
.card {
  view-transition-name: card-transition;
}

view-transition-name daje wybranemu elementowi, na przykład karcie, własną animację przejścia. Po stronie JavaScriptu przejście uruchamiasz metodą document.startViewTransition():

// JavaScript API dla View Transitions
function navigateToPage(url) {
  if (document.startViewTransition) {
    document.startViewTransition(() => {
      // Logika nawigacji
      window.location.href = url;
    });
  } else {
    // Fallback dla przeglądarek bez wsparcia
    window.location.href = url;
  }
}

// Programmatic view transitions
function updateContent(newContent) {
  if (document.startViewTransition) {
    document.startViewTransition(() => {
      document.querySelector('.content').innerHTML = newContent;
    });
  } else {
    document.querySelector('.content').innerHTML = newContent;
  }
}

Przeglądarka robi zrzut starego widoku, wykonuje zmianę w DOM i animuje przejście. Przy nawigacji między osobnymi stronami lepiej jednak dodać do CSS obu stron regułę @view-transition { navigation: auto; }, bez JavaScriptu.

3. Scroll-driven Animations

Animacje sterowane przewijaniem łączą @keyframes z osią czasu przewijania zamiast z zegarem:

/* Animacje oparte na scrollu */
@keyframes reveal {
  from {
    opacity: 0;
    transform: translateY(50px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.scroll-reveal {
  animation: reveal linear;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

/* Progress bar based on scroll */
.progress-bar {
  animation: progress-bar linear;
  animation-timeline: scroll(root);
}

@keyframes progress-bar {
  from { width: 0%; }
  to { width: 100%; }
}

/* Parallax effect with scroll timeline */
.parallax-bg {
  animation: parallax linear;
  animation-timeline: scroll(nearest);
  animation-range: exit -100% entry 100%;
}

@keyframes parallax {
  from { transform: translateY(-50%); }
  to { transform: translateY(50%); }
}

view() śledzi pojawianie się elementu w widoku, a scroll() postęp przewijania. animation-timeline musi stać po skrócie animation, bo skrót resetuje tę właściwość.

4. CSS Color Functions Level 5

Nowe funkcje kolorów pozwalają liczyć odcienie w przeglądarce. Zwróć uwagę na light-dark() na końcu przykładu:

/* Nowe funkcje kolorów */
.advanced-colors {
  /* Relative color syntax */
  --primary: #007bff;
  --primary-light: color(from var(--primary) srgb r g b / 0.5);
  --primary-dark: color(from var(--primary) srgb calc(r * 0.8) calc(g * 0.8) calc(b * 0.8));

  /* Color mixing */
  --mixed-color: color-mix(in srgb, var(--primary) 70%, white);

  /* Contrast color function */
  --text-color: contrast-color(var(--primary));

  /* Wide gamut colors */
  --vibrant-red: color(display-p3 1 0.2 0.3);
  --rec2020-green: color(rec2020 0.4 0.9 0.1);
}

/* Light-dark function */
:root {
  color-scheme: light dark; /* wymagane przez light-dark() */
}

.theme-aware {
  background: light-dark(white, #1a1a1a);
  color: light-dark(#333, white);
}

light-dark(white, #1a1a1a) wybiera pierwszy kolor w jasnym motywie, a drugi w ciemnym, ale tylko gdy color-scheme dopuszcza oba motywy. contrast-color() jest najmłodsza i ma ograniczone wsparcie.

Metodologie i best practices według społeczności

Utility-first vs Component-first

Porównaj podejście utility-first i komponentowe na jednym przycisku:

/* Utility-first approach (Tailwind style) */
.btn-primary {
  @apply inline-flex items-center px-4 py-2
         bg-blue-600 border border-transparent
         rounded-md font-semibold text-xs text-white
         uppercase tracking-widest hover:bg-blue-700
         focus:bg-blue-700 active:bg-blue-900
         focus:outline-none focus:ring-2 focus:ring-indigo-500
         focus:ring-offset-2 transition ease-in-out duration-150;
}

/* Component-first approach */
.button {
  --button-bg: var(--color-primary);
  --button-text: var(--color-white);
  --button-border: var(--color-primary);
  --button-hover-bg: var(--color-primary-dark);

  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1rem;
  background: var(--button-bg);
  color: var(--button-text);
  border: 1px solid var(--button-border);
  border-radius: 0.375rem;
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  transition: all 0.15s ease-in-out;

  &:hover {
    background: var(--button-hover-bg);
  }

  &:focus {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
  }

  &.secondary {
    --button-bg: var(--color-secondary);
    --button-border: var(--color-secondary);
    --button-hover-bg: var(--color-secondary-dark);
  }
}

@apply działa tylko z Tailwindem. ring to pojęcie z Tailwinda, a w czystym CSS podobny efekt daje outline z outline-offset.

CSS Architecture patterns

CUBE CSS dzieli style na kompozycję, klasy pomocnicze, bloki i wyjątki (Composition, Utility, Block, Exception):

/* CUBE CSS methodology */
/* Composition */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space, 1rem);
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space, 1rem);
  align-items: var(--align, flex-start);
  justify-content: var(--justify, flex-start);
}

/* Utilities */
.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.flow > * + * {
  margin-top: var(--flow-space, 1em);
}

/* Block */
.card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: var(--space-m);
  box-shadow: var(--shadow);
}

/* Exception */
.card[data-variant="ghost"] {
  background: transparent;
  box-shadow: none;
  border: 1px solid var(--border);
}

Wyjątek [data-variant="ghost"] zmienia kartę atrybutem zamiast kolejną klasą.

CSS Tools ecosystem - trendy narzędziowe

Build tools preferences

Badanie pyta też o narzędzia: preprocesory, wtyczki PostCSS i bundlery. Dane mogą wyglądać tak:

const buildToolsUsage = {
  // CSS Processors
  sass: {
    usage: "71%",
    satisfaction: "79%",
    retention: "74%"
  },
  less: {
    usage: "23%",
    satisfaction: "61%",
    retention: "45%"
  },
  stylus: {
    usage: "8%",
    satisfaction: "68%",
    retention: "52%"
  },

  // PostCSS plugins
  autoprefixer: {
    usage: "84%",
    satisfaction: "87%",
    retention: "89%"
  },
  purgecss: {
    usage: "45%",
    satisfaction: "82%",
    retention: "78%"
  },
  cssnano: {
    usage: "52%",
    satisfaction: "79%",
    retention: "76%"
  },

  // Bundlers
  webpack: {
    usage: "68%",
    satisfaction: "65%",
    retention: "58%"
  },
  vite: {
    usage: "67%",
    satisfaction: "91%",
    retention: "89%"
  },
  parcel: {
    usage: "23%",
    satisfaction: "78%",
    retention: "71%"
  }
};

Również te liczby są przykładowe, więc traktuj je jak wzór, a nie wynik.

CSS-in-JS evolution

CSS-in-JS przeszedł drogę od generowania stylów w przeglądarce do generowania ich podczas budowania. Oto trzy podejścia:

// Styled components approach
const Button = styled.button`
  background: ${props => props.primary ? '#007bff' : '#6c757d'};
  color: white;
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 0.25rem;
  cursor: pointer;

  &:hover {
    opacity: 0.9;
  }

  @media (max-width: 768px) {
    font-size: 0.875rem;
  }
`

// Zero-runtime CSS-in-JS (Compiled, Vanilla Extract)
import { style } from '@vanilla-extract/css';

export const button = style({
  background: '#007bff',
  color: 'white',
  padding: '0.5rem 1rem',
  border: 'none',
  borderRadius: '0.25rem',
  cursor: 'pointer',

  ':hover': {
    opacity: 0.9
  },

  '@media': {
    '(max-width: 768px)': {
      fontSize: '0.875rem'
    }
  }
});

// Atomic CSS approach (Stitches)
const Button = styled('button', {
  background: '$blue600',
  color: '$white',
  padding: '$2 $4',
  border: 'none',
  borderRadius: '$md',
  cursor: 'pointer',

  '&:hover': {
    opacity: 0.9
  },

  variants: {
    size: {
      small: {
        padding: '$1 $2',
        fontSize: '$sm'
      },
      large: {
        padding: '$3 $6',
        fontSize: '$lg'
      }
    }
  }
});

Rozwiązania zero-runtime, jak Vanilla Extract, zamieniają style w zwykły plik CSS już podczas budowania.

CSS optimization strategies

Wydajność to kolejny trend. Pierwsza reguła, mimo komentarza, ogranicza ruch dla osób, które tego potrzebują:

/* Critical CSS loading */
@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    animation-delay: -1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    background-attachment: initial !important;
    scroll-behavior: auto !important;
    transition-duration: 0s !important;
    transition-delay: 0s !important;
  }
}

/* Container-based responsive design */
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

@container sidebar (min-width: 250px) {
  .navigation {
    display: block;
  }
}

/* CSS containment for performance */
.card {
  contain: layout style paint;
}

.infinite-list-item {
  contain: strict;
  content-visibility: auto;
  contain-intrinsic-size: 200px;
}

content-visibility: auto pomija renderowanie treści poza ekranem, a contain-intrinsic-size rezerwuje dla niej miejsce, żeby strona nie skakała.

Modern CSS loading patterns

Kluczowe style wpisujemy w HTML, a resztę ładujemy tak, by nie blokowała pierwszego wyświetlenia:

<!-- Critical CSS inline -->
<style>
  /* Critical above-the-fold styles */
  .hero { display: flex; min-height: 100vh; }
  .header { position: fixed; top: 0; width: 100%; }
</style>

<!-- Non-critical CSS with media queries -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

<!-- CSS for specific components -->
<link rel="stylesheet" href="components.css" media="print" onload="this.media='all'">

Sztuczki z preload i media="print" ładują CSS asynchronicznie, a noscript daje zapas bez JavaScriptu.

Browser support strategies

Progressive enhancement patterns

Nowości wprowadzamy tak, by starsze przeglądarki dostały działającą bazę, a nowsze coś więcej:

/* Feature detection with @supports */
.grid-container {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

@supports (display: grid) {
  .grid-container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  }
}

@supports (container-type: inline-size) {
  .responsive-component {
    container-type: inline-size;
  }

  @container (min-width: 300px) {
    .component-content {
      display: flex;
    }
  }
}

/* Graceful degradation for new color spaces */
.vibrant-bg {
  background: #ff6b6b; /* Fallback */
  background: color(display-p3 1 0.4 0.4); /* Modern browsers */
}

/* Progressive enhancement for scroll animations */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .scroll-animation {
      animation: fadeIn linear;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }
  }
}

Najpierw zwykła wartość, potem @supports z nowością. Przy animacjach sprawdzamy dodatkowo, czy użytkownik nie prosi o mniej ruchu.

Inclusive design patterns

Media queries preferencji dopasowują stronę do ustawień systemu użytkownika:

/* Respect user preferences */
@media (prefers-color-scheme: dark) {
  :root {
    --bg-primary: #1a1a1a;
    --text-primary: #ffffff;
    --border-color: #404040;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media (prefers-contrast: more) {
  :root {
    --border-width: 2px;
    --focus-ring-width: 3px;
  }
}

/* Focus management */
.button {
  &:focus-visible {
    outline: 2px solid var(--focus-color);
    outline-offset: 2px;
  }

  &:focus:not(:focus-visible) {
    outline: none;
  }
}

/* Screen reader optimizations */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Color contrast helpers */
.ensure-contrast {
  background: var(--bg-color);
  color: contrast-color(var(--bg-color)); /* Future CSS function */
}

Dla prefers-contrast poprawne wartości to more, less, custom i no-preference, a :focus-visible pokazuje obramowanie fokusu tylko wtedy, gdy jest potrzebne.

Przyszłe kierunki rozwoju CSS

Predictions based on State of CSS

Na koniec prognozy. Zapisane jako dane wyglądają tak:

const futureCSSTrends = {
  shortTerm: [
    'Widespread Container Queries adoption',
    'CSS Nesting in all browsers',
    'View Transitions API expansion',
    'Better CSS Houdini support'
  ],

  mediumTerm: [
    'CSS Anchor Positioning',
    'Advanced color functions',
    'Scroll-driven animations',
    'CSS Modules native support'
  ],

  longTerm: [
    'CSS Variables 2.0 with functions',
    'CSS Layout API (Houdini)',
    'CSS Parser API',
    'Advanced typography controls'
  ],

  emerging: [
    'CSS Container Style Queries',
    'CSS Conditional Rules Level 4',
    'CSS Spatial Navigation',
    'CSS Environment Variables'
  ]
};

// Developer priorities
const developerWants = {
  features: [
    'Better debugging tools',
    'Native CSS mixins',
    'Improved CSS math functions',
    'Cross-browser consistency'
  ],

  tooling: [
    'Faster build tools',
    'Better IntelliSense',
    'Visual CSS editors',
    'Performance analyzers'
  ],

  ecosystem: [
    'Standardized design tokens',
    'Better framework interop',
    'Component sharing standards',
    'CSS testing tools'
  ]
};

Część z nich już się spełniła, na przykład zagnieżdżanie działa we wszystkich głównych przeglądarkach.

Design system evolution

Poniższy przykład to fantazja o przyszłości systemów projektowych. Reguły @design-tokens i @component nie istnieją w żadnej specyfikacji CSS:

/* Future design token approach */
@design-tokens {
  --color-primary: #007bff;
  --color-secondary: #6c757d;
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --typography-heading-1: {
    font-family: Inter, sans-serif;
    font-size: 2.5rem;
    font-weight: 700;
    line-height: 1.2;
  };
}

/* Advanced component definition */
@component button {
  base: {
    display: inline-flex;
    align-items: center;
    padding: var(--space-sm) var(--space-md);
    border: none;
    border-radius: 0.375rem;
    cursor: pointer;
    transition: all 0.15s ease;
  };

  variants: {
    variant: {
      primary: {
        background: var(--color-primary);
        color: white;
      },
      secondary: {
        background: var(--color-secondary);
        color: white;
      }
    },

    size: {
      small: {
        padding: var(--space-xs) var(--space-sm);
        font-size: 0.875rem;
      },
      large: {
        padding: var(--space-md) var(--space-lg);
        font-size: 1.125rem;
      }
    }
  }
}

Dziś tokeny zapisujesz jako zmienne CSS, a grupa W3C Design Tokens Community Group pracuje nad wspólnym formatem tokenów w JSON.

Podsumowanie State of CSS

Kluczowe wnioski z badań

  • Container Queries rewolucjonizują responsywny design
  • Utility-first frameworks (Tailwind) dominują nad tradycyjnymi
  • CSS Nesting staje się standardem w nowoczesnym CSS
  • Performance jest kluczowym czynnikiem w wyborze narzędzi
  • Accessibility zyskuje na znaczeniu w społeczności
  • Zero-runtime CSS-in-JS to przyszłość styling w React

Rekomendacje dla developerów

  1. Nadąż za Container Queries - to fundamentalna zmiana w CSS
  2. Eksperymentuj z CSS Nesting - już dostępne w większości przeglądarek
  3. Rozważ Tailwind CSS - jeśli jeszcze nie używasz utility-first
  4. Przygotuj się na View Transitions - nowa era animacji webowych
  5. Inwestuj w accessibility - to nie tylko trend, to konieczność

Moja rada: raz w roku przejrzyj wyniki State of CSS, ale nowości wdrażaj dopiero po sprawdzeniu wsparcia na caniuse.com. W piaskownicy poniżej poeksperymentuj z color-mix(), jedną z nowych funkcji kolorów.

Pamiętaj: State of CSS to mapa kartografa, która pokazuje kierunek, ale drogę przez pustynię i tak sprawdzasz własnymi krokami.

Kod do tej lekcji: index.html
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <title>color-mix()</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>color-mix() - mieszanie kolorow</h1>
    <div class="palette">
        <div class="swatch s-lightest">90% bialy</div>
        <div class="swatch s-lighter">70% bialy</div>
        <div class="swatch s-light">50% bialy</div>
        <div class="swatch s-base">Bazowy</div>
        <div class="swatch s-dark">70% czarny</div>
        <div class="swatch s-darker">50% czarny</div>
    </div>
    <div class="demo-card">
        <h2>Karta z paleta</h2>
        <p>Kolory generowane z jednego bazowego!</p>
    </div>
</body>
</html>

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. 1. Czym jest State of CSS?

  2. 2. Który framework reprezentuje rosnący trend utility-first według State of 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 poprawne wywołanie funkcji light-dark() dla koloru tła:

Przydatne artykuły