Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Cascade Layers - kontrolowanie kolejności w kaskadzie CSS

CSS Cascade Layers (@layer) to potężna funkcjonalność CSS, która pozwala na jawne kontrolowanie kolejności kaskady stylów. Umożliwia organizowanie CSS w logiczne warstwy z określoną hierarchią ważności, co znacząco ułatwia zarządzanie złożonymi arkuszami stylów.

Podstawy Cascade Layers

Czym są Cascade Layers?

Cascade Layers pozwalają na definiowanie nazwanych warstw CSS, gdzie style z warstw wyższych w hierarchii mają pierwszeństwo przed stylami z warstw niższych, niezależnie od specyficzności selektorów.

1/* Definicja warstwy i jej stylów */
2@layer reset {
3  * {
4    margin: 0;
5    padding: 0;
6    box-sizing: border-box;
7  }
8}
9
10@layer base {
11  body {
12    font-family: 'Inter', sans-serif;
13    line-height: 1.6;
14    color: #333;
15  }
16  
17  h1, h2, h3, h4, h5, h6 {
18    margin-bottom: 0.5em;
19    font-weight: 600;
20  }
21}
22
23@layer components {
24  .button {
25    padding: 0.75rem 1.5rem;
26    border: none;
27    border-radius: 6px;
28    background: #007bff;
29    color: white;
30    cursor: pointer;
31  }
32}
33
34@layer utilities {
35  .text-center { text-align: center; }
36  .hidden { display: none; }
37  .mt-4 { margin-top: 1rem; }
38}

Deklarowanie kolejności warstw

Można jawnie zdefiniować kolejność warstw na początku arkusza stylów:

1/* Definicja kolejności warstw - od najniższego do najwyższego priorytetu */
2@layer reset, base, layout, components, utilities;
3
4/* Teraz można używać warstw w dowolnej kolejności w kodzie */
5
6@layer utilities {
7  .text-red { color: red; }
8}
9
10@layer reset {
11  * { margin: 0; }
12}
13
14@layer components {
15  .card {
16    background: white;
17    border: 1px solid #ddd;
18    padding: 1rem;
19  }
20}
21
22/* Kolejność definicji w kodzie nie ma znaczenia - liczy się kolejność w deklaracji @layer */

Zaawansowane techniki Cascade Layers

1. Zagnieżdżanie warstw

1@layer framework {
2  /* Warstwy zagnieżdżone w warstwie framework */
3  @layer reset {
4    *, *::before, *::after {
5      box-sizing: border-box;
6      margin: 0;
7      padding: 0;
8    }
9    
10    html {
11      line-height: 1.15;
12      -webkit-text-size-adjust: 100%;
13    }
14  }
15  
16  @layer base {
17    body {
18      font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
19      font-size: 1rem;
20      line-height: 1.6;
21      color: #212529;
22      background: #ffffff;
23    }
24    
25    img, svg {
26      display: block;
27      max-width: 100%;
28      height: auto;
29    }
30    
31    button, input, select, textarea {
32      font: inherit;
33    }
34  }
35  
36  @layer layout {
37    .container {
38      width: 100%;
39      max-width: 1200px;
40      margin: 0 auto;
41      padding: 0 1rem;
42    }
43    
44    .grid {
45      display: grid;
46      gap: 1rem;
47    }
48    
49    .flex {
50      display: flex;
51      align-items: center;
52      gap: 1rem;
53    }
54    
55    @media (min-width: 768px) {
56      .container {
57        padding: 0 2rem;
58      }
59      
60      .grid {
61        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
62        gap: 2rem;
63      }
64    }
65  }
66  
67  @layer components {
68    /* Komponenty UI */
69    .btn {
70      --btn-padding: 0.75rem 1.5rem;
71      --btn-border-radius: 6px;
72      --btn-font-weight: 500;
73      --btn-transition: all 0.2s ease;
74      
75      display: inline-flex;
76      align-items: center;
77      justify-content: center;
78      padding: var(--btn-padding);
79      border: 1px solid transparent;
80      border-radius: var(--btn-border-radius);
81      font-weight: var(--btn-font-weight);
82      text-decoration: none;
83      cursor: pointer;
84      transition: var(--btn-transition);
85      
86      &:focus {
87        outline: 2px solid transparent;
88        box-shadow: 0 0 0 2px rgba(66, 153, 225, 0.5);
89      }
90      
91      &:disabled {
92        opacity: 0.6;
93        cursor: not-allowed;
94      }
95    }
96    
97    .btn-primary {
98      background: #007bff;
99      color: white;
100      border-color: #007bff;
101      
102      &:hover:not(:disabled) {
103        background: #0056b3;
104        border-color: #0056b3;
105      }
106    }
107    
108    .btn-secondary {
109      background: #6c757d;
110      color: white;
111      border-color: #6c757d;
112      
113      &:hover:not(:disabled) {
114        background: #545b62;
115        border-color: #545b62;
116      }
117    }
118    
119    .btn-outline {
120      background: transparent;
121      color: #007bff;
122      border-color: #007bff;
123      
124      &:hover:not(:disabled) {
125        background: #007bff;
126        color: white;
127      }
128    }
129    
130    /* Card component */
131    .card {
132      background: white;
133      border: 1px solid #e9ecef;
134      border-radius: 12px;
135      overflow: hidden;
136      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
137      transition: all 0.3s ease;
138      
139      &:hover {
140        box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
141        transform: translateY(-2px);
142      }
143    }
144    
145    .card-header {
146      padding: 1.5rem;
147      border-bottom: 1px solid #e9ecef;
148      background: #f8f9fa;
149    }
150    
151    .card-body {
152      padding: 1.5rem;
153    }
154    
155    .card-footer {
156      padding: 1rem 1.5rem;
157      border-top: 1px solid #e9ecef;
158      background: #f8f9fa;
159    }
160    
161    /* Alert component */
162    .alert {
163      --alert-padding: 1rem 1.5rem;
164      --alert-border-radius: 8px;
165      --alert-border-width: 1px;
166      
167      padding: var(--alert-padding);
168      border: var(--alert-border-width) solid transparent;
169      border-radius: var(--alert-border-radius);
170      margin-bottom: 1rem;
171      
172      .alert-title {
173        font-weight: 600;
174        margin-bottom: 0.5rem;
175      }
176      
177      &.alert-info {
178        background: #e3f2fd;
179        border-color: #2196f3;
180        color: #0d47a1;
181      }
182      
183      &.alert-success {
184        background: #e8f5e8;
185        border-color: #4caf50;
186        color: #1b5e20;
187      }
188      
189      &.alert-warning {
190        background: #fff3e0;
191        border-color: #ff9800;
192        color: #e65100;
193      }
194      
195      &.alert-error {
196        background: #ffebee;
197        border-color: #f44336;
198        color: #b71c1c;
199      }
200    }
201  }
202}
203
204/* Style zewnętrzne (wyższy priorytet od framework) */
205@layer application {
206  /* Nadpisania specyficzne dla aplikacji */
207  .btn-primary {
208    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
209    border: none;
210    
211    &:hover:not(:disabled) {
212      background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
213    }
214  }
215  
216  .card {
217    backdrop-filter: blur(10px);
218    background: rgba(255, 255, 255, 0.9);
219  }
220}
221
222/* Utilities - najwyższy priorytet */
223@layer utilities {
224  /* Klasy pomocnicze o najwyższym priorytecie */
225  .text-left { text-align: left !important; }
226  .text-center { text-align: center !important; }
227  .text-right { text-align: right !important; }
228  
229  .d-none { display: none !important; }
230  .d-block { display: block !important; }
231  .d-flex { display: flex !important; }
232  .d-grid { display: grid !important; }
233  
234  .m-0 { margin: 0 !important; }
235  .m-1 { margin: 0.25rem !important; }
236  .m-2 { margin: 0.5rem !important; }
237  .m-3 { margin: 1rem !important; }
238  .m-4 { margin: 1.5rem !important; }
239  .m-5 { margin: 3rem !important; }
240  
241  .p-0 { padding: 0 !important; }
242  .p-1 { padding: 0.25rem !important; }
243  .p-2 { padding: 0.5rem !important; }
244  .p-3 { padding: 1rem !important; }
245  .p-4 { padding: 1.5rem !important; }
246  .p-5 { padding: 3rem !important; }
247  
248  /* Responsive utilities */
249  @media (min-width: 768px) {
250    .md\:text-left { text-align: left !important; }
251    .md\:text-center { text-align: center !important; }
252    .md\:text-right { text-align: right !important; }
253    
254    .md\:d-none { display: none !important; }
255    .md\:d-block { display: block !important; }
256    .md\:d-flex { display: flex !important; }
257  }
258  
259  @media (min-width: 1024px) {
260    .lg\:text-left { text-align: left !important; }
261    .lg\:text-center { text-align: center !important; }
262    .lg\:text-right { text-align: right !important; }
263    
264    .lg\:d-none { display: none !important; }
265    .lg\:d-block { display: block !important; }
266    .lg\:d-flex { display: flex !important; }
267  }
268}

2. Warunkowe warstwy

1/* Warstwy z media queries */
2@layer responsive {
3  @media (max-width: 767px) {
4    .mobile-only {
5      display: block;
6    }
7    
8    .desktop-only {
9      display: none;
10    }
11    
12    .container {
13      padding: 0 1rem;
14    }
15    
16    .grid {
17      grid-template-columns: 1fr;
18    }
19  }
20  
21  @media (min-width: 768px) {
22    .mobile-only {
23      display: none;
24    }
25    
26    .desktop-only {
27      display: block;
28    }
29    
30    .container {
31      padding: 0 2rem;
32    }
33  }
34}
35
36/* Warstwy z feature queries */
37@layer modern {
38  @supports (display: grid) {
39    .grid-layout {
40      display: grid;
41      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
42      gap: 1rem;
43    }
44  }
45  
46  @supports not (display: grid) {
47    .grid-layout {
48      display: flex;
49      flex-wrap: wrap;
50      gap: 1rem;
51    }
52    
53    .grid-layout > * {
54      flex: 1 1 250px;
55    }
56  }
57  
58  @supports (container-type: inline-size) {
59    .responsive-component {
60      container-type: inline-size;
61    }
62    
63    @container (min-width: 400px) {
64      .responsive-component .card {
65        display: flex;
66        align-items: center;
67        gap: 1rem;
68      }
69    }
70  }
71}
72
73/* Theme layers */
74@layer themes {
75  [data-theme="light"] {
76    --bg-primary: #ffffff;
77    --bg-secondary: #f8f9fa;
78    --text-primary: #212529;
79    --text-secondary: #6c757d;
80    --border-color: #dee2e6;
81  }
82  
83  [data-theme="dark"] {
84    --bg-primary: #1a1a1a;
85    --bg-secondary: #2d2d2d;
86    --text-primary: #ffffff;
87    --text-secondary: #b0b0b0;
88    --border-color: #404040;
89  }
90  
91  [data-theme="blue"] {
92    --bg-primary: #0f1419;
93    --bg-secondary: #1e2a35;
94    --text-primary: #ffffff;
95    --text-secondary: #8fa3b0;
96    --border-color: #2a3f50;
97  }
98}

Praktyczne zastosowania Cascade Layers

1. Architektura CSS w dużych projektach

1/* Definicja głównej architektury */
2@layer normalize, base, layout, components, pages, themes, utilities;
3
4/* 1. Normalize/Reset */
5@layer normalize {
6  /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
7  
8  html {
9    line-height: 1.15;
10    -webkit-text-size-adjust: 100%;
11  }
12  
13  body {
14    margin: 0;
15  }
16  
17  main {
18    display: block;
19  }
20  
21  h1 {
22    font-size: 2em;
23    margin: 0.67em 0;
24  }
25  
26  /* ... reszta normalize.css ... */
27}
28
29/* 2. Base styles */
30@layer base {
31  :root {
32    /* Design tokens */
33    --font-family-base: 'Inter', system-ui, sans-serif;
34    --font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
35    
36    --font-size-xs: 0.75rem;
37    --font-size-sm: 0.875rem;
38    --font-size-base: 1rem;
39    --font-size-lg: 1.125rem;
40    --font-size-xl: 1.25rem;
41    --font-size-2xl: 1.5rem;
42    --font-size-3xl: 1.875rem;
43    --font-size-4xl: 2.25rem;
44    
45    --color-primary: #007bff;
46    --color-secondary: #6c757d;
47    --color-success: #28a745;
48    --color-warning: #ffc107;
49    --color-danger: #dc3545;
50    --color-info: #17a2b8;
51    
52    --spacing-xs: 0.25rem;
53    --spacing-sm: 0.5rem;
54    --spacing-md: 1rem;
55    --spacing-lg: 1.5rem;
56    --spacing-xl: 2rem;
57    --spacing-2xl: 2.5rem;
58    --spacing-3xl: 3rem;
59    
60    --border-radius-sm: 4px;
61    --border-radius-md: 8px;
62    --border-radius-lg: 12px;
63    --border-radius-xl: 16px;
64    --border-radius-full: 50%;
65    
66    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
67    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
68    --shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.15);
69  }
70  
71  body {
72    font-family: var(--font-family-base);
73    font-size: var(--font-size-base);
74    line-height: 1.6;
75    color: var(--text-primary, #212529);
76    background: var(--bg-primary, #ffffff);
77  }
78  
79  h1, h2, h3, h4, h5, h6 {
80    margin-top: 0;
81    margin-bottom: var(--spacing-md);
82    font-weight: 600;
83    line-height: 1.2;
84    color: var(--text-primary, #212529);
85  }
86  
87  p {
88    margin-top: 0;
89    margin-bottom: var(--spacing-md);
90    color: var(--text-secondary, #6c757d);
91  }
92  
93  a {
94    color: var(--color-primary);
95    text-decoration: none;
96    
97    &:hover {
98      text-decoration: underline;
99    }
100  }
101  
102  img, svg {
103    display: block;
104    max-width: 100%;
105    height: auto;
106  }
107  
108  code {
109    font-family: var(--font-family-mono);
110    font-size: 0.9em;
111    background: rgba(0, 0, 0, 0.1);
112    padding: 0.2em 0.4em;
113    border-radius: var(--border-radius-sm);
114  }
115}
116
117/* 3. Layout patterns */
118@layer layout {
119  .container {
120    width: 100%;
121    max-width: 1200px;
122    margin: 0 auto;
123    padding: 0 var(--spacing-md);
124  }
125  
126  .container-fluid {
127    width: 100%;
128    padding: 0 var(--spacing-md);
129  }
130  
131  .row {
132    display: flex;
133    flex-wrap: wrap;
134    margin: 0 calc(var(--spacing-md) * -0.5);
135  }
136  
137  .col {
138    flex: 1;
139    padding: 0 calc(var(--spacing-md) * 0.5);
140  }
141  
142  .grid {
143    display: grid;
144    gap: var(--spacing-md);
145  }
146  
147  .grid-auto {
148    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
149  }
150  
151  .flex {
152    display: flex;
153  }
154  
155  .flex-column {
156    flex-direction: column;
157  }
158  
159  .items-center {
160    align-items: center;
161  }
162  
163  .justify-center {
164    justify-content: center;
165  }
166  
167  .justify-between {
168    justify-content: space-between;
169  }
170  
171  .gap-sm { gap: var(--spacing-sm); }
172  .gap-md { gap: var(--spacing-md); }
173  .gap-lg { gap: var(--spacing-lg); }
174  
175  @media (min-width: 768px) {
176    .container {
177      padding: 0 var(--spacing-lg);
178    }
179    
180    .grid {
181      gap: var(--spacing-lg);
182    }
183    
184    .md\:flex-row {
185      flex-direction: row;
186    }
187    
188    .md\:gap-xl {
189      gap: var(--spacing-xl);
190    }
191  }
192  
193  @media (min-width: 1024px) {
194    .container {
195      padding: 0 var(--spacing-xl);
196    }
197    
198    .lg\:grid-cols-3 {
199      grid-template-columns: repeat(3, 1fr);
200    }
201    
202    .lg\:grid-cols-4 {
203      grid-template-columns: repeat(4, 1fr);
204    }
205  }
206}
207
208/* 4. Reusable components */
209@layer components {
210  /* Button system */
211  .btn {
212    --btn-padding-y: var(--spacing-sm);
213    --btn-padding-x: var(--spacing-md);
214    --btn-font-size: var(--font-size-base);
215    --btn-border-radius: var(--border-radius-md);
216    
217    display: inline-flex;
218    align-items: center;
219    justify-content: center;
220    padding: var(--btn-padding-y) var(--btn-padding-x);
221    font-size: var(--btn-font-size);
222    font-weight: 500;
223    border: 1px solid transparent;
224    border-radius: var(--btn-border-radius);
225    text-decoration: none;
226    cursor: pointer;
227    transition: all 0.2s ease;
228    user-select: none;
229    
230    &:focus {
231      outline: 2px solid transparent;
232      box-shadow: 0 0 0 2px rgba(66, 153, 225, 0.5);
233    }
234    
235    &:disabled {
236      opacity: 0.6;
237      cursor: not-allowed;
238      pointer-events: none;
239    }
240    
241    /* Size variants */
242    &.btn-sm {
243      --btn-padding-y: var(--spacing-xs);
244      --btn-padding-x: var(--spacing-sm);
245      --btn-font-size: var(--font-size-sm);
246    }
247    
248    &.btn-lg {
249      --btn-padding-y: var(--spacing-md);
250      --btn-padding-x: var(--spacing-lg);
251      --btn-font-size: var(--font-size-lg);
252    }
253    
254    /* Color variants */
255    &.btn-primary {
256      background: var(--color-primary);
257      color: white;
258      border-color: var(--color-primary);
259      
260      &:hover:not(:disabled) {
261        background: color-mix(in srgb, var(--color-primary) 90%, black);
262        border-color: color-mix(in srgb, var(--color-primary) 90%, black);
263      }
264    }
265    
266    &.btn-secondary {
267      background: var(--color-secondary);
268      color: white;
269      border-color: var(--color-secondary);
270      
271      &:hover:not(:disabled) {
272        background: color-mix(in srgb, var(--color-secondary) 90%, black);
273        border-color: color-mix(in srgb, var(--color-secondary) 90%, black);
274      }
275    }
276    
277    &.btn-outline {
278      background: transparent;
279      color: var(--color-primary);
280      border-color: var(--color-primary);
281      
282      &:hover:not(:disabled) {
283        background: var(--color-primary);
284        color: white;
285      }
286    }
287    
288    &.btn-ghost {
289      background: transparent;
290      color: var(--color-primary);
291      border-color: transparent;
292      
293      &:hover:not(:disabled) {
294        background: rgba(var(--color-primary-rgb, 0, 123, 255), 0.1);
295      }
296    }
297  }
298  
299  /* Card system */
300  .card {
301    background: var(--bg-primary, white);
302    border: 1px solid var(--border-color, #e9ecef);
303    border-radius: var(--border-radius-lg);
304    overflow: hidden;
305    box-shadow: var(--shadow-sm);
306    transition: all 0.3s ease;
307    
308    &.card-hover:hover {
309      box-shadow: var(--shadow-lg);
310      transform: translateY(-2px);
311    }
312    
313    .card-header {
314      padding: var(--spacing-lg);
315      border-bottom: 1px solid var(--border-color, #e9ecef);
316      background: var(--bg-secondary, #f8f9fa);
317      
318      .card-title {
319        margin: 0 0 var(--spacing-xs) 0;
320        font-size: var(--font-size-lg);
321        font-weight: 600;
322        color: var(--text-primary);
323      }
324      
325      .card-subtitle {
326        margin: 0;
327        font-size: var(--font-size-sm);
328        color: var(--text-secondary);
329      }
330    }
331    
332    .card-body {
333      padding: var(--spacing-lg);
334    }
335    
336    .card-footer {
337      padding: var(--spacing-md) var(--spacing-lg);
338      border-top: 1px solid var(--border-color, #e9ecef);
339      background: var(--bg-secondary, #f8f9fa);
340    }
341  }
342  
343  /* Form components */
344  .form-group {
345    margin-bottom: var(--spacing-md);
346  }
347  
348  .form-label {
349    display: block;
350    margin-bottom: var(--spacing-xs);
351    font-weight: 500;
352    color: var(--text-primary);
353  }
354  
355  .form-control {
356    width: 100%;
357    padding: var(--spacing-sm) var(--spacing-md);
358    font-size: var(--font-size-base);
359    border: 1px solid var(--border-color, #ced4da);
360    border-radius: var(--border-radius-md);
361    background: var(--bg-primary, white);
362    color: var(--text-primary);
363    transition: all 0.2s ease;
364    
365    &:focus {
366      outline: none;
367      border-color: var(--color-primary);
368      box-shadow: 0 0 0 2px rgba(var(--color-primary-rgb, 0, 123, 255), 0.25);
369    }
370
371    &::placeholder {
372      color: var(--text-muted, #adb5bd);
373    }
374    
375    &:disabled {
376      background: var(--bg-secondary, #f8f9fa);
377      opacity: 0.6;
378      cursor: not-allowed;
379    }
380  }
381  
382  textarea.form-control {
383    resize: vertical;
384    min-height: 100px;
385  }
386  
387  .form-text {
388    margin-top: var(--spacing-xs);
389    font-size: var(--font-size-sm);
390    color: var(--text-muted, #6c757d);
391  }
392  
393  .form-error {
394    margin-top: var(--spacing-xs);
395    font-size: var(--font-size-sm);
396    color: var(--color-danger);
397  }
398}
399
400/* 5. Page-specific styles */
401@layer pages {
402  .page-home {
403    .hero {
404      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
405      color: white;
406      padding: var(--spacing-3xl) 0;
407      text-align: center;
408      
409      .hero-title {
410        font-size: var(--font-size-4xl);
411        margin-bottom: var(--spacing-md);
412      }
413      
414      .hero-subtitle {
415        font-size: var(--font-size-xl);
416        opacity: 0.9;
417        margin-bottom: var(--spacing-xl);
418      }
419    }
420    
421    .features {
422      padding: var(--spacing-3xl) 0;
423      
424      .feature-grid {
425        display: grid;
426        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
427        gap: var(--spacing-xl);
428      }
429      
430      .feature-card {
431        text-align: center;
432        padding: var(--spacing-lg);
433        
434        .feature-icon {
435          width: 60px;
436          height: 60px;
437          margin: 0 auto var(--spacing-md);
438          background: var(--color-primary);
439          border-radius: var(--border-radius-full);
440          display: flex;
441          align-items: center;
442          justify-content: center;
443          color: white;
444          font-size: var(--font-size-xl);
445        }
446        
447        .feature-title {
448          font-size: var(--font-size-lg);
449          margin-bottom: var(--spacing-sm);
450        }
451        
452        .feature-description {
453          color: var(--text-secondary);
454        }
455      }
456    }
457  }
458  
459  .page-about {
460    .team-grid {
461      display: grid;
462      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
463      gap: var(--spacing-lg);
464    }
465    
466    .team-member {
467      text-align: center;
468      
469      .member-avatar {
470        width: 150px;
471        height: 150px;
472        border-radius: var(--border-radius-full);
473        margin: 0 auto var(--spacing-md);
474        object-fit: cover;
475      }
476      
477      .member-name {
478        font-size: var(--font-size-lg);
479        margin-bottom: var(--spacing-xs);
480      }
481      
482      .member-role {
483        color: var(--color-primary);
484        font-weight: 500;
485        margin-bottom: var(--spacing-sm);
486      }
487      
488      .member-bio {
489        color: var(--text-secondary);
490        font-size: var(--font-size-sm);
491      }
492    }
493  }
494}
495
496/* 6. Theme overrides */
497@layer themes {
498  /* Light theme (default) */
499  :root,
500  [data-theme="light"] {
501    --bg-primary: #ffffff;
502    --bg-secondary: #f8f9fa;
503    --text-primary: #212529;
504    --text-secondary: #6c757d;
505    --text-muted: #adb5bd;
506    --border-color: #dee2e6;
507    --color-primary-rgb: 0, 123, 255;
508  }
509  
510  /* Dark theme */
511  [data-theme="dark"] {
512    --bg-primary: #1a1a1a;
513    --bg-secondary: #2d2d2d;
514    --text-primary: #ffffff;
515    --text-secondary: #b0b0b0;
516    --text-muted: #6c757d;
517    --border-color: #404040;
518    
519    .card {
520      background: rgba(255, 255, 255, 0.05);
521      backdrop-filter: blur(10px);
522    }
523    
524    .form-control {
525      background: var(--bg-secondary);
526      border-color: var(--border-color);
527      
528      &:focus {
529        background: var(--bg-primary);
530      }
531    }
532  }
533  
534  /* Blue theme */
535  [data-theme="blue"] {
536    --bg-primary: #0f1419;
537    --bg-secondary: #1e2a35;
538    --text-primary: #ffffff;
539    --text-secondary: #8fa3b0;
540    --text-muted: #6c7b7f;
541    --border-color: #2a3f50;
542    --color-primary: #4fc3f7;
543    --color-primary-rgb: 79, 195, 247;
544  }
545  
546  /* System preference */
547  @media (prefers-color-scheme: dark) {
548    :root:not([data-theme]) {
549      --bg-primary: #1a1a1a;
550      --bg-secondary: #2d2d2d;
551      --text-primary: #ffffff;
552      --text-secondary: #b0b0b0;
553      --text-muted: #6c757d;
554      --border-color: #404040;
555    }
556  }
557}
558
559/* 7. Utility classes - highest priority */
560@layer utilities {
561  /* Display */
562  .d-none { display: none !important; }
563  .d-block { display: block !important; }
564  .d-inline { display: inline !important; }
565  .d-inline-block { display: inline-block !important; }
566  .d-flex { display: flex !important; }
567  .d-grid { display: grid !important; }
568  
569  /* Positioning */
570  .position-relative { position: relative !important; }
571  .position-absolute { position: absolute !important; }
572  .position-fixed { position: fixed !important; }
573  .position-sticky { position: sticky !important; }
574  
575  /* Text alignment */
576  .text-left { text-align: left !important; }
577  .text-center { text-align: center !important; }
578  .text-right { text-align: right !important; }
579  .text-justify { text-align: justify !important; }
580  
581  /* Font weights */
582  .fw-normal { font-weight: 400 !important; }
583  .fw-medium { font-weight: 500 !important; }
584  .fw-semibold { font-weight: 600 !important; }
585  .fw-bold { font-weight: 700 !important; }
586  
587  /* Colors */
588  .text-primary { color: var(--color-primary) !important; }
589  .text-secondary { color: var(--text-secondary) !important; }
590  .text-muted { color: var(--text-muted) !important; }
591  .text-success { color: var(--color-success) !important; }
592  .text-warning { color: var(--color-warning) !important; }
593  .text-danger { color: var(--color-danger) !important; }
594  
595  /* Background colors */
596  .bg-primary { background-color: var(--color-primary) !important; }
597  .bg-secondary { background-color: var(--bg-secondary) !important; }
598  .bg-success { background-color: var(--color-success) !important; }
599  .bg-warning { background-color: var(--color-warning) !important; }
600  .bg-danger { background-color: var(--color-danger) !important; }
601  
602  /* Spacing utilities */
603  .m-0 { margin: 0 !important; }
604  .m-1 { margin: var(--spacing-xs) !important; }
605  .m-2 { margin: var(--spacing-sm) !important; }
606  .m-3 { margin: var(--spacing-md) !important; }
607  .m-4 { margin: var(--spacing-lg) !important; }
608  .m-5 { margin: var(--spacing-xl) !important; }
609  
610  .p-0 { padding: 0 !important; }
611  .p-1 { padding: var(--spacing-xs) !important; }
612  .p-2 { padding: var(--spacing-sm) !important; }
613  .p-3 { padding: var(--spacing-md) !important; }
614  .p-4 { padding: var(--spacing-lg) !important; }
615  .p-5 { padding: var(--spacing-xl) !important; }
616  
617  /* Margin/padding directional */
618  .mt-0 { margin-top: 0 !important; }
619  .mt-1 { margin-top: var(--spacing-xs) !important; }
620  .mt-2 { margin-top: var(--spacing-sm) !important; }
621  .mt-3 { margin-top: var(--spacing-md) !important; }
622  .mt-4 { margin-top: var(--spacing-lg) !important; }
623  .mt-5 { margin-top: var(--spacing-xl) !important; }
624  
625  .mb-0 { margin-bottom: 0 !important; }
626  .mb-1 { margin-bottom: var(--spacing-xs) !important; }
627  .mb-2 { margin-bottom: var(--spacing-sm) !important; }
628  .mb-3 { margin-bottom: var(--spacing-md) !important; }
629  .mb-4 { margin-bottom: var(--spacing-lg) !important; }
630  .mb-5 { margin-bottom: var(--spacing-xl) !important; }
631  
632  .pt-0 { padding-top: 0 !important; }
633  .pt-1 { padding-top: var(--spacing-xs) !important; }
634  .pt-2 { padding-top: var(--spacing-sm) !important; }
635  .pt-3 { padding-top: var(--spacing-md) !important; }
636  .pt-4 { padding-top: var(--spacing-lg) !important; }
637  .pt-5 { padding-top: var(--spacing-xl) !important; }
638  
639  .pb-0 { padding-bottom: 0 !important; }
640  .pb-1 { padding-bottom: var(--spacing-xs) !important; }
641  .pb-2 { padding-bottom: var(--spacing-sm) !important; }
642  .pb-3 { padding-bottom: var(--spacing-md) !important; }
643  .pb-4 { padding-bottom: var(--spacing-lg) !important; }
644  .pb-5 { padding-bottom: var(--spacing-xl) !important; }
645  
646  /* Responsive utilities */
647  @media (min-width: 768px) {
648    .md\:d-none { display: none !important; }
649    .md\:d-block { display: block !important; }
650    .md\:d-flex { display: flex !important; }
651    .md\:text-left { text-align: left !important; }
652    .md\:text-center { text-align: center !important; }
653    .md\:text-right { text-align: right !important; }
654  }
655  
656  @media (min-width: 1024px) {
657    .lg\:d-none { display: none !important; }
658    .lg\:d-block { display: block !important; }
659    .lg\:d-flex { display: flex !important; }
660    .lg\:text-left { text-align: left !important; }
661    .lg\:text-center { text-align: center !important; }
662    .lg\:text-right { text-align: right !important; }
663  }
664}

2. Integracja z frameworkami CSS

1/* Integracja z Tailwind CSS */
2@layer tailwind-base, components, tailwind-utilities;
3
4@layer tailwind-base {
5  /* Tailwind's base styles */
6  @tailwind base;
7}
8
9@layer components {
10  /* Custom components over Tailwind's base */
11  .btn-custom {
12    @apply px-4 py-2 bg-blue-500 text-white rounded-lg;
13    
14    &:hover {
15      @apply bg-blue-600;
16    }
17  }
18  
19  .card-custom {
20    @apply bg-white shadow-lg rounded-xl p-6;
21    
22    .card-title {
23      @apply text-xl font-semibold mb-2;
24    }
25    
26    .card-content {
27      @apply text-gray-600 leading-relaxed;
28    }
29  }
30}
31
32@layer tailwind-utilities {
33  /* Tailwind's utilities have highest priority */
34  @tailwind utilities;
35}
36
37/* Integracja z Bootstrap */
38@layer bootstrap-reboot, bootstrap-grid, components, bootstrap-utilities;
39
40@layer bootstrap-reboot {
41  /* Bootstrap's reboot styles */
42}
43
44@layer bootstrap-grid {
45  /* Bootstrap's grid system */
46  .container {
47    width: 100%;
48    padding-right: 15px;
49    padding-left: 15px;
50    margin-right: auto;
51    margin-left: auto;
52  }
53  
54  .row {
55    display: flex;
56    flex-wrap: wrap;
57    margin-right: -15px;
58    margin-left: -15px;
59  }
60  
61  .col {
62    flex: 1 0 0%;
63    padding-right: 15px;
64    padding-left: 15px;
65  }
66}
67
68@layer components {
69  /* Custom components that enhance Bootstrap */
70  .btn-gradient {
71    background: linear-gradient(45deg, #007bff, #0056b3);
72    border: none;
73    
74    &:hover {
75      background: linear-gradient(45deg, #0056b3, #004085);
76    }
77  }
78  
79  .card-modern {
80    backdrop-filter: blur(10px);
81    background: rgba(255, 255, 255, 0.9);
82    border: 1px solid rgba(255, 255, 255, 0.2);
83  }
84}
85
86@layer bootstrap-utilities {
87  /* Bootstrap's utility classes */
88}

Najlepsze praktyki Cascade Layers

1. Strategia nazewnictwa i organizacji

1/* ✅ Dobrze - logiczna hierarchia warstw */
2@layer 
3  reset,           /* Reset/normalize styles */
4  base,            /* Base typography and elements */
5  layout,          /* Layout patterns and grid systems */
6  components,      /* Reusable UI components */
7  pages,           /* Page-specific styles */
8  themes,          /* Theme variations */
9  utilities;       /* Utility classes */
10
11/* ✅ Dobrze - funkcjonalne nazwy warstw */
12@layer
13  normalize,
14  design-tokens,
15  typography,
16  forms,
17  navigation,
18  content,
19  interactions,
20  responsive,
21  print;
22
23/* ❌ Źle - niejasne nazwy warstw */
24@layer layer1, layer2, layer3, misc, other;

2. Zarządzanie priorytetami

1/* ✅ Dobrze - jawne zarządzanie priorytetami */
2@layer framework, custom, overrides;
3
4@layer framework {
5  /* Kod frameworka CSS */
6  .button {
7    padding: 0.5rem 1rem;
8    background: #007bff;
9    color: white;
10  }
11}
12
13@layer custom {
14  /* Dostosowania specyficzne dla projektu */
15  .button {
16    border-radius: 8px;
17    font-weight: 500;
18  }
19}
20
21@layer overrides {
22  /* Krytyczne nadpisania */
23  .button.important {
24    background: #dc3545 !important;
25  }
26}
27
28/* ❌ Źle - poleganie tylko na !important */
29.button {
30  background: #007bff !important;
31  padding: 0.5rem 1rem !important;
32  color: white !important;
33}

3. Debugging i rozwój

1/* Helper do debugowania warstw */
2@layer debug {
3  [data-debug="layers"] * {
4    position: relative;
5  }
6  
7  [data-debug="layers"] *::before {
8    content: attr(data-layer, 'unknown');
9    position: absolute;
10    top: 0;
11    right: 0;
12    background: rgba(255, 0, 0, 0.8);
13    color: white;
14    font-size: 10px;
15    padding: 2px 4px;
16    pointer-events: none;
17    z-index: 9999;
18  }
19}
20
21/* Warstwy dla różnych środowisk */
22@layer development {
23  /* Style tylko dla developmentu */
24  .debug-grid {
25    background-image: 
26      linear-gradient(rgba(255,0,0,0.1) 1px, transparent 1px),
27      linear-gradient(90deg, rgba(255,0,0,0.1) 1px, transparent 1px);
28    background-size: 20px 20px;
29  }
30  
31  .debug-info {
32    position: fixed;
33    bottom: 10px;
34    right: 10px;
35    background: rgba(0, 0, 0, 0.8);
36    color: white;
37    padding: 10px;
38    font-family: monospace;
39    font-size: 12px;
40    border-radius: 4px;
41    z-index: 9999;
42  }
43}
44
45/* Conditional loading warstw */
46@media (max-width: 767px) {
47  @layer mobile-specific {
48    .desktop-only {
49      display: none !important;
50    }
51    
52    .mobile-nav {
53      display: block;
54    }
55  }
56}
57
58@media print {
59  @layer print {
60    * {
61      background: transparent !important;
62      color: black !important;
63      box-shadow: none !important;
64    }
65    
66    .no-print {
67      display: none !important;
68    }
69  }
70}

CSS Cascade Layers fundamentalnie zmieniają sposób zarządzania CSS w dużych projektach, oferując precyzyjną kontrolę nad kolejnością stosowania stylów i eliminując konieczność używania

!important
w większości przypadków.

Ir a CodeWorlds