CSS常见问答
layout viewport、visual viewport 和 ideal viewport 有什么区别?
视口(Viewport)是移动 Web 开发中一个非常重要的概念,最早是由苹果公司在推出 iPhone 手机时发明的,其目的是为了让 iPhone 的小屏幕尽可能完整显示整个网页。通过设置视口,不管网页原始的分辨率尺寸有多大,都能将其缩小显示在手机浏览器上,这样保证网页在手机上看起来更像在桌面浏览器中的样子。在苹果公司引入视口的概念后,大多数的移动开发者也都认同了这个做法。
视口(Viewport)简单来说就是浏览器显示页面内容的屏幕区域。但在移动端浏览器涉及三个视口(Viewport)概念 :布局视口(Layout Viewport)、视觉视口(Visual Viewport)和理想视口(Ideal Viewport)。

布局视口(Layout Viewport)
布局视口(Layout Viewport)是指浏览器在其中绘制网页的视口,它涵盖页面上的所有元素。布局视口的宽度取决于文档内容,不会随用户在屏幕上缩放页面而变化。
获取布局视口:
document.documentElement.clientWidth | document.body.clientWidth
注意: 一般移动端浏览器都默认设置了布局视口的宽度。根据设备的不同,布局视口的默认宽度有可能是 768px、980px 或 1024px等,这个宽度并不适合在手机屏幕中展示。移动端浏览器之所以采用这样的默认设置,是为了解决早期的 PC 端页面在手机上显示的问题。
视觉视口(Visual Viewport)
视觉视口(Visual Viewport)是指是屏幕上实际可见的内容,不包括屏幕键盘、缩放区域之外的区域或任何其他不随页面尺寸缩放的屏幕控件。视觉视口区域的宽度是指浏览器窗口的宽度,而移动设备的浏览器窗口宽度一般也是整个屏幕的宽度。
获取视觉视口:
window.innerWidth
注意: 当用户缩放页面,或者屏幕键盘等用户界面功能开启/关闭时,视觉视口会变化,但布局视口不会改变。
理想视口(Ideal Viewport)
理想视口(Ideal Viewport)是指对设备来讲最理想的视口尺寸,即布局视口和屏幕宽度一致。采用理想视口的方式,可以使网页在移动端浏览器上获得最理想的浏览和阅读的宽度。
设置理想视口:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1, user-scalable=no">
获取理想视口:
window.screen.width
滚动条隐藏后,为什么无法再显示?
::-webkit-scrollbar 伪元素的层级结构
WebKit 滚动条由多个伪元素组成,形成一个层级结构:
::-webkit-scrollbar (整个滚动条容器)
├── ::-webkit-scrollbar-track (滚动条轨道/背景)
├── ::-webkit-scrollbar-thumb (滚动条滑块/可拖拽部分)
├── ::-webkit-scrollbar-button (滚动条按钮)
└── ::-webkit-scrollbar-corner (滚动条角落)
设置 display: none 后,无法通过改变 display 重新显示?
当在 ::-webkit-scrollbar 上设置 display: none 时:浏览器不会创建或渲染该伪元素及其子元素,也就是,伪元素从渲染树中被移除,而非仅设为不可见。
设置 display: none 之后,尝试设置 display: block、display: initial、display: revert 等都不会生效,因为:
浏览器已经不再处理该伪元素;
后续样式无法作用于一个不存在的元素。
这是一个已知的 WebKit 渲染行为,而不是 CSS 标准的预期行为。
为什么设置 thumb 和 track 样式后能显示?
当直接为 ::-webkit-scrollbar-thumb 和 ::-webkit-scrollbar-track 设置样式时,WebKit 会:
检测到子伪元素的样式声明;
重新评估滚动条的渲染状态;
即使父元素有 display: none,浏览器仍会根据子元素样式重新创建这些伪元素;
通过 !important 提高优先级,确保样式生效。
这是 WebKit 的一个渲染优化机制:当子伪元素有明确的样式声明时,浏览器会优先渲染它们,即使父元素被隐藏。
根据 MDN 文档和 WebKit 实现:::-webkit-scrollbar 伪元素是非标准的,主要用于 WebKit 浏览器。当为滚动条的子部分设置了样式,浏览器会认为你想要自定义滚动条,浏览器会重新渲染滚动条,即使之前被 display: none 隐藏。
正确的解决方案
/* 设置子伪元素的样式*/
&::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
/* 设置滚动条的高度*/
&::-webkit-scrollbar {
width: 0;
height: 0;
}
letter-spacing、word-spacing、white-space 有什么不同?
- letter-spacing: 用于控制字符之间的间距,包括英文字母、汉字以及空格等。
- word-spacing: 用于控制单词之间间距,换句话说,就是是增加空格的宽度。
- white-space: 用于设置如何处理元素中的 空白 (en-US),包括空格、换行符、制表符等。
letter-spacing 具有以下一些特性:
- 默认值是
normal,间距是按照当前字体的正常间距确定的。和 0 不同的是,用户代理根据此属性来确定文字的默认对齐方式; - 无论值多大或多小,第一行一定会保留至少一个字符;
- 一个很大的正或负的值会将字符变为不可读的:设置很大的正值,会使每个字符独占一行,类似垂直排列;设计很大的负值,除第一个字符,会使字符反向排列,除第一个字符,其他字符可能无法阅读;
- 支持小数值,但不支持百分比值。
white-space 取值如下:
- normal:连续的空白符会被合并,换行符会被当作空白符来处理;
- nowrap:连续的空白符会被合并,但文本内的换行无效;
- pre:连续的空白符会被保留,在遇到换行符或者 br元素时才会换行;
- pre-wrap:连续的空白符会被保留,在遇到换行符或者 br 元素,或者需要为了填充时才会换行;
- pre-line:连续的空白符会被合并,在遇到换行符或者 br 元素,或者需要为了填充时才会换行;
- break-spaces:与
pre-wrap的行为相同,除了:- 任何保留的空白序列总是占用空间,包括在行尾;
- 每个保留的空格字符后都存在换行机会,包括空格字符之间;
- 这样保留的空间占用空间而不会挂起,从而影响盒子的固有尺寸(最小内容大小和最大内容大小)。
min-width|max-width|width 的覆盖规则?
max-width比width小时,即使width使用了!important,仍是max-width生效;min-width和max-width冲突时,min-width生效。
此规则也适用于 height。