I’m building a UI that shows/hides certain elements based on what “state” the user is in. The user can transition between states by clicking around the screen.
My HTML renders every element that could be shown. Then Stimulus kicks in and on connect() adds the hidden class to elements that shouldn’t be shown.
This works great on Safari. However, in Chrome there is a noticeable flicker or “popping” of elements when the page loads.
Is this the right approach? If not, is there a recommended way of handling this?
Any idea as to why this would happen in one browser and not the other?
Edit: Here’s an example project in Glitch that shows the flicker. Open the project’s live page in Chrome and refresh a few times and you will see the flicker. Yet no matter how many times you refresh in Safari it won’t occur.
It sounds like your JS bundle loading strategy is non-render-blocking (good). This means you will see a flicker between render and your JS kicking in.
You might consider a different approach that by default hides all of these elements with opacity or a visually-hidden class using CSS. Then when your JS bundle loads after render, you can reveal the elements that should by default be seen using your code in connect.
It’s partly a timing issue with the <script> loading asynchronously:
The controller won’t run / elements won’t be hidden until the JavaScript file loads and processes.
You could solve that by loading the <script> synchronously (Relic Reminder), but that’s not ideal for overall performance. I’d go with a CSS-first approach.
I ended up adding initial CSS classes to show/hide the elements on the page before the JavaScript kicks in. Effectively, moving most of my logic from the client to the server. Now only a few show/hide methods are needed in the controller and all seems to be well.