It would be an a11y fail, if it wouldn't be
visibility: hidden. For two simple reasons.
- If you tab through the page you can reach the input (and all other focusable content in this area) without seeing it. (And you might re-add content jumps.)
- You have introduced a control that shows/hides another content area, but for screenreader users this area is not hidden and therefore the control wouldn't make sense.
visibility: hidden to hide it.
Yes, this is a workaround, but it doesn't really help in real world situations. In those situations you have a generalized JS code and some CSS code. The JS should not know whether there is a CSS
transition or what
transition is used. The CSS dev might also want to use multiple effects and so on. Even your example doesn't work properly, it focuses the input on every
transitionend not only on showing. If another transition is in place you get multiple events, which
transitionend is the right to use? What happens if no CSS transition is used and instead another JS script hooks into a triggered event to provide a JS animation and so on.
And here is where the pain starts. You need to write a quite amount of code, that re-checks the visual state of the element over and over again to decide, when it is save to focus it.
If you look into this project: https://github.com/medialize/ally.js. You will see some code that does just that, checking as soon as an element can be focused without creating a scroll problem and so on. It's quite amount of code to realize this simple a11y focus management task.
At the end of this you will realize, that you can't focus an
input async on most mobile browser, you need to focus it inside of a trusted