EYThe LogEmre Yakut
← all entries
Debugging

Sixteen cells vanished: the generic class name trap

The sequencer cells in my site’s groovebox went invisible one morning. No JavaScript error, nothing in the console. The cause was two CSS classes with the same name in two different files.

.beat experience.css · hikâye adımı .beat studio · sequencer hücresi ✕position:absolute; opacity:016 hücre görünmez oldu.story .beat { … }iki dosya, aynı sınıf adı, farklı niyet

The music section of my site has a real groovebox running in the browser: a 16-step sequencer, unlimited instruments, each channel with its own audio engine. It had been fine for months.

One morning I opened it — the sequencer cells were gone.

Audio played. The playhead moved. Channel headers were in place. Only the squares you click were missing.

I looked in the wrong place

My first reflex was JavaScript. The console was clean. I logged the function that builds the cells — it runs 16 times, creates the elements, appends them to the DOM. All correct.

I selected an element in devtools. It was there. It was not visible.

.st-cell.beat {
  position: absolute;
  opacity: 0;
  transform: translateY(20px);
}

I had not written that rule. Or rather I had — for something else, in another file.

Two files, one word

The professional section of the site has a narrative sequence: story steps that appear as the page scrolls. Their class is .beat — as in the beat of a story. They start invisible and fade in, so they sit at zero opacity.

The sequencer cells are also .beat — in the musical sense. Completely different worlds, exactly the same word.

Both stylesheets load on the same page. CSS has no namespaces. The two merged into one rule set, and the story rule won because it was more specific.

the worst part of this bug

Nothing reports an error. CSS saw nothing invalid. JavaScript did nothing. The browser did exactly what it was told.

The system produced the wrong result by working perfectly — and that is the hardest kind of bug to find.

The fix is one character

/* before */
.beat { position: absolute; opacity: 0; … }

/* after */
.story .beat { position: absolute; opacity: 0; … }

The story steps now only take that rule inside their own scope. The cells came back.

The real lesson is naming

This is not a CSS bug. It is a naming bug.

“beat” was the right word in both contexts. That is exactly the problem: right words are shared. item, card, row, panel, active, step, cell — every one of them will be the right word somewhere else one day.

The rule now: never write a generic name unscoped. When I see a single-word, context-free class name I fix it, even if nothing has broken yet.

The same bug wearing other clothes

  • Global JavaScript variables — two scripts using the same name: whichever loads last wins, with no error.
  • Environment variables — a child process behaves differently because of a variable inherited from its parent; the only difference is where you launched it from. This happened to me exactly in the voice assistant.
  • Database column names — joining two tables, one identically named column silently shadows the other.

What they share: the collision is resolved as a rule, not an error. And the rule lets the side you did not expect win.

Every collision resolved silently is a bug that will surface silently.

Debugging