Button group dividers have inconsistent thickness or shift horizontally with fractional zoom or DPI scaling
Prerequisites
- [x] I have searched for duplicate or closed issues
- [x] I have validated any HTML to avoid common problems
- [x] I have read the contributing guidelines
Describe the issue
The Bootstrap button component is implemented with overlapping adjacent borders. At fractional zoom levels, or in environments with DPI scaling, these may be rounded differently. This causes both borders to be displayed simultaneously, or for the dividing border to 'shift' horizontally when the active button changes.
Reduced test cases
Effect 1: Double-divider
- Navigate to the Button Group demonstration in the Bootstrap docs
- Adopt a fractional zoom level, or other platform-specific DPI scaling
- At certain zoom levels, the divider between neighbouring buttons is shown doubled:
Effect 2: Horizontal shift
If the test case is modified to add backgrounds to the buttons (shown here crudely), then the divider shifts horizontally depending on which is selected:
<div class="btn-group" role="group" aria-label="Basic outlined example">
<button type="button" class="btn btn-outline-primary bg-white text-primary">Left</button>
<button type="button" class="btn btn-outline-primary bg-white text-primary">Middle</button>
<button type="button" class="btn btn-outline-primary bg-white text-primary">Right</button>
</div>
What operating system(s) are you seeing the problem on?
Windows
What browser(s) are you seeing the problem on?
Chrome
What version of Bootstrap are you using?
v5.3
(hello again! I've updated the issue to include a reproduction and animation showcasing the horizontal shift problem too - thanks for your attention)
This appears to originate at the layout stage as opposed to the rasterisation stage, as the border is adopting a fractional value while the negative margin applied to overlap the adjacent borders does not:
With box-sizing: border-box, this is sufficient to offset the element relative to its neighbour.
(for example, manually setting margin-left to -0.667 instead stops reproducing the issue at that exact zoom level)
The fix for #28940 looks relevant here.