← Back to Blog

When AI Can't Do CSS: The Comedy of Iterative UI Debugging

Paul Allington 14 October 2025 8 min read

I want to tell you about emoji reactions. Specifically, I want to tell you about the three days it took to get a row of tiny emoji icons to sit next to a date on a comment card. If that sounds like it should take about fifteen minutes, congratulations, you have a reasonable expectation of how software development works. Unfortunately, AI does not share your expectation.

This is a post about the gap between what AI is brilliant at and what it is genuinely, bafflingly terrible at. And that gap lives almost entirely in CSS.

The Emoji Reaction Disaster

The feature request was simple. Task Board has comments on tasks, like any project management tool. I wanted emoji reactions on those comments, like Slack. You hover over a comment, a little bar of emoji options appears, you click one, it shows beneath the comment. Straightforward. Every messaging app built since 2015 has this.

Claude built the reaction system itself in about twenty minutes. The data model, the API endpoints, the Blazor component logic, the SignalR real-time updates. All of it. Working. Clean code. No complaints.

Then we got to the bit where the emoji bar needed to actually appear in the right place on screen.

"The emoji bar is colliding with the dates."

First attempt at a fix moved the bar to a completely different part of the comment card. Not what I asked for.

"Not quite. The left-aligned comments are fine. Right-aligned - my comments - are not."

Task Board has a chat-style layout. Other people's comments align left, yours align right. The emoji bar worked perfectly on left-aligned comments and was an absolute catastrophe on right-aligned ones. Half the bar was hidden behind the edge of the card. The other half was overlapping the timestamp.

"What is so hard here? It's gone backwards!"

Each fix introduced a new problem. Move the bar up, it covers the comment text. Move it right, it clips off the card. Add a z-index fix, it appears behind the avatar. I watched Claude make twelve consecutive CSS changes, each one solving the previous problem and creating a new one, like a game of whack-a-mole played by someone who has never seen a mole.

"Jesus, it's now even worse!"

I am not a patient man when it comes to UI work. I know this about myself. But there is something uniquely maddening about watching an AI that can architect a distributed system with event sourcing and CQRS struggle to put a small box next to a date.

"Why can't it go next to the date, like where it was before? Every change you make seems to make it further away."

Eventually - and I mean eventually, after what felt like forty messages on this single element - it landed. The emoji bar appeared on hover, positioned correctly on both left and right-aligned comments, didn't overlap anything, and had a nice little fade-in animation. I typed the most relieved two words of the entire project: "Ok perfect. Commit, comment."

The Hover Target Problem

Except it wasn't perfect. Because the next day I noticed the hover target was wrong. You had to hover over a very specific three-pixel strip at the top of the comment to trigger the emoji bar. Anywhere else and nothing happened. So we went back in.

The fix for the hover target broke the positioning again. The fix for the positioning removed the hover effect entirely. For one glorious iteration, the emoji bar was visible at all times on every comment, which made the entire comment thread look like a slot machine.

Three more rounds of fixes. Then it worked. Actually worked. I tested it on mobile, on different screen sizes, on comments with long text and short text. All fine. The total time spent on emoji reaction positioning was longer than the time spent building the entire reaction system. That ratio tells you everything you need to know about AI and CSS.

The Modal That Loved the Left Side

Here's another one. Task Board has modals - popup dialogs for editing tasks, confirming deletions, that sort of thing. Standard stuff. At some point, every modal in the application started appearing aligned to the left side of the screen instead of centred.

I raised it. Claude fixed it. Next session, they were on the left again. Fixed it again. Next session, left again. This went on across three or four separate sessions, each time Claude confidently applying a fix that worked within the session and then apparently evaporated overnight.

The problem, it turned out, was that Claude was editing site.css - the compiled output - instead of site.less, the source file. Every time the LESS compiler ran, it overwrote the fix with the original broken styles. Claude didn't know this because it saw the CSS file, made a change that worked, and moved on. It had no concept of the build pipeline that would undo its work.

This is a pattern I've hit repeatedly. AI is excellent at fixing the immediate problem and terrible at understanding the system around the fix. It treats each file as an isolated unit. It doesn't think about build processes, compilation steps, or file generation pipelines unless you explicitly tell it to. And even then, it sometimes forgets mid-conversation.

The SweetAlert Saga

Task Board used SweetAlert for confirmation dialogs. You know the ones - "Are you sure you want to delete this?" with a big warning icon. They work fine. They're a well-known library. There is absolutely nothing wrong with SweetAlert.

Except that every time one popped up, it felt aggressive. A massive modal with a yellow triangle and bold text asking if you're really, truly, absolutely certain you want to archive a task. It felt like the application was shouting at you for daring to click a button.

"Swal still feels quite aggressive."

So we replaced SweetAlert with toast notifications for non-critical confirmations and slim, minimal modals for the ones that genuinely needed user confirmation. This was the right call. The UI feels calmer now. But the process of getting there involved Claude repeatedly reverting to SweetAlert-style patterns, producing toasts that appeared in the wrong corner, and at one point generating a toast notification that was larger than the modal it replaced.

Nobody writes about this part. The blog posts about AI development talk about building features in minutes, shipping at unprecedented speed. And that part is true. But they skip the hours spent arguing with an AI about whether a notification should appear in the top-right or bottom-right corner, and why it's currently appearing in the middle of the screen on top of the navigation bar.

Why AI Struggles With Visual Work

I've thought about this a lot, because it's not obvious why an AI that can reason about complex distributed systems falls apart when asked to position a div.

Here's my theory: CSS is not a logical system. It's a historical accident. It's a set of rules that interact in ways that are technically deterministic but practically unpredictable. Flexbox, grid, absolute positioning, relative positioning, z-index stacking contexts, margin collapsing, overflow behaviour - these all interact with each other, and the interaction depends on the specific combination of properties across the entire DOM tree.

When Claude writes backend code, it's working with explicit, predictable APIs. Call a method, get a result. When it writes CSS, it's working with a system where changing one property on one element can cascade through the entire layout in ways that are technically correct but visually wrong. And the AI has no way to see the visual result. It's writing CSS blind.

This is the fundamental problem: AI can reason about code, but it cannot see what code produces on screen. It can predict what CSS should do based on the specification. But CSS in the real world doesn't behave like the specification. It behaves like the specification as interpreted by a browser engine, modified by every other style rule in the cascade, influenced by the specific content and dimensions of every element in the layout. No amount of reasoning can substitute for actually looking at the screen.

The Screenshots That Changed Everything

I'll be honest with you - the breakthrough wasn't a better prompt or a cleverer approach. It was screenshots. When I started pasting screenshots of the broken UI into the conversation, the fixes got dramatically better. Claude could see what I was seeing. It could correlate its CSS changes with actual visual outcomes.

This sounds obvious in retrospect. But when you're in the flow of terminal-based development, your instinct is to describe the problem in words. "The emoji bar is overlapping the date" is less useful than a screenshot showing exactly how it's overlapping, by how many pixels, and what the surrounding layout looks like.

Even with screenshots, it's not perfect. But it cuts the iteration cycles roughly in half. Instead of twelve rounds of CSS whack-a-mole, you get six. Progress.

What I Actually Do Now

After months of this, I've developed a workflow for UI work that accounts for AI's CSS blindness.

For layout and structure, I let Claude do the first pass. It's good at setting up the HTML structure, choosing the right CSS approach (flex vs grid vs whatever), and getting the rough layout in place. This part usually works first or second try.

For fine-tuning - precise positioning, spacing, hover effects, responsive breakpoints - I often do the first adjustment myself, then have Claude review and refine. This is faster than the back-and-forth, because I can see the screen and make the change that's needed, then let Claude clean up the code and handle edge cases.

For anything involving overlapping elements, z-index, or position: absolute - I brace myself. These are where the real pain lives, and no amount of workflow optimisation fully eliminates the iterative suffering.

The irony isn't lost on me. I started using AI to avoid the tedious parts of development. CSS positioning is tedious. And it's the one thing AI makes more tedious, not less. The emoji bar works beautifully now though. Small victories.

Want to talk?

If you're on a similar AI journey or want to discuss what I've learned, get in touch.

Get In Touch

Ready To Get To Work?

I'm ready to get stuck in whenever you are...it all starts with an email

...oh, and tea!

paul@thecodeguy.co.uk