Tweak `.visually-hidden` to use `display:inline-block` instead of absolute positioning
Description
Use display:inline-block instead of position:absolute for .visually-hidden
Motivation & Context
While tried and tested, the regular .visually-hidden styles have unintended consequences in certain scenarios, such as inside responsive tables - see https://github.com/twbs/bootstrap/issues/31885
As the position:absolute is used essentially to force the element to accept explicit width/height/clip even when it's currently inline, this new approach should have the same end result, but without causing any more accidental spacing.
See the redone example from #31885 (replacing the old .sr-only with .visually-hidden), with overrides that mimic the end result of this PR: https://codepen.io/team/bootstrap/pen/azzxqBZ (removing the overrides in the Pen's CSS shows the current broken behaviour: make the viewport/browser window narrow, and notice how - just like in the original #31885 issue - the visually hidden content in the last cell of the first row leads to whitespace to the right of the table that then results in a page-level horizontal scrollbar)
Suggest extensive testing of this, to make sure the change doesn't now cause other unintended consequences elsewhere. Suggest also testing on devices that are notoriously flaky ... like "does it work as expected on iOS/Safari with/without VoiceOver running".
Marking as a breaking change because it has the potential to break things if an author did heavily rely on the old styles for some reason.
Type of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Refactoring (non-breaking change)
- [x] Breaking change (fix or feature that would change existing functionality)
Checklist
- [x] I have read the contributing guidelines
- [x] My code follows the code style of the project (using
npm run lint) - [ ] My change introduces changes to the documentation
- [ ] I have updated the documentation accordingly
- [ ] I have added tests to cover my changes
- [ ] All new and existing tests passed
Live previews
Related issues
https://github.com/twbs/bootstrap/issues/31885
I think this needs various test cases for when a visually hidden element is a flex or grid child, for example.
Absolute position ensures context and flow would not be impacted, but I think switching to display could lead to layout changes.
I'll try to pack some cases.
thanks @ffoodd that'd be super helpful ... hoping that there won't be any unforeseen side effects here...
I’m currently working on a CodePen aggregating every reduced test cases I can think of.
Seeking around old issues, I have a first thing to note: removing position: absolute will prevent clip from being applied.
But, FWIW, I also ran into #24906 which removed clip-path for paint issues on Chromium: playing with its reduced test case, I can confirm that this is not an issue anymore (tested on Edge / Ubuntu). So regarding clipping, I think we're safe if we (finally) drop clip and use clip-path: inset(50%) instead.
So, here's the reduced test cases collection on CodePen, using current 5.38 release and this PR's build.
As I thought, there're edge cases when used as grid or flex children (checked on Firefox). IMHO this should not exist, but as it was possible until this change, we can fear that someone used it…
At least, we now have a pen to play with!
thanks for keeping the flame alive @ffoodd .. i know i've really been dropping off from my duties here, but ... life
So, after a few minutes digging around:
- switching to
clip-pathdoes not seem buggy anymore :tada: - applying
flex: nonealongside other resets prevents flex layout from breaking; - applying
grid-area: nonesomewhat prevents grid layout from breaking.
I'm not sure that's all to be done, but that a first step :)
And FWIW, using inline-block display in lieu of absolute positioning fixes every unwanted scrollbars cases in Chromium.
I rebased the branch and pushed some more improvements:
- Switch to
clip-path: the de-facto standard sinceclipis deprecated. Previous performance issues in Chromium seems to have been fixed. - Add
flex: noneas another reset to protect against layout issues when.visually-hiddenis used in a flex container. - Add
contain: strictas an overall rule, since anything that could be in a.visually-hiddenelement should not have any impact regarding layout, paint nor content outside of its containment.
The only edge case I couldn't deal with is when .visually-hidden is a grid child. But I wonder who on earth could set a visually hidden element on a grid?
If I'm missing any case, feel free to fork the CodePen mentioned above to add your case.