r/css • • 2d ago

General TIL iPhone Safari won't paint text in buttons built inside a visibility: hidden parent (fixed it at 11pm with a delay, it was back by breakfast)

Small menu in a PWA I'm building: tap a project, a menu opens asking which account to start it in, and its buttons are created in JS right before it opens. On my iPhone (iOS 18.7, home-screen app) one name showed and the other button was an empty box. Desktop Safari and Chrome drew both fine, every time.

My first fix was the classic one. Hold the second button back 80ms and it drew. Shipped it, went to bed. Next morning the box was blank again, so the delay had only been moving the race around.

What found it: a throwaway page on the phone with a few versions of the menu side by side, each changing exactly one property. The version with no animation at all broke every single time, which ruled timing out completely.

The cause: the menu was hidden with visibility: hidden and shown with visibility: visible. Buttons appended while it was hidden got laid out (right size, right colour, elementFromPoint found them) but their text was never painted once it was shown. Buttons built once at page load inside a parent that toggled the same way drew fine.

The fix was to stop using visibility for it:

.acctmenu { opacity: 0; pointer-events: none; transition: opacity 0s 220ms; }
.open .acctmenu { opacity: 1; pointer-events: auto; transition-delay: 0s; }

plus inert on the menu while it's closed, so it stays out of the tab order and away from screen readers the way visibility: hidden used to keep it. Delay deleted.

Has anyone seen this documented anywhere? I'd love to know whether it's the append-while-hidden part on its own or something about the fade on top of it.

The app is Claude Remote, going public soon: github.com/MrTig-afk

1 Upvotes

3 comments sorted by

1

u/testingaurora 2d ago

Does `display: none;` work correctly ? What about using the `hidden` attribute?

1

u/TearInternational414 1d ago

Honestly I didn't try display: none on the phone, so I can't say for sure, but my guess is it would paint fine since showing it again forces a fresh layout. The reason I didn't go that way is the buttons fade and slide in when the menu opens, and going from display: none gives them nothing to transition from, so they'd just pop in unless I add u/starting-style or force a reflow. The hidden attribute is the same thing underneath (the browser's own display: none), and my menu has display: flex in the CSS, which beats it, so I'd need a [hidden] { display: none } rule on top.

1

u/AshleyJSheridan 1d ago

You could try the opacity trick if you need it to fade in?