4 min read

Debugging CSS with Claude Code

Debugging CSS with Claude Code
Photo by Nick Karvounis / Unsplash

tldr; claude mcp add playwright npx @playwright/mcp@latest

I got a new request for my hardcover-embed service: to be able to embed reviews!

Jeff Sexton had been embedding the Goodreads review widget on his website and wanted to replace it with data from Hardcover.

(btw, Jeff is awesome and has great reviews and recommendations! If you're on the Hardcover Discord, he's always recommending books to folks in #books. Hit him up there if you're looking for your next read!)

So I quickly built the backend and vibe coded the frontend until it looked like this:

Jeff embedded it into his website, and it looked weird; the CSS was all off.

The images had no left or right padding, and there was a lot of whitespace underneath. I knew that the site's CSS was overriding/interfering with the widget CSS, but I didn't know how to fix it.

I could feed Claude screenshots manually, but as I wrote in the previous post Thoughts on building with AI, a quick feedback loop is important for agents. I decided to try to make Claude open the browser and iterate by itself. A quick Google search led me to this: Making Claude Code into an autonomous frontend dev.

Connecting the MCP server

All I had to do was:

$ claude mcp add playwright npx @playwright/mcp@latest

I then asked Claude to update Claude.md with instructions to use the Playwright MCP for frontend debugging and it added these lines:

## Frontend Testing and Debugging


### Using Playwright MCP Server

When troubleshooting HTML, CSS, and JavaScript issues in the application frontend, use the Playwright MCP server tools:

1. **Accessing frontend pages**:
   - Navigate to `http://localhost:8080/` or the configured port
   - Use `mcp__playwright__browser_navigate` to open pages
   - Use `mcp__playwright__browser_snapshot` to capture the current page state
   - Use `mcp__playwright__browser_console_messages` to view JavaScript console output

2. **Common debugging workflows**:
   - **HTML/CSS issues**: Use `mcp__playwright__browser_snapshot` to inspect the DOM structure
   - **JavaScript errors**: Check `mcp__playwright__browser_console_messages` for error logs
   - **Interactive debugging**: Use `mcp__playwright__browser_evaluate` to run JavaScript in the page context
   - **Network issues**: Monitor API calls with `mcp__playwright__browser_network_requests`

Quick feedback loop

Now that I had this setup, I downloaded the HTML for Jeff's homepage and changed the embedding script to use http://localhost:8080/static/review-widget.js instead of https:hardcoverembed.gouthamve.dev/static/review-widget.js. Now I can clearly reproduce the issue at http://localhost:8080/bookanon.html and any changes I made were immediately visible.

Doesn't work for big pages

I now explained the issue to Claude and it went to work! And then quickly ran into a wall:

⏺ Now let me navigate to the page with the review widget:

⏺ playwright - Navigate to a URL (MCP)(url: "http://localhost:8080/bookanon.html")
  ⎿  Error: MCP tool "browser_navigate" response (26052 tokens) exceeds maximum allowed tokens (25000). Please use pagination, filtering, or limit parameters to reduce the response
     size.

⏺ Let me check the review widget JavaScript to understand the structure:

⏺ Read(web/static/review-widget.js)
  ⎿  Read 100 lines (ctrl+r to expand)

⏺ Let me see more of the CSS:

⏺ Read(web/static/review-widget.js)
  ⎿  Read 100 lines (ctrl+r to expand)

⏺ Now I see the issue. Looking at the CSS, I can see that .hrw-book-cover has styles but doesn't have any left padding/margin. Let me check if this is the element that needs fixing.
  Let me wait for the page to load properly and check the widget:

⏺ playwright - Wait for (MCP)(time: 2)
  ⎿  Error: MCP tool "browser_wait_for" response (26036 tokens) exceeds maximum allowed tokens (25000). Please use pagination, filtering, or limit parameters to reduce the response
     size.
  ⎿  Interrupted by user

It was using too many tokens and Microsoft had an interesting response to the issue:

We believe that the tokens will get cheaper faster than we can elaborate a meaningful pagination solution.

Anyways, I decided to reduce the size of the page by cutting out everything that wasn't required.

Now Claude could use Playwright, see the issues, and iterate quickly, fixing them.

After about 30 minutes of prompting, I now have a clean interface:

Conclusion

You can compare the changes here. Clauded added a bunch of !important tags to the CSS so it won't be overridden. I honestly don't know if that's a good idea. I'll soon find a frontend person to help me review the current state of the code, but until then I'm happy with this.

I'll also push for Hardcover to provide this functionality natively, so I and my poor man's CSS don't need to live for long. But overall, I'm pleased that I gained a new user 😄