What are Loops in SCSS?
Loops let you generate CSS automatically by repeating code with different values. Instead of writing 12 separate classes for 12 grid columns, write one loop and SCSS creates them all for you. This is perfect for creating comprehensive grid systems.
The @for Loop
The @for loop repeats code a specific number of times:
// Generate column span classes
@for $i from 1 through 12 {
.col-#{$i} {
grid-column: span $i;
}
}
This creates:
/* Compiled CSS */
.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
/* ... up to ... */
.col-12 { grid-column: span 12; }
Generating Grid Template Columns
// Create 1-12 column grid classes
@for $cols from 1 through 12 {
.grid-cols-#{$cols} {
display: grid;
grid-template-columns: repeat($cols, 1fr);
}
}
Now you have .grid-cols-1 through .grid-cols-12 automatically.
The @each Loop
The @each loop iterates over a list or map:
// Loop through spacing values
$spacing-values: 0, 8, 16, 24, 32, 48, 64;
@each $space in $spacing-values {
.gap-#{$space} {
gap: #{$space}px;
}
}
Generates: .gap-0, .gap-8, .gap-16, and so on.
Loop with Maps
Use maps for more complex loop data:
$grid-breakpoints: (
sm: 640px,
md: 768px,
lg: 1024px,
xl: 1280px
);
@each $name, $width in $grid-breakpoints {
@media (min-width: $width) {
.container-#{$name} {
max-width: $width;
}
}
}
Complete Grid System with Loops
// Configuration
$grid-columns: 12;
$grid-gaps: (0, 4, 8, 12, 16, 20, 24, 32, 40, 48);
// Generate column span classes
@for $i from 1 through $grid-columns {
.col-span-#{$i} {
grid-column: span $i;
}
}
// Generate row span classes
@for $i from 1 through 6 {
.row-span-#{$i} {
grid-row: span $i;
}
}
// Generate gap utilities
@each $gap in $grid-gaps {
.gap-#{$gap} {
gap: #{$gap}px;
}
}
// Generate grid template columns
@for $cols from 1 through $grid-columns {
.grid-cols-#{$cols} {
display: grid;
grid-template-columns: repeat($cols, 1fr);
}
}
Conditional Loops with @if
Combine loops with conditions for smart generation:
@for $i from 1 through 12 {
.col-#{$i} {
grid-column: span $i;
// Special styling for half-width columns
@if $i == 6 {
border-left: 2px solid #ddd;
}
// Full width gets different treatment
@if $i == 12 {
padding: 20px 0;
}
}
}
Nested Loops for Responsive Grids
$breakpoints: (
sm: 640px,
md: 768px,
lg: 1024px
);
// Generate responsive grid classes
@each $bp-name, $bp-value in $breakpoints {
@media (min-width: $bp-value) {
@for $cols from 1 through 12 {
.#{$bp-name}\:grid-cols-#{$cols} {
grid-template-columns: repeat($cols, 1fr);
}
}
}
}
Creates classes like: .sm:grid-cols-3, .md:grid-cols-4, .lg:grid-cols-6
@while Loop (Advanced)
Less common but useful for specific cases:
$i: 1;
@while $i <= 5 {
.grid-#{$i}x {
grid-template-columns: repeat($i, 1fr);
gap: #{$i * 8}px; // Gap increases with columns
}
$i: $i + 1;
}
Practical Example: Complete Utility System
// Design tokens
$columns: 12;
$spacing-scale: (
xs: 4px,
sm: 8px,
md: 16px,
lg: 24px,
xl: 32px,
2xl: 48px
);
// Column utilities
@for $i from 1 through $columns {
.col-#{$i} {
grid-column: span $i;
}
.col-start-#{$i} {
grid-column-start: $i;
}
.grid-cols-#{$i} {
grid-template-columns: repeat($i, 1fr);
}
}
// Gap utilities from spacing scale
@each $name, $size in $spacing-scale {
.gap-#{$name} {
gap: $size;
}
.gap-x-#{$name} {
column-gap: $size;
}
.gap-y-#{$name} {
row-gap: $size;
}
}
// Grid auto-flow utilities
$flow-directions: row, column, dense, row-dense, column-dense;
@each $direction in $flow-directions {
.grid-flow-#{$direction} {
grid-auto-flow: $direction;
}
}
When to Use Loops
Good Use Cases:
- Building utility-class libraries (like your own Tailwind)
- Creating consistent spacing and sizing systems
- Generating responsive grid variations
- Pattern-based class generation
Avoid Loops For:
- One-off custom layouts (just write them directly)
- Generating classes you will never use (bloats CSS file)
- Simple 2-3 similar classes (loops are overkill)