Native CSS Nesting is Here!
Learn how to use CSS nesting to write cleaner, more maintainable stylesheets.
No more preprocessors needed! CSS now supports nesting natively. Write cleaner, more organised stylesheets with less repetition.
For years, we've relied on preprocessors like SASS and LESS for nesting. Now CSS has caught up! Native nesting means faster builds, simpler tooling, and one less dependency in your project.
/* So much repetition! */
.card {
background: white;
padding: 2rem;
}
.card h2 {
margin-bottom: 1rem;
}
.card p {
line-height: 1.6;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.card:hover h2 {
color: #2563eb;
}
/* Clean and organised! */
.card {
background: white;
padding: 2rem;
h2 {
margin-bottom: 1rem;
}
p {
line-height: 1.6;
}
&:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
h2 {
color: #2563eb;
}
}
}
/* Nested navigation styles */
.demo-nav {
background: #f3f4f6;
padding: 1rem;
border-radius: 0.5rem;
ul {
display: flex;
gap: 2rem;
list-style: none;
margin: 0;
padding: 0;
}
li {
position: relative;
&.active {
font-weight: 600;
a {
color: #2563eb;
}
&::after {
content: '';
position: absolute;
bottom: -0.5rem;
left: 0;
right: 0;
height: 2px;
background: #2563eb;
}
}
}
a {
color: #6b7280;
text-decoration: none;
transition: color 0.2s;
&:hover {
color: #111827;
}
}
}
/* Using & for parent reference */
.btn-nested {
padding: 0.75rem 1.5rem;
border: 2px solid #e5e7eb;
background: white;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.2s;
/* Modifier classes */
&.primary {
background: #2563eb;
border-color: #2563eb;
color: white;
&:hover {
background: #1d4ed8;
}
}
&.secondary {
background: #7c3aed;
border-color: #7c3aed;
color: white;
&:hover {
background: #6d28d9;
}
}
/* States */
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
&:active {
transform: translateY(0);
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
&:hover {
transform: none;
box-shadow: none;
}
}
}
Resize your browser to see me change!
/* Nested media queries */
.responsive-card {
padding: 2rem;
background: white;
border-radius: 1rem;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
h4 {
margin-bottom: 1rem;
color: #1f2937;
}
.card-grid {
display: grid;
gap: 1rem;
/* Mobile first approach */
grid-template-columns: 1fr;
@media (min-width: 640px) {
grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 1024px) {
grid-template-columns: repeat(3, 1fr);
}
}
.card-item {
padding: 1rem;
background: #f3f4f6;
border-radius: 0.5rem;
text-align: center;
@media (min-width: 640px) {
padding: 1.5rem;
}
}
}
Learn how to use CSS nesting to write cleaner, more maintainable stylesheets.
/* Complex nested component */
.blog-card {
display: flex;
flex-direction: column;
background: white;
border-radius: 1rem;
overflow: hidden;
transition: transform 0.3s;
&:hover {
transform: translateY(-4px);
.blog-card__image {
transform: scale(1.05);
}
}
&__image {
height: 200px;
background: linear-gradient(135deg, #667eea, #764ba2);
position: relative;
transition: transform 0.3s;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 2rem;
&::before {
content: '📝';
}
}
&__category {
position: absolute;
top: 1rem;
left: 1rem;
padding: 0.25rem 0.75rem;
background: rgba(255,255,255,0.9);
color: #764ba2;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 600;
}
&__content {
padding: 1.5rem;
flex: 1;
display: flex;
flex-direction: column;
}
&__title {
margin: 0 0 0.5rem;
color: #1f2937;
font-size: 1.25rem;
}
&__excerpt {
color: #6b7280;
line-height: 1.6;
flex: 1;
}
&__footer {
display: flex;
justify-content: space-between;
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
font-size: 0.875rem;
color: #9ca3af;
}
}
Hover over me for a surprise!
/* Nested animations and keyframes */
.animation-demo {
text-align: center;
padding: 3rem;
.loader {
display: inline-flex;
gap: 0.5rem;
margin-bottom: 2rem;
&__dot {
width: 12px;
height: 12px;
background: #2563eb;
border-radius: 50%;
animation: bounce 1.4s infinite ease-in-out both;
&:nth-child(1) {
animation-delay: -0.32s;
}
&:nth-child(2) {
animation-delay: -0.16s;
}
}
}
.animation-text {
font-size: 1.25rem;
color: #6b7280;
transition: all 0.3s;
display: inline-block;
&:hover {
color: #2563eb;
transform: scale(1.1) rotate(2deg);
animation: wiggle 0.5s ease-in-out;
}
}
}
/* Keyframes still go outside */
@keyframes bounce {
0%, 80%, 100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(-5deg); }
75% { transform: rotate(5deg); }
}
// SASS with variables and mixins
$primary: #2563eb;
$radius: 0.5rem;
@mixin button-style {
padding: 0.75rem 1.5rem;
border-radius: $radius;
transition: all 0.2s;
}
.form {
padding: 2rem;
&__group {
margin-bottom: 1.5rem;
label {
display: block;
margin-bottom: 0.5rem;
color: darken($primary, 20%);
}
input {
@include button-style;
border: 2px solid $primary;
&:focus {
outline: none;
border-color: lighten($primary, 10%);
}
}
}
}
/* CSS with custom properties */
:root {
--primary: #2563eb;
--primary-dark: #1d4ed8;
--primary-light: #60a5fa;
--radius: 0.5rem;
}
.form {
padding: 2rem;
&__group {
margin-bottom: 1.5rem;
label {
display: block;
margin-bottom: 0.5rem;
color: var(--primary-dark);
}
input {
/* Direct styles instead of mixin */
padding: 0.75rem 1.5rem;
border-radius: var(--radius);
transition: all 0.2s;
border: 2px solid var(--primary);
&:focus {
outline: none;
border-color: var(--primary-light);
}
}
}
}
/* CSS automatically adds & */
.parent {
.child { } /* = .parent .child */
& .child { } /* = .parent .child */
div { } /* = .parent div */
& div { } /* = .parent div */
}
/* Be careful with specificity */
.card {
/* This becomes .card.active */
&.active { }
/* This becomes .card .active */
.active { }
/* Multiple selectors */
h2, h3 {
margin: 0;
}
}
/* Media queries and supports */
.element {
width: 100%;
@media (min-width: 768px) {
width: 50%;
}
@supports (display: grid) {
display: grid;
}
}
Avoid nesting more than 3 levels deep. It makes CSS harder to read and increases specificity.
Combine BEM naming with nesting for the best of both worlds - clarity and convenience.
Modern DevTools show nested CSS properly, making debugging much easier than before.
Like a perfectly nested tea cosy, CSS nesting keeps everything warm and organised!