我们终于学会了如何让 div 居中,结果浏览器又加了侧边栏。
We finally learned to center a div, then browsers added sidebars

原始链接: https://seg6.space/posts/center-div/

使用 CSS Grid (`place-items: center`) 来居中元素虽然简单,但它会将内容锚定在可视视口,而非整个浏览器窗口。当侧边栏或开发者工具等元素出现时,“完美居中”的内容在视觉上会显得偏移。 为了解决这个问题,作者计算了相对于物理浏览器窗口居中元素所需的偏移量。虽然 `window.innerWidth` 和 `window.outerWidth` 提供了额外的总空间,但它们无法揭示这些空间在屏幕上是如何分布的。 突破点在于利用指针事件(`screenX` 和 `clientX`)来映射网页在浏览器窗口中的位置。虽然 Firefox 直接提供了此数据,但 Chromium 需要在用户与页面交互时进行修正更新。作者最终将此逻辑封装为一个名为“center, actually”的工具,该工具可以自动检测并居中那些用户无法直接控制代码页面上的元素。

这篇 Hacker News 帖子讨论了网页开发中一个长期存在的挑战:如何将 `div` 元素居中。讨论由一篇指向 `seg6.space` 的文章引发。 用户们探讨了现代 CSS 居中技术的细节。虽然有些人提到了诸如 `margin: 0 auto` 这样的传统方法,但其他人指出这些方法通常仅能处理水平对齐。评论者重点介绍了 `scrollbar-gutter` 属性,将其作为解决滚动条引起布局偏移的一种现代方案。 对话还涉及了围绕居中技术的局限性及审美争议。参与者指出,浏览器刻意限制网站获取其相对于物理屏幕的位置,使得“基于窗口”的居中既不可能实现,也可能并非理想方案。总的来说,这场讨论反映了 CSS 元素居中在开发圈中长期存在的“梗”的地位,既认可了语言本身的技术演进,也承认了开发者在追求完美对齐时所面临的持续困扰。
相关文章

原文

Centering a div used to require this little ritual:

.thing {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

These days, it is almost disappointingly easy:

body {
  display: grid;
  min-height: 100dvh;
  place-items: center;
}

I used that for the .site div you’re reading. It looked centered until I opened it in a browser with the sidebar visible.

The .site div was still perfectly centered, just inside the wrong rectangle. I figured the fix would be simple enough: JavaScript knows the width of both the webview and the browser window.

window.innerWidth // the webview
window.outerWidth // the whole browser window
const browserChrome = window.outerWidth - window.innerWidth;

With the sidebar on the left, I could move .site back by half of that difference:

const shift = -browserChrome / 2;
.site {
  translate: var(--window-center-shift, 0px);
}

That worked, right up until I opened DevTools.

Mine is docked on the right, so the width difference now included browser UI on both sides. It gave me the total, but no way to tell how that total was split.

What finally gave me the missing coordinate was the pointer. A trusted pointer event knows where it is on the screen and where it is inside the webview, which is enough to locate the webview inside the window:

const viewportLeft = event.screenX - event.clientX * scale;
const viewportRight = viewportLeft + innerWidth * scale;

const left = viewportLeft - window.screenX;
const right = window.screenX + outerWidth - viewportRight;
const shift = (right - left) / (2 * scale);

Firefox exposes the same viewport position directly. Chromium does not, so this site starts with the left-sidebar estimate and corrects it as soon as the pointer enters the page.

I wanted to try the same fix on pages I do not control, so I made center, actually. It tries to find the centered element itself; if it guesses wrong, I can pick one. The demo is the simplest place to see the difference.

联系我们 contact @ memedata.com