What is Nesting?
One of SCSS's most popular features is nesting. Instead of writing separate selectors for parent and child elements, you can nest child selectors inside the parent. This mirrors your HTML structure and keeps related code together.
💡 Key Benefit:
Nesting makes your code easier to read and maintain. All styles for a component stay together, just like your HTML structure!
CSS vs SCSS Nesting
Regular CSS (Without Nesting):
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.card-grid .card {
background: white;
padding: 20px;
}
.card-grid .card h3 {
font-size: 1.5rem;
margin-bottom: 10px;
}
.card-grid .card p {
color: gray;
}
SCSS (With Nesting):
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
.card {
background: white;
padding: 20px;
h3 {
font-size: 1.5rem;
margin-bottom: 10px;
}
p {
color: gray;
}
}
}
Much cleaner! All the .card-grid styles are in one place, and the nesting shows the structure clearly.
Nesting Grid Items
Here's a practical example with a grid container and its items:
$grid-gap: 24px;
.product-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: $grid-gap;
.product-card {
// Styles for each grid item
background: white;
border-radius: 8px;
padding: 16px;
img {
width: 100%;
border-radius: 4px;
}
h4 {
margin: 12px 0;
font-size: 1.2rem;
}
.price {
color: green;
font-weight: bold;
}
}
}
This compiles to separate CSS selectors, but your source code stays organized!
Using the & (Parent Selector)
The & symbol represents the parent selector. This is super useful for hover states and modifiers:
.grid-item {
background: lightgray;
padding: 20px;
&:hover {
// Compiles to: .grid-item:hover
background: darkgray;
}
&.featured {
// Compiles to: .grid-item.featured
border: 2px solid gold;
}
&.large {
// Compiles to: .grid-item.large
grid-column: span 2;
}
}
✅ Pro Tip:
The & is your friend! Use it for hover states, active states, and modifier classes.
It keeps all variations of an element together.
Nesting Media Queries
You can even nest media queries inside your selectors - this is HUGE for responsive grids:
.container {
display: grid;
grid-template-columns: 1fr; // Mobile: 1 column
gap: 16px;
@media (min-width: 768px) {
// Tablet: 2 columns
grid-template-columns: repeat(2, 1fr);
gap: 24px;
}
@media (min-width: 1024px) {
// Desktop: 3 columns
grid-template-columns: repeat(3, 1fr);
gap: 32px;
}
.item {
background: white;
padding: 20px;
}
}
All your responsive behavior for .container is right there in one place. No hunting through your
CSS file for media queries!
Real-World Example: Complete Grid Component
$breakpoint-md: 768px;
$breakpoint-lg: 1024px;
.blog-grid {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
padding: 20px;
@media (min-width: $breakpoint-md) {
grid-template-columns: repeat(2, 1fr);
gap: 30px;
}
@media (min-width: $breakpoint-lg) {
grid-template-columns: repeat(3, 1fr);
padding: 40px;
}
.blog-card {
background: white;
border-radius: 8px;
overflow: hidden;
&:hover {
transform: translateY(-4px);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.thumbnail {
width: 100%;
height: 200px;
object-fit: cover;
}
.content {
padding: 20px;
h3 {
margin-bottom: 10px;
color: #333;
}
p {
color: #666;
line-height: 1.6;
}
}
.meta {
padding: 10px 20px;
background: #f5f5f5;
font-size: 0.875rem;
color: #999;
}
}
}
Everything for the blog grid component - layout, responsive behavior, and child styles - is organized in one logical block!
Best Practices for Nesting
⚠️ Don't Nest Too Deep:
Avoid nesting more than 3-4 levels deep. It makes CSS specificity too high and your code harder to override.
Good: .grid → .item → h3
Bad: .page → .section → .grid → .item → .content → h3
Good Nesting:
.grid {
display: grid;
.item {
padding: 20px;
h3 {
font-size: 1.5rem;
}
}
}
Too Much Nesting:
// Avoid this!
.page {
.container {
.section {
.grid {
.item {
.header {
h3 {
// Way too deep!
}
}
}
}
}
}
}