Solving the Misalignment Between Antd Table Headers and Content Cells
Recently, I encountered this styling issue, as shown in the image.
The image shows the problem.
How to Reproduce
Fixed table header with percentage width columns.
Investigation Steps
- Testing showed that on Mac with Chrome
Version 79.0.3945.130
, this issue doesn’t occur - On Windows 10 with Chrome
Version 79.0.3945.130
, the issue exists - On Windows 10 with Edge, there’s no issue
- Dragging the browser to an extended screen eliminates the issue
After comparing these scenarios, I found clues related to system, browser, different screens
, and based on this direction of investigation, I finally determined the cause.
Problem Explanation
PC screen display scaling settings
affect page layoutIf you change it to 100%, the page redraws and the problem disappears
On Windows, Chrome’s scroll pane takes up space by default, but on Mac it doesn’t. This is related to the operating system, not the browser version. Why doesn’t Mac have this issue? For example, in Chrome on Mac, the scroll pane is not calculated into the width, as if it’s on a different layer
The direct cause of misalignment is that
on Windows, when the device pixel ratio is not 1, the vertical scroll pane width of the table header is inconsistent with the scroll pane width of the table content, so the container width and table content width are inconsistent
. Since we set the column widths as percentages, this causes the two widths to be different, resulting in this problem. When we manually change the computer’s scaling to 100%, the scroll pane widths become consistent, so there’s no misalignment issue. But why, when the device pixel ratio is not 1, are the table header’s vertical scroll pane and the table content’s scroll pane widths inconsistent? I don’t know, maybe both are bugs.
Device Pixel Ratio
Now that we understand the problem, let’s explore the underlying cause: device pixel ratio.
When we modify the scaling, we’re actually changing the device pixel ratio
. If we set it to 150%, the device pixel ratio becomes 1.5, meaning that text that appears as 12px in CSS will physically display as 18px, although the CSS still shows 12px. This explains why sometimes web pages look like they have larger fonts than others.
We can also get the actual device pixel ratio
by executing a JavaScript script.
How to Solve
With the problem identified, the solution is either to control the scrollbar widths to be consistent or to make the scrollbar width not count in calculations. Here, I directly set the scrollbar to not occupy space:
.ant-table-small>.ant-table-content .ant-table-header{
overflow-y: overlay !important;
}
.ant-table-fixed-header>.ant-table-content>.ant-table-scroll>.ant-table-body{
overflow-y: overlay !important;
}
Note that overlay
is only supported in WebKit and Blink
kernel browsers
Behaves the same as auto, but with the scrollbars drawn on top of content instead of taking up space. Only supported in WebKit-based (e.g., Safari) and Blink-based (e.g., Chrome or Opera) browsers.
From MDN
Also, the reason for adding !important here is that the scroll styles added by the antd component are inline styles, so this is necessary to make our solution work.