We use cookies to enhance your experience on the site
CodeWorlds

CSS Nesting - Native Style Nesting

CSS Nesting is a native CSS feature that allows nesting selectors inside other selectors, similar to preprocessors like Sass or Less. This significantly improves the readability and organization of CSS code.

CSS Nesting Basics

Simple Nesting

1/* Traditional CSS */
2.card {
3  padding: 1rem;
4  background: white;
5  border-radius: 8px;
6}
7
8.card h2 {
9  font-size: 1.5rem;
10  margin-bottom: 1rem;
11  color: #333;
12}
13
14.card p {
15  line-height: 1.6;
16  color: #666;
17}
18
19.card .button {
20  padding: 0.5rem 1rem;
21  background: #007bff;
22  color: white;
23  border: none;
24  border-radius: 4px;
25}
26
27/* CSS Nesting */
28.card {
29  padding: 1rem;
30  background: white;
31  border-radius: 8px;
32
33  h2 {
34    font-size: 1.5rem;
35    margin-bottom: 1rem;
36    color: #333;
37  }
38
39  p {
40    line-height: 1.6;
41    color: #666;
42  }
43
44  .button {
45    padding: 0.5rem 1rem;
46    background: #007bff;
47    color: white;
48    border: none;
49    border-radius: 4px;
50  }
51}

Using the & Symbol

The

&
symbol represents the parent selector and allows creating more complex selectors:

1.button {
2  padding: 0.75rem 1.5rem;
3  background: #007bff;
4  color: white;
5  border: none;
6  border-radius: 4px;
7  cursor: pointer;
8  transition: all 0.3s ease;
9
10  /* Hover and focus states */
11  &:hover {
12    background: #0056b3;
13    transform: translateY(-1px);
14  }
15
16  &:focus {
17    outline: none;
18    box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
19  }
20
21  &:active {
22    transform: translateY(0);
23  }
24
25  /* Button variants */
26  &.secondary {
27    background: #6c757d;
28
29    &:hover {
30      background: #545b62;
31    }
32  }
33
34  &.danger {
35    background: #dc3545;
36
37    &:hover {
38      background: #c82333;
39    }
40  }
41
42  /* State modifiers */
43  &.loading {
44    position: relative;
45    color: transparent;
46
47    &::after {
48      content: '';
49      position: absolute;
50      top: 50%;
51      left: 50%;
52      width: 16px;
53      height: 16px;
54      border: 2px solid #ffffff;
55      border-top: 2px solid transparent;
56      border-radius: 50%;
57      animation: spin 1s linear infinite;
58      transform: translate(-50%, -50%);
59    }
60  }
61
62  &:disabled {
63    opacity: 0.6;
64    cursor: not-allowed;
65
66    &:hover {
67      background: #007bff;
68      transform: none;
69    }
70  }
71}
72
73@keyframes spin {
74  0% { transform: translate(-50%, -50%) rotate(0deg); }
75  100% { transform: translate(-50%, -50%) rotate(360deg); }
76}

Advanced Nesting Techniques

Combinators and Pseudo-selectors

1.navigation {
2  display: flex;
3  align-items: center;
4  padding: 1rem 2rem;
5  background: #ffffff;
6  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
7
8  .logo {
9    font-size: 1.5rem;
10    font-weight: bold;
11    color: #007bff;
12    text-decoration: none;
13
14    &:hover {
15      color: #0056b3;
16    }
17  }
18
19  .nav-list {
20    display: flex;
21    list-style: none;
22    margin: 0 0 0 auto;
23    padding: 0;
24    gap: 2rem;
25
26    .nav-item {
27      position: relative;
28
29      .nav-link {
30        display: block;
31        padding: 0.5rem 0;
32        color: #333;
33        text-decoration: none;
34        font-weight: 500;
35        transition: color 0.3s ease;
36
37        &:hover {
38          color: #007bff;
39        }
40
41        &.active {
42          color: #007bff;
43
44          &::after {
45            content: '';
46            position: absolute;
47            bottom: -8px;
48            left: 0;
49            right: 0;
50            height: 2px;
51            background: #007bff;
52          }
53        }
54      }
55
56      /* Dropdown menu */
57      .dropdown {
58        position: absolute;
59        top: 100%;
60        left: 0;
61        min-width: 200px;
62        background: white;
63        border-radius: 8px;
64        box-shadow: 0 4px 12px rgba(0,0,0,0.15);
65        opacity: 0;
66        visibility: hidden;
67        transform: translateY(-10px);
68        transition: all 0.3s ease;
69        z-index: 1000;
70
71        .dropdown-item {
72          .dropdown-link {
73            display: block;
74            padding: 0.75rem 1rem;
75            color: #333;
76            text-decoration: none;
77
78            &:hover {
79              background: #f8f9fa;
80              color: #007bff;
81            }
82
83            &:first-child {
84              border-radius: 8px 8px 0 0;
85            }
86
87            &:last-child {
88              border-radius: 0 0 8px 8px;
89            }
90          }
91        }
92      }
93
94      /* Show dropdown on hover */
95      &:hover .dropdown {
96        opacity: 1;
97        visibility: visible;
98        transform: translateY(0);
99      }
100    }
101  }
102
103  /* Responsive navigation */
104  .mobile-toggle {
105    display: none;
106    flex-direction: column;
107    gap: 4px;
108    background: none;
109    border: none;
110    cursor: pointer;
111
112    .bar {
113      width: 25px;
114      height: 3px;
115      background: #333;
116      transition: all 0.3s ease;
117    }
118
119    &.active {
120      .bar:nth-child(1) {
121        transform: rotate(45deg) translate(5px, 5px);
122      }
123
124      .bar:nth-child(2) {
125        opacity: 0;
126      }
127
128      .bar:nth-child(3) {
129        transform: rotate(-45deg) translate(7px, -6px);
130      }
131    }
132  }
133
134  @media (max-width: 768px) {
135    .nav-list {
136      position: fixed;
137      top: 70px;
138      left: 0;
139      right: 0;
140      flex-direction: column;
141      background: white;
142      padding: 1rem 2rem;
143      transform: translateY(-100%);
144      transition: transform 0.3s ease;
145      box-shadow: 0 4px 12px rgba(0,0,0,0.15);
146
147      &.active {
148        transform: translateY(0);
149      }
150
151      .nav-item {
152        .dropdown {
153          position: static;
154          opacity: 1;
155          visibility: visible;
156          transform: none;
157          box-shadow: none;
158          background: #f8f9fa;
159          margin-top: 0.5rem;
160        }
161      }
162    }
163
164    .mobile-toggle {
165      display: flex;
166    }
167  }
168}

Nesting with Media Queries

1.hero-section {
2  display: flex;
3  align-items: center;
4  min-height: 100vh;
5  padding: 2rem;
6  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
7  color: white;
8
9  .hero-content {
10    max-width: 1200px;
11    margin: 0 auto;
12    text-align: center;
13
14    .hero-title {
15      font-size: 3.5rem;
16      font-weight: 700;
17      margin-bottom: 1.5rem;
18      line-height: 1.2;
19
20      @media (max-width: 768px) {
21        font-size: 2.5rem;
22      }
23
24      @media (max-width: 480px) {
25        font-size: 2rem;
26      }
27    }
28
29    .hero-subtitle {
30      font-size: 1.5rem;
31      font-weight: 300;
32      margin-bottom: 2rem;
33      opacity: 0.9;
34
35      @media (max-width: 768px) {
36        font-size: 1.25rem;
37      }
38
39      @media (max-width: 480px) {
40        font-size: 1.1rem;
41      }
42    }
43
44    .hero-buttons {
45      display: flex;
46      gap: 1rem;
47      justify-content: center;
48      flex-wrap: wrap;
49
50      @media (max-width: 480px) {
51        flex-direction: column;
52        align-items: center;
53      }
54
55      .btn-primary {
56        padding: 1rem 2rem;
57        font-size: 1.1rem;
58        background: rgba(255, 255, 255, 0.2);
59        border: 2px solid white;
60        color: white;
61        border-radius: 50px;
62        text-decoration: none;
63        transition: all 0.3s ease;
64        backdrop-filter: blur(10px);
65
66        &:hover {
67          background: white;
68          color: #667eea;
69          transform: translateY(-2px);
70          box-shadow: 0 8px 25px rgba(0,0,0,0.2);
71        }
72
73        @media (max-width: 480px) {
74          width: 200px;
75        }
76      }
77
78      .btn-secondary {
79        padding: 1rem 2rem;
80        font-size: 1.1rem;
81        background: transparent;
82        border: 2px solid rgba(255, 255, 255, 0.5);
83        color: white;
84        border-radius: 50px;
85        text-decoration: none;
86        transition: all 0.3s ease;
87
88        &:hover {
89          border-color: white;
90          background: rgba(255, 255, 255, 0.1);
91        }
92
93        @media (max-width: 480px) {
94          width: 200px;
95        }
96      }
97    }
98  }
99
100  @media (max-width: 768px) {
101    padding: 1rem;
102    min-height: 80vh;
103  }
104}

Practical Nesting Examples

Complex Form

1.contact-form {
2  max-width: 600px;
3  margin: 2rem auto;
4  padding: 2rem;
5  background: white;
6  border-radius: 12px;
7  box-shadow: 0 8px 25px rgba(0,0,0,0.1);
8
9  .form-header {
10    text-align: center;
11    margin-bottom: 2rem;
12
13    h2 {
14      font-size: 2rem;
15      color: #333;
16      margin-bottom: 0.5rem;
17    }
18
19    p {
20      color: #666;
21      font-size: 1.1rem;
22    }
23  }
24
25  .form-row {
26    display: flex;
27    gap: 1rem;
28    margin-bottom: 1.5rem;
29
30    @media (max-width: 600px) {
31      flex-direction: column;
32    }
33
34    .form-group {
35      flex: 1;
36
37      &.full-width {
38        flex-basis: 100%;
39      }
40    }
41  }
42
43  .form-group {
44    margin-bottom: 1.5rem;
45
46    label {
47      display: block;
48      margin-bottom: 0.5rem;
49      font-weight: 600;
50      color: #333;
51
52      .required {
53        color: #e74c3c;
54        margin-left: 0.25rem;
55      }
56    }
57
58    input, textarea, select {
59      width: 100%;
60      padding: 0.75rem;
61      border: 2px solid #e1e5e9;
62      border-radius: 8px;
63      font-size: 1rem;
64      transition: all 0.3s ease;
65      background: #fafbfc;
66
67      &:focus {
68        outline: none;
69        border-color: #007bff;
70        background: white;
71        box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
72      }
73
74      &::
75## Practical Application
76
77Practice this concept in the editor below.
78        color: #adb5bd;
79      }
80
81      &.error {
82        border-color: #e74c3c;
83        background: #fff5f5;
84
85        &:focus {
86          box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.1);
87        }
88      }
89
90      &.success {
91        border-color: #28a745;
92        background: #f8fff9;
93
94        &:focus {
95          box-shadow: 0 0 0 3px rgba(40, 167, 69, 0.1);
96        }
97      }
98    }
99
100    textarea {
101      min-height: 120px;
102      resize: vertical;
103    }
104
105    select {
106      cursor: pointer;
107      background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
108      background-position: right 0.5rem center;
109      background-repeat: no-repeat;
110      background-size: 1.5em 1.5em;
111      padding-right: 2.5rem;
112    }
113
114    .error-message {
115      display: block;
116      margin-top: 0.5rem;
117      color: #e74c3c;
118      font-size: 0.875rem;
119    }
120
121    .help-text {
122      display: block;
123      margin-top: 0.5rem;
124      color: #6c757d;
125      font-size: 0.875rem;
126    }
127  }
128
129  .checkbox-group {
130    margin: 1.5rem 0;
131
132    .checkbox-item {
133      display: flex;
134      align-items: center;
135      gap: 0.75rem;
136      margin-bottom: 1rem;
137
138      input[type="checkbox"] {
139        width: auto;
140        margin: 0;
141
142        &:checked + label::before {
143          background-color: #007bff;
144          border-color: #007bff;
145        }
146      }
147
148      label {
149        margin: 0;
150        cursor: pointer;
151        user-select: none;
152
153        a {
154          color: #007bff;
155          text-decoration: none;
156
157          &:hover {
158            text-decoration: underline;
159          }
160        }
161      }
162    }
163  }
164
165  .form-actions {
166    display: flex;
167    gap: 1rem;
168    justify-content: flex-end;
169    margin-top: 2rem;
170
171    @media (max-width: 480px) {
172      flex-direction: column;
173    }
174
175    .btn {
176      padding: 0.75rem 2rem;
177      border: none;
178      border-radius: 8px;
179      font-size: 1rem;
180      font-weight: 600;
181      cursor: pointer;
182      transition: all 0.3s ease;
183      text-decoration: none;
184      display: inline-block;
185      text-align: center;
186
187      &.btn-primary {
188        background: #007bff;
189        color: white;
190
191        &:hover:not(:disabled) {
192          background: #0056b3;
193          transform: translateY(-1px);
194        }
195
196        &:disabled {
197          opacity: 0.6;
198          cursor: not-allowed;
199        }
200      }
201
202      &.btn-secondary {
203        background: #f8f9fa;
204        color: #6c757d;
205        border: 1px solid #dee2e6;
206
207        &:hover {
208          background: #e9ecef;
209          color: #495057;
210        }
211      }
212
213      @media (max-width: 480px) {
214        width: 100%;
215      }
216    }
217  }
218
219  .loading-overlay {
220    position: absolute;
221    top: 0;
222    left: 0;
223    right: 0;
224    bottom: 0;
225    background: rgba(255, 255, 255, 0.9);
226    display: flex;
227    align-items: center;
228    justify-content: center;
229    border-radius: 12px;
230
231    .spinner {
232      width: 40px;
233      height: 40px;
234      border: 4px solid #f3f3f3;
235      border-top: 4px solid #007bff;
236      border-radius: 50%;
237      animation: spin 1s linear infinite;
238    }
239  }
240}

Card Component with Variants

1.card {
2  background: white;
3  border-radius: 12px;
4  overflow: hidden;
5  transition: all 0.3s ease;
6  position: relative;
7
8  /* Shadow variants */
9  &.shadow-sm {
10    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
11  }
12
13  &.shadow-md {
14    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
15  }
16
17  &.shadow-lg {
18    box-shadow: 0 10px 25px rgba(0,0,0,0.15);
19  }
20
21  /* Interactive variants */
22  &.hoverable {
23    cursor: pointer;
24
25    &:hover {
26      transform: translateY(-4px);
27      box-shadow: 0 12px 30px rgba(0,0,0,0.2);
28    }
29  }
30
31  &.clickable {
32    cursor: pointer;
33    user-select: none;
34
35    &:active {
36      transform: scale(0.98);
37    }
38  }
39
40  /* Card components */
41  .card-header {
42    padding: 1.5rem;
43    border-bottom: 1px solid #f0f0f0;
44
45    &.with-image {
46      padding: 0;
47      position: relative;
48
49      .header-image {
50        width: 100%;
51        height: 200px;
52        object-fit: cover;
53      }
54
55      .header-content {
56        position: absolute;
57        bottom: 0;
58        left: 0;
59        right: 0;
60        padding: 1.5rem;
61        background: linear-gradient(transparent, rgba(0,0,0,0.7));
62        color: white;
63      }
64    }
65
66    .card-title {
67      font-size: 1.5rem;
68      font-weight: 600;
69      margin: 0 0 0.5rem 0;
70      color: #333;
71
72      .card-header.with-image & {
73        color: white;
74      }
75    }
76
77    .card-subtitle {
78      font-size: 1rem;
79      color: #666;
80      margin: 0;
81
82      .card-header.with-image & {
83        color: rgba(255,255,255,0.9);
84      }
85    }
86  }
87
88  .card-body {
89    padding: 1.5rem;
90
91    .card-text {
92      line-height: 1.6;
93      color: #555;
94      margin-bottom: 1rem;
95
96      &:last-child {
97        margin-bottom: 0;
98      }
99    }
100
101    .card-meta {
102      display: flex;
103      align-items: center;
104      gap: 1rem;
105      margin-bottom: 1rem;
106      font-size: 0.9rem;
107      color: #666;
108
109      .meta-item {
110        display: flex;
111        align-items: center;
112        gap: 0.25rem;
113
114        .icon {
115          width: 16px;
116          height: 16px;
117        }
118      }
119    }
120
121    .card-tags {
122      display: flex;
123      flex-wrap: wrap;
124      gap: 0.5rem;
125      margin-bottom: 1rem;
126
127      .tag {
128        padding: 0.25rem 0.75rem;
129        background: #f8f9fa;
130        color: #495057;
131        border-radius: 20px;
132        font-size: 0.8rem;
133        font-weight: 500;
134
135        &.primary {
136          background: #e3f2fd;
137          color: #1976d2;
138        }
139
140        &.success {
141          background: #e8f5e8;
142          color: #2e7d32;
143        }
144
145        &.warning {
146          background: #fff3e0;
147          color: #f57c00;
148        }
149
150        &.danger {
151          background: #ffebee;
152          color: #d32f2f;
153        }
154      }
155    }
156  }
157
158  .card-footer {
159    padding: 1rem 1.5rem;
160    background: #f8f9fa;
161    border-top: 1px solid #f0f0f0;
162
163    .card-actions {
164      display: flex;
165      justify-content: space-between;
166      align-items: center;
167      gap: 1rem;
168
169      @media (max-width: 480px) {
170        flex-direction: column;
171        align-items: stretch;
172      }
173
174      .action-group {
175        display: flex;
176        gap: 0.5rem;
177
178        @media (max-width: 480px) {
179          justify-content: center;
180        }
181      }
182
183      .btn {
184        padding: 0.5rem 1rem;
185        border: none;
186        border-radius: 6px;
187        font-size: 0.9rem;
188        cursor: pointer;
189        text-decoration: none;
190        transition: all 0.2s ease;
191
192        &.btn-primary {
193          background: #007bff;
194          color: white;
195
196          &:hover {
197            background: #0056b3;
198          }
199        }
200
201        &.btn-outline {
202          background: transparent;
203          color: #007bff;
204          border: 1px solid #007bff;
205
206          &:hover {
207            background: #007bff;
208            color: white;
209          }
210        }
211
212        &.btn-ghost {
213          background: transparent;
214          color: #6c757d;
215
216          &:hover {
217            background: #e9ecef;
218            color: #495057;
219          }
220        }
221      }
222    }
223  }
224
225  /* Special states */
226  &.loading {
227    pointer-events: none;
228
229    &::after {
230      content: '';
231      position: absolute;
232      top: 0;
233      left: 0;
234      right: 0;
235      bottom: 0;
236      background: rgba(255,255,255,0.8);
237      display: flex;
238      align-items: center;
239      justify-content: center;
240    }
241  }
242
243  &.disabled {
244    opacity: 0.6;
245    pointer-events: none;
246  }
247}

CSS Nesting Best Practices

1. Limit Nesting Depth

1/* Good - maximum 3-4 levels */
2.header {
3  .navigation {
4    .nav-item {
5      .nav-link {
6        /* maximum level */
7      }
8    }
9  }
10}
11
12/* Bad - too deep nesting */
13.page {
14  .content {
15    .section {
16      .container {
17        .row {
18          .column {
19            .card {
20              .header {
21                /* too deep! */
22              }
23            }
24          }
25        }
26      }
27    }
28  }
29}

2. Use Meaningful Selector Names

1/* Good */
2.product-card {
3  .product-image {
4    /* styles */
5  }
6
7  .product-info {
8    .product-title { /* styles */ }
9    .product-price { /* styles */ }
10  }
11}
12
13/* Bad */
14.card {
15  .img {
16    /* styles */
17  }
18
19  .info {
20    .title { /* styles */ }
21    .price { /* styles */ }
22  }
23}

3. Group Related Styles

1.modal {
2  /* Basic layout styles */
3  position: fixed;
4  top: 0;
5  left: 0;
6  width: 100%;
7  height: 100%;
8  z-index: 1000;
9
10  /* Background and overlay */
11  .modal-backdrop {
12    position: absolute;
13    top: 0;
14    left: 0;
15    width: 100%;
16    height: 100%;
17    background: rgba(0,0,0,0.5);
18    backdrop-filter: blur(4px);
19  }
20
21  /* Modal content */
22  .modal-content {
23    position: relative;
24    max-width: 500px;
25    margin: 5% auto;
26    background: white;
27    border-radius: 12px;
28    overflow: hidden;
29
30    /* Modal components */
31    .modal-header {
32      /* styles */
33    }
34
35    .modal-body {
36      /* styles */
37    }
38
39    .modal-footer {
40      /* styles */
41    }
42  }
43
44  /* States and animations */
45  &.fade-in {
46    animation: modalFadeIn 0.3s ease;
47  }
48
49  &.fade-out {
50    animation: modalFadeOut 0.3s ease;
51  }
52}

CSS Nesting significantly improves the organization and readability of CSS code, enabling the creation of more intuitive and maintainable stylesheets. The key is to exercise restraint and follow best practices.

Go to CodeWorlds