DEV Community

Mohamed Idris
Mohamed Idris

Posted on

Why BEM Nesting Breaks in Tailwind v4

So today I spent sometime debugging why some CSS styles weren't applying. Turns out, Tailwind v4 quietly broke something on was working Tailwind v3.

What happened

I had CSS like this:

.dropdown {
  background: white;

  &--open {
    background: blue;
  }

  &__icon {
    width: 16px;
  }
}
Enter fullscreen mode Exit fullscreen mode

In Tailwind v3, this worked perfectly. It would compile to:

.dropdown { background: white; }
.dropdown--open { background: blue; }
.dropdown__icon { width: 16px; }
Enter fullscreen mode Exit fullscreen mode

But in Tailwind v4? Nothing. No error. No warning. It just silently does nothing.

Meanwhile, this still works fine:

.dropdown {
  &:hover { background: gray; }
  & .child { color: red; }
}
Enter fullscreen mode Exit fullscreen mode

Wait, what? &:hover works but &--open doesn't? Why??

The reason

It comes down to native CSS nesting vs SASS nesting.

Native CSS (what browsers understand) supports & only for:

  • Pseudo-classes: &:hover, &:focus, &::before
  • Combinators: & .child, & > .child, & + .sibling
  • Chaining: &.another-class

SASS added an extra feature on top: using & to concatenate strings. So &--open inside .dropdown would glue them together into .dropdown--open. That's not real CSS — that's a SASS trick.

Tailwind v3 used postcss-nested under the hood, which copied the SASS behavior. So BEM nesting worked.

Tailwind v4 switched to Lightning CSS, which follows the real CSS nesting spec. No more string concatenation. BEM nesting just silently fails.

The fix

Simple. Just write the full class name:

/* Before (broken in v4) */
.dropdown {
  &--open {
    background: blue;
  }
  &__icon {
    width: 16px;
  }
}

/* After (works everywhere) */
.dropdown--open {
  background: blue;
}

.dropdown__icon {
  width: 16px;
}
Enter fullscreen mode Exit fullscreen mode

You can still use nesting for the stuff native CSS supports:

.dropdown {
  &:hover {
    background: gray;
  }

  & .dropdown__icon {
    width: 16px;
  }
}
Enter fullscreen mode Exit fullscreen mode

TL;DR

Syntax Tailwind v3 Tailwind v4 Why
&:hover works works Native CSS nesting
& .child works works Native CSS nesting
&--modifier works broken SASS feature, not native CSS
&__element works broken SASS feature, not native CSS

Tailwind v4 uses Lightning CSS which follows the native CSS spec. BEM string concatenation with & is a SASS-only feature that native CSS doesn't support.

If you're migrating to Tailwind v4 and styles are silently disappearing, check for BEM nesting first.

Related: Tailwind CSS GitHub Issue #18522

Top comments (0)