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.
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}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 */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}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}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}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}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;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}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.