State of CSS to coroczne badanie społeczności web developerów, które mapuje trendy, preferencje i kierunki rozwoju CSS. To niezastąpione źródło informacji o tym, dokąd zmierza technologia stylowania stron internetowych.
CSS nieustannie ewoluuje, wprowadzając coraz bardziej zaawansowane możliwości:
1/* Container Queries - responsywność oparta na kontenerze */
2@container sidebar (min-width: 250px) {
3 .card {
4 display: flex;
5 flex-direction: row;
6 }
7}
8
9/* CSS Nesting - zagnieżdżanie w natywnym CSS */
10.card {
11 background: white;
12 border-radius: 8px;
13
14 &:hover {
15 background: #f8f9fa;
16 }
17
18 .title {
19 font-size: 1.2rem;
20 font-weight: bold;
21
22 &.highlight {
23 color: #007bff;
24 }
25 }
26}
27
28/* CSS Cascade Layers - kontrola nad kaskadą */
29@layer reset, base, theme, components, utilities;
30
31@layer reset {
32 * { margin: 0; padding: 0; }
33}
34
35@layer theme {
36 :root {
37 --primary: #007bff;
38 --secondary: #6c757d;
39 }
40}
41
42/* Subgrid - dziedziczenie siatki grid */
43.main-grid {
44 display: grid;
45 grid-template-columns: repeat(4, 1fr);
46 gap: 20px;
47}
48
49.card {
50 display: grid;
51 grid-template-rows: subgrid;
52 grid-row: span 3;
53}CSS Houdini pozwala programistom na dostęp do CSS Object Model:
1// Rejestracja custom property
2CSS.registerProperty({
3 name: '--gradient-angle',
4 syntax: '<angle>',
5 inherits: false,
6 initialValue: '0deg'
7});
8
9// Paint Worklet - custom drawing
10class CircleGradient {
11 paint(ctx, size, properties) {
12 const gradient = ctx.createRadialGradient(
13 size.width / 2, size.height / 2, 0,
14 size.width / 2, size.height / 2, size.width / 2
15 );
16
17 gradient.addColorStop(0, properties.get('--start-color'));
18 gradient.addColorStop(1, properties.get('--end-color'));
19
20 ctx.fillStyle = gradient;
21 ctx.fillRect(0, 0, size.width, size.height);
22 }
23}
24
25registerPaint('circle-gradient', CircleGradient);1/* Użycie Paint Worklet */
2.custom-background {
3 --start-color: #667eea;
4 --end-color: #764ba2;
5 background: paint(circle-gradient);
6}Według badań State of CSS, najpopularniejsze nowe funkcjonalności to:
1const cssFeatureUsage = {
2 flexbox: {
3 usage: "94%",
4 satisfaction: "92%",
5 interest: "65%"
6 },
7 grid: {
8 usage: "89%",
9 satisfaction: "94%",
10 interest: "71%"
11 },
12 customProperties: {
13 usage: "87%",
14 satisfaction: "89%",
15 interest: "68%"
16 },
17 containerQueries: {
18 usage: "23%",
19 satisfaction: "91%",
20 interest: "89%"
21 },
22 cssNesting: {
23 usage: "31%",
24 satisfaction: "87%",
25 interest: "84%"
26 },
27 cascadeLayers: {
28 usage: "8%",
29 satisfaction: "73%",
30 interest: "76%"
31 }
32};
33
34// Trendy wzrostowe
35const emergingFeatures = [
36 'Container Queries',
37 'CSS Nesting',
38 'Cascade Layers',
39 'CSS Subgrid',
40 'CSS Scroll-Driven Animations',
41 'View Transitions API'
42];1const cssFrameworksRanking = {
2 // Utility-first frameworks
3 tailwind: {
4 usage: "78%",
5 satisfaction: "84%",
6 retention: "87%",
7 trend: "rising"
8 },
9
10 // Component frameworks
11 bootstrap: {
12 usage: "45%",
13 satisfaction: "43%",
14 retention: "38%",
15 trend: "declining"
16 },
17
18 materialUI: {
19 usage: "32%",
20 satisfaction: "67%",
21 retention: "62%",
22 trend: "stable"
23 },
24
25 // CSS-in-JS solutions
26 styledComponents: {
27 usage: "41%",
28 satisfaction: "71%",
29 retention: "68%",
30 trend: "stable"
31 },
32
33 emotion: {
34 usage: "23%",
35 satisfaction: "73%",
36 retention: "69%",
37 trend: "stable"
38 }
39};1/* Pozycjonowanie względem anchora */
2.anchor {
3 anchor-name: --my-anchor;
4}
5
6.positioned {
7 position: absolute;
8 position-anchor: --my-anchor;
9 top: anchor(bottom);
10 left: anchor(center);
11 margin-top: 10px;
12}
13
14/* Anchor queries - responsywność oparta na anchor */
15@position-try --fallback {
16 top: anchor(top);
17 bottom: auto;
18 margin-top: -10px;
19}
20
21.positioned {
22 position-try-options: --fallback;
23}1/* Animacje między widokami */
2::view-transition-old(root) {
3 animation: slide-out 0.3s ease-out;
4}
5
6::view-transition-new(root) {
7 animation: slide-in 0.3s ease-in;
8}
9
10@keyframes slide-out {
11 from { transform: translateX(0); }
12 to { transform: translateX(-100%); }
13}
14
15@keyframes slide-in {
16 from { transform: translateX(100%); }
17 to { transform: translateX(0); }
18}
19
20/* Named view transitions */
21.card {
22 view-transition-name: card-transition;
23}1// JavaScript API dla View Transitions
2function navigateToPage(url) {
3 if (document.startViewTransition) {
4 document.startViewTransition(() => {
5 // Logika nawigacji
6 window.location.href = url;
7 });
8 } else {
9 // Fallback dla przeglądarek bez wsparcia
10 window.location.href = url;
11 }
12}
13
14// Programmatic view transitions
15function updateContent(newContent) {
16 if (document.startViewTransition) {
17 document.startViewTransition(() => {
18 document.querySelector('.content').innerHTML = newContent;
19 });
20 } else {
21 document.querySelector('.content').innerHTML = newContent;
22 }
23}1/* Animacje oparte na scrollu */
2@keyframes reveal {
3 from {
4 opacity: 0;
5 transform: translateY(50px);
6 }
7 to {
8 opacity: 1;
9 transform: translateY(0);
10 }
11}
12
13.scroll-reveal {
14 animation: reveal linear;
15 animation-timeline: view();
16 animation-range: entry 25% cover 50%;
17}
18
19/* Progress bar based on scroll */
20.progress-bar {
21 animation: progress-bar linear;
22 animation-timeline: scroll(root);
23}
24
25@keyframes progress-bar {
26 from { width: 0%; }
27 to { width: 100%; }
28}
29
30/* Parallax effect with scroll timeline */
31.parallax-bg {
32 animation: parallax linear;
33 animation-timeline: scroll(nearest);
34 animation-range: exit -100% entry 100%;
35}
36
37@keyframes parallax {
38 from { transform: translateY(-50%); }
39 to { transform: translateY(50%); }
40}1/* Nowe funkcje kolorów */
2.advanced-colors {
3 /* Relative color syntax */
4 --primary: #007bff;
5 --primary-light: color(from var(--primary) srgb r g b / 0.5);
6 --primary-dark: color(from var(--primary) srgb calc(r * 0.8) calc(g * 0.8) calc(b * 0.8));
7
8 /* Color mixing */
9 --mixed-color: color-mix(in srgb, var(--primary) 70%, white);
10
11 /* Contrast color function */
12 --text-color: contrast-color(var(--primary));
13
14 /* Wide gamut colors */
15 --vibrant-red: color(display-p3 1 0.2 0.3);
16 --rec2020-green: color(rec2020 0.4 0.9 0.1);
17}
18
19/* Light-dark function */
20.theme-aware {
21 background: light-dark(white, #1a1a1a);
22 color: light-dark(#333, white);
23}1/* Utility-first approach (Tailwind style) */
2.btn-primary {
3 @apply inline-flex items-center px-4 py-2
4 bg-blue-600 border border-transparent
5 rounded-md font-semibold text-xs text-white
6 uppercase tracking-widest hover:bg-blue-700
7 focus:bg-blue-700 active:bg-blue-900
8 focus:outline-none focus:ring-2 focus:ring-indigo-500
9 focus:ring-offset-2 transition ease-in-out duration-150;
10}
11
12/* Component-first approach */
13.button {
14 --button-bg: var(--color-primary);
15 --button-text: var(--color-white);
16 --button-border: var(--color-primary);
17 --button-hover-bg: var(--color-primary-dark);
18
19 display: inline-flex;
20 align-items: center;
21 padding: 0.5rem 1rem;
22 background: var(--button-bg);
23 color: var(--button-text);
24 border: 1px solid var(--button-border);
25 border-radius: 0.375rem;
26 font-weight: 600;
27 font-size: 0.75rem;
28 text-transform: uppercase;
29 letter-spacing: 0.05em;
30 transition: all 0.15s ease-in-out;
31
32 &:hover {
33 background: var(--button-hover-bg);
34 }
35
36 &:focus {
37 outline: none;
38 ring: 2px solid var(--color-primary);
39 ring-offset: 2px;
40 }
41
42 &.secondary {
43 --button-bg: var(--color-secondary);
44 --button-border: var(--color-secondary);
45 --button-hover-bg: var(--color-secondary-dark);
46 }
47}1/* CUBE CSS methodology */
2/* Composition */
3.stack {
4 display: flex;
5 flex-direction: column;
6 gap: var(--space, 1rem);
7}
8
9.cluster {
10 display: flex;
11 flex-wrap: wrap;
12 gap: var(--space, 1rem);
13 align-items: var(--align, flex-start);
14 justify-content: var(--justify, flex-start);
15}
16
17/* Utilities */
18.visually-hidden {
19 position: absolute !important;
20 width: 1px !important;
21 height: 1px !important;
22 padding: 0 !important;
23 margin: -1px !important;
24 overflow: hidden !important;
25 clip: rect(0, 0, 0, 0) !important;
26 white-space: nowrap !important;
27 border: 0 !important;
28}
29
30.flow > * + * {
31 margin-top: var(--flow-space, 1em);
32}
33
34/* Block */
35.card {
36 background: var(--surface);
37 border-radius: var(--radius);
38 padding: var(--space-m);
39 box-shadow: var(--shadow);
40}
41
42/* Exception */
43.card[data-variant="ghost"] {
44 background: transparent;
45 box-shadow: none;
46 border: 1px solid var(--border);
47}1const buildToolsUsage = {
2 // CSS Processors
3 sass: {
4 usage: "71%",
5 satisfaction: "79%",
6 retention: "74%"
7 },
8 less: {
9 usage: "23%",
10 satisfaction: "61%",
11 retention: "45%"
12 },
13 stylus: {
14 usage: "8%",
15 satisfaction: "68%",
16 retention: "52%"
17 },
18
19 // PostCSS plugins
20 autoprefixer: {
21 usage: "84%",
22 satisfaction: "87%",
23 retention: "89%"
24 },
25 purgecss: {
26 usage: "45%",
27 satisfaction: "82%",
28 retention: "78%"
29 },
30 cssnano: {
31 usage: "52%",
32 satisfaction: "79%",
33 retention: "76%"
34 },
35
36 // Bundlers
37 webpack: {
38 usage: "68%",
39 satisfaction: "65%",
40 retention: "58%"
41 },
42 vite: {
43 usage: "67%",
44 satisfaction: "91%",
45 retention: "89%"
46 },
47 parcel: {
48 usage: "23%",
49 satisfaction: "78%",
50 retention: "71%"
51 }
52};1// Styled components approach
2const Button = styled.button`
3 background: ${props => props.primary ? '#007bff' : '#6c757d'};
4 color: white;
5 padding: 0.5rem 1rem;
6 border: none;
7 border-radius: 0.25rem;
8 cursor: pointer;
9
10 &:hover {
11 opacity: 0.9;
12 }
13
14 @media (max-width: 768px) {
15 font-size: 0.875rem;
16 }
17`;
18
19// Zero-runtime CSS-in-JS (Compiled, Vanilla Extract)
20import { style } from '@vanilla-extract/css';
21
22export const button = style({
23 background: '#007bff',
24 color: 'white',
25 padding: '0.5rem 1rem',
26 border: 'none',
27 borderRadius: '0.25rem',
28 cursor: 'pointer',
29
30 ':hover': {
31 opacity: 0.9
32 },
33
34 '@media': {
35 '(max-width: 768px)': {
36 fontSize: '0.875rem'
37 }
38 }
39});
40
41// Atomic CSS approach (Stitches)
42const Button = styled('button', {
43 background: '$blue600',
44 color: '$white',
45 padding: '$2 $4',
46 border: 'none',
47 borderRadius: '$md',
48 cursor: 'pointer',
49
50 '&:hover': {
51 opacity: 0.9
52 },
53
54 variants: {
55 size: {
56 small: {
57 padding: '$1 $2',
58 fontSize: '$sm'
59 },
60 large: {
61 padding: '$3 $6',
62 fontSize: '$lg'
63 }
64 }
65 }
66});1/* Critical CSS loading */
2@media (prefers-reduced-motion: reduce) {
3 *,
4 ::before,
5 ::after {
6 animation-delay: -1ms !important;
7 animation-duration: 1ms !important;
8 animation-iteration-count: 1 !important;
9 background-attachment: initial !important;
10 scroll-behavior: auto !important;
11 transition-duration: 0s !important;
12 transition-delay: 0s !important;
13 }
14}
15
16/* Container-based responsive design */
17.sidebar {
18 container-type: inline-size;
19 container-name: sidebar;
20}
21
22@container sidebar (min-width: 250px) {
23 .navigation {
24 display: block;
25 }
26}
27
28/* CSS containment for performance */
29.card {
30 contain: layout style paint;
31}
32
33.infinite-list-item {
34 contain: strict;
35 content-visibility: auto;
36 contain-intrinsic-size: 200px;
37}1<!-- Critical CSS inline -->
2<style>
3 /* Critical above-the-fold styles */
4 .hero { display: flex; min-height: 100vh; }
5 .header { position: fixed; top: 0; width: 100%; }
6</style>
7
8<!-- Non-critical CSS with media queries -->
9<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
10<noscript><link rel="stylesheet" href="styles.css"></noscript>
11
12<!-- CSS for specific components -->
13<link rel="stylesheet" href="components.css" media="print" onload="this.media='all'">1/* Feature detection with @supports */
2.grid-container {
3 display: flex;
4 flex-wrap: wrap;
5 gap: 1rem;
6}
7
8@supports (display: grid) {
9 .grid-container {
10 display: grid;
11 grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
12 }
13}
14
15@supports (container-type: inline-size) {
16 .responsive-component {
17 container-type: inline-size;
18 }
19
20 @container (min-width: 300px) {
21 .component-content {
22 display: flex;
23 }
24 }
25}
26
27/* Graceful degradation for new color spaces */
28.vibrant-bg {
29 background: #ff6b6b; /* Fallback */
30 background: color(display-p3 1 0.4 0.4); /* Modern browsers */
31}
32
33/* Progressive enhancement for scroll animations */
34@media (prefers-reduced-motion: no-preference) {
35 @supports (animation-timeline: scroll()) {
36 .scroll-animation {
37 animation: fadeIn linear;
38 animation-timeline: view();
39 animation-range: entry 0% cover 40%;
40 }
41 }
42}1/* Respect user preferences */
2@media (prefers-color-scheme: dark) {
3 :root {
4 --bg-primary: #1a1a1a;
5 --text-primary: #ffffff;
6 --border-color: #404040;
7 }
8}
9
10@media (prefers-reduced-motion: reduce) {
11 * {
12 animation-duration: 0.01ms !important;
13 animation-iteration-count: 1 !important;
14 transition-duration: 0.01ms !important;
15 }
16}
17
18@media (prefers-contrast: high) {
19 :root {
20 --border-width: 2px;
21 --focus-ring-width: 3px;
22 }
23}
24
25/* Focus management */
26.button {
27 &:focus-visible {
28 outline: 2px solid var(--focus-color);
29 outline-offset: 2px;
30 }
31
32 &:focus:not(:focus-visible) {
33 outline: none;
34 }
35}
36
37/* Screen reader optimizations */
38.sr-only {
39 position: absolute;
40 width: 1px;
41 height: 1px;
42 padding: 0;
43 margin: -1px;
44 overflow: hidden;
45 clip: rect(0, 0, 0, 0);
46 white-space: nowrap;
47 border: 0;
48}
49
50/* Color contrast helpers */
51.ensure-contrast {
52 background: var(--bg-color);
53 color: contrast-color(var(--bg-color)); /* Future CSS function */
54}1const futureCSSTrends = {
2 shortTerm: [
3 'Widespread Container Queries adoption',
4 'CSS Nesting in all browsers',
5 'View Transitions API expansion',
6 'Better CSS Houdini support'
7 ],
8
9 mediumTerm: [
10 'CSS Anchor Positioning',
11 'Advanced color functions',
12 'Scroll-driven animations',
13 'CSS Modules native support'
14 ],
15
16 longTerm: [
17 'CSS Variables 2.0 with functions',
18 'CSS Layout API (Houdini)',
19 'CSS Parser API',
20 'Advanced typography controls'
21 ],
22
23 emerging: [
24 'CSS Container Style Queries',
25 'CSS Conditional Rules Level 4',
26 'CSS Spatial Navigation',
27 'CSS Environment Variables'
28 ]
29};
30
31// Developer priorities
32const developerWants = {
33 features: [
34 'Better debugging tools',
35 'Native CSS mixins',
36 'Improved CSS math functions',
37 'Cross-browser consistency'
38 ],
39
40 tooling: [
41 'Faster build tools',
42 'Better IntelliSense',
43 'Visual CSS editors',
44 'Performance analyzers'
45 ],
46
47 ecosystem: [
48 'Standardized design tokens',
49 'Better framework interop',
50 'Component sharing standards',
51 'CSS testing tools'
52 ]
53};1/* Future design token approach */
2@design-tokens {
3 --color-primary: #007bff;
4 --color-secondary: #6c757d;
5 --space-xs: 0.25rem;
6 --space-sm: 0.5rem;
7 --space-md: 1rem;
8 --typography-heading-1: {
9 font-family: Inter, sans-serif;
10 font-size: 2.5rem;
11 font-weight: 700;
12 line-height: 1.2;
13 };
14}
15
16/* Advanced component definition */
17@component button {
18 base: {
19 display: inline-flex;
20 align-items: center;
21 padding: var(--space-sm) var(--space-md);
22 border: none;
23 border-radius: 0.375rem;
24 cursor: pointer;
25 transition: all 0.15s ease;
26 };
27
28 variants: {
29 variant: {
30 primary: {
31 background: var(--color-primary);
32 color: white;
33 },
34 secondary: {
35 background: var(--color-secondary);
36 color: white;
37 }
38 },
39
40 size: {
41 small: {
42 padding: var(--space-xs) var(--space-sm);
43 font-size: 0.875rem;
44 },
45 large: {
46 padding: var(--space-md) var(--space-lg);
47 font-size: 1.125rem;
48 }
49 }
50 }
51}