Skip to content

CSS 单位系统:尺寸的语言艺术

单位的本质

在 CSS 中,几乎所有的尺寸和距离都需要单位。选择正确的单位不仅影响页面的视觉效果,更决定了网站的响应式能力和可维护性。

CSS 单位可以分为两大类:

  • 绝对单位:固定不变的物理尺寸
  • 相对单位:相对于其他元素或上下文的尺寸

理解每种单位的特性和适用场景,是掌握 CSS 布局的关键。

绝对单位

绝对单位的大小是固定的,不会随上下文改变。

px(像素)

像素是最常用的绝对单位,代表屏幕上的一个物理像素点:

css
.box {
  width: 200px;
  height: 100px;
  font-size: 16px;
  border: 1px solid #ddd;
}

特点

  • 精确控制尺寸
  • 在不同设备上保持相同的视觉大小(在相同的设备像素比下)
  • 不受父元素影响

适用场景

  • 边框宽度:border: 1px solid #ddd
  • 阴影偏移:box-shadow: 2px 4px 8px rgba(0,0,0,0.1)
  • 小图标尺寸:width: 24px; height: 24px
  • 媒体查询断点:@media (min-width: 768px)

注意事项

css
/* 现代设备的像素密度问题 */
/* iPhone 的物理分辨率是 750x1334,但 CSS 像素是 375x667 */
/* 这是因为设备像素比(Device Pixel Ratio, DPR)为 2 */

.icon {
  width: 20px; /* 在高DPI屏幕上实际占用 40 个物理像素 */
}

/* 移动端适配 */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
  .retina-image {
    background-image: url("[email protected]");
    background-size: 100px 100px; /* 原始尺寸的一半 */
  }
}

其他绝对单位

这些单位主要用于打印样式:

css
/* 很少在屏幕显示中使用 */
.print-content {
  width: 21cm; /* 厘米 */
  height: 29.7cm; /* A4 纸的尺寸 */
  margin: 2.54cm; /* 1英寸 = 2.54cm */
  font-size: 12pt; /* 点,1pt = 1/72英寸 */
  line-height: 1pc; /* 派卡,1pc = 12pt */
}

@media print {
  body {
    width: 210mm; /* 毫米 */
    margin: 1in; /* 英寸 */
  }

  h1 {
    font-size: 18pt; /* 打印时使用 pt 更精确 */
  }
}

相对单位

相对单位的大小取决于其他元素或上下文,这使得它们特别适合响应式设计。

em - 相对于父元素

em 相对于当前元素的 font-size,如果当前元素未设置 font-size,则相对于父元素的 font-size

css
/* 基础示例 */
.parent {
  font-size: 16px;
}

.child {
  font-size: 1.5em; /* 16px × 1.5 = 24px */
  padding: 1em; /* 24px × 1 = 24px(相对于自己的font-size) */
  margin: 0.5em; /* 24px × 0.5 = 12px */
}

/* em 的复合效应 */
.level-1 {
  font-size: 1.2em; /* 假设父元素是 16px,这里是 19.2px */
}

.level-1 .level-2 {
  font-size: 1.2em; /* 19.2px × 1.2 = 23.04px */
}

.level-1 .level-2 .level-3 {
  font-size: 1.2em; /* 23.04px × 1.2 = 27.65px */
}
/* 嵌套会导致字体越来越大或越来越小 */

实际应用

css
/* 创建模块化的组件 */
.button {
  font-size: 16px; /* 基准大小 */
  padding: 0.5em 1em; /* 8px 16px */
  border-radius: 0.25em; /* 4px */
  margin: 0.5em; /* 8px */
}

.button-large {
  font-size: 20px; /* 改变基准 */
  /* padding 自动变为 10px 20px */
  /* border-radius 自动变为 5px */
  /* margin 自动变为 10px */
}

.button-small {
  font-size: 12px;
  /* 所有尺寸按比例缩小 */
}

/* 响应式排版 */
h1 {
  font-size: 2em; /* 相对于父元素 */
  margin-bottom: 0.5em; /* 保持比例 */
  line-height: 1.2em; /* 相对于自己 */
}

rem - 相对于根元素

rem(root em)相对于根元素(<html>)的 font-size,避免了 em 的复合效应:

css
/* 设置根元素基准 */
html {
  font-size: 16px; /* 1rem = 16px */
}

.container {
  padding: 1rem; /* 16px */
  margin-bottom: 2rem; /* 32px */
}

.title {
  font-size: 2rem; /* 32px */
  margin-bottom: 1rem; /* 16px */
}

.nested .deeply .buried .text {
  font-size: 1rem; /* 始终是 16px,不受嵌套影响 */
}

响应式设计

css
/* 基于根字体大小的响应式系统 */
html {
  font-size: 16px;
}

@media (max-width: 768px) {
  html {
    font-size: 14px; /* 所有使用 rem 的元素自动等比缩小 */
  }
}

@media (max-width: 480px) {
  html {
    font-size: 12px;
  }
}

/* 所有尺寸都会自动适配 */
.card {
  padding: 1.5rem; /* 平板: 21px, 手机: 18px */
  border-radius: 0.5rem; /* 平板: 7px, 手机: 6px */
}

.heading {
  font-size: 2.5rem; /* 平板: 35px, 手机: 30px */
  margin-bottom: 1rem; /* 平板: 14px, 手机: 12px */
}

使用技巧:62.5% 基准

css
/* 方便计算的技巧 */
html {
  font-size: 62.5%; /* 16px × 62.5% = 10px */
}

body {
  font-size: 1.6rem; /* 16px */
}

.text-small {
  font-size: 1.2rem; /* 12px */
}

.text-large {
  font-size: 2rem; /* 20px */
}

.heading {
  font-size: 3.2rem; /* 32px */
}

% - 百分比

百分比单位相对于父元素的对应属性值:

css
/* 宽度百分比 */
.container {
  width: 100%; /* 父元素宽度的 100% */
  max-width: 1200px; /* 限制最大宽度 */
}

.column {
  width: 50%; /* 父元素宽度的 50% */
  padding: 2%; /* 父元素宽度的 2% */
}

/* 高度百分比 - 需要父元素有明确高度 */
.parent {
  height: 500px; /* 必须设置高度 */
}

.child {
  height: 80%; /* 500px × 80% = 400px */
}

/* padding 和 margin 的百分比都相对于父元素的宽度 */
.box {
  width: 100%;
  padding-bottom: 56.25%; /* 16:9 宽高比 (9/16 = 0.5625) */
}

/* position 定位中的百分比 */
.centered {
  position: absolute;
  top: 50%; /* 相对于父元素高度 */
  left: 50%; /* 相对于父元素宽度 */
  transform: translate(-50%, -50%); /* 相对于自身尺寸 */
}

/* transform 中的百分比相对于元素自身 */
.slide-in {
  transform: translateX(-100%); /* 向左移动自身宽度 */
}

/* background-position 的百分比 */
.banner {
  background-position: 50% 50%; /* 水平和垂直居中 */
}

视口单位

视口单位相对于浏览器视口(viewport)的尺寸。

vw 和 vh

css
/* vw: 1vw = 视口宽度的 1% */
/* vh: 1vh = 视口高度的 1% */

/* 全屏区块 */
.hero {
  width: 100vw; /* 视口宽度的 100% */
  height: 100vh; /* 视口高度的 100% */
}

/* 响应式文字 */
.title {
  font-size: 5vw; /* 在 1200px 宽的屏幕上是 60px */
  /* 在 375px 宽的手机上是 18.75px */
}

/* 限制范围 */
.responsive-text {
  font-size: clamp(16px, 4vw, 48px);
  /* 最小 16px,理想 4vw,最大 48px */
}

/* 固定宽高比的容器 */
.video-container {
  width: 80vw;
  height: 45vw; /* 16:9 比例 (80 × 9/16 = 45) */
  max-width: 1200px;
  max-height: 675px;
}

vmin 和 vmax

css
/* vmin: 视口宽度和高度中较小的值的 1% */
/* vmax: 视口宽度和高度中较大的值的 1% */

/* 在任何方向都能看到的元素 */
.square {
  width: 50vmin; /* 始终不超过视口的一半 */
  height: 50vmin;
}

/* 响应式图标 */
.icon {
  font-size: 10vmin; /* 横屏和竖屏都保持合适大小 */
}

/* 全屏背景 */
.background {
  width: 100vmax;
  height: 100vmax;
}

lvh, svh, dvh - 移动端视口单位

CSS 新增的视口单位,解决移动端地址栏问题:

css
/* lvh (Large Viewport Height): 不包含地址栏的高度 */
/* svh (Small Viewport Height): 包含地址栏的高度 */
/* dvh (Dynamic Viewport Height): 动态高度 */

.mobile-hero {
  height: 100dvh; /* 动态适应地址栏的显示/隐藏 */
}

.fixed-header {
  height: 100svh; /* 使用最小视口高度 */
}

.content {
  min-height: 100lvh; /* 使用最大视口高度 */
}

角度单位

用于 transformgradient

css
.rotated {
  transform: rotate(45deg); /* 度 (0-360) */
  transform: rotate(0.785rad); /* 弧度 */
  transform: rotate(50grad); /* 百分度 (0-400) */
  transform: rotate(0.125turn); /* 圈数 */
}

.gradient {
  background: linear-gradient(135deg, blue, red);
}

时间单位

用于动画和过渡:

css
.transition {
  transition: all 0.3s ease; /* 秒 */
  transition: all 300ms ease; /* 毫秒 */
}

.animation {
  animation: slide 2s ease-in-out; /* 2秒 */
  animation-delay: 500ms; /* 延迟 500毫秒 */
}

calc() 函数

混合使用不同单位:

css
/* 基本计算 */
.container {
  width: calc(100% - 80px); /* 百分比减去固定值 */
  padding: calc(2rem + 10px); /* rem 加上 px */
  margin: calc(5vw - 20px); /* 视口单位减 px */
}

/* 复杂布局 */
.sidebar {
  width: 300px;
}

.main-content {
  width: calc(100% - 300px); /* 剩余宽度 */
}

/* 响应式间距 */
.grid {
  grid-template-columns: repeat(3, calc((100% - 40px) / 3));
  gap: 20px;
}

/* 动态字体大小 */
.fluid-text {
  font-size: calc(16px + 1vw); /* 基础大小 + 视口缩放 */
}

/* 嵌套 calc */
.complex {
  width: calc(100% - calc(20px * 2));
}

实战技巧

响应式排版系统

css
:root {
  --base-size: 16px;
  --scale-ratio: 1.25;

  --text-xs: calc(var(--base-size) / var(--scale-ratio) / var(--scale-ratio));
  --text-sm: calc(var(--base-size) / var(--scale-ratio));
  --text-base: var(--base-size);
  --text-lg: calc(var(--base-size) * var(--scale-ratio));
  --text-xl: calc(var(--base-size) * var(--scale-ratio) * var(--scale-ratio));
  --text-2xl: calc(
    var(--base-size) * var(--scale-ratio) * var(--scale-ratio) * var(--scale-ratio)
  );
}

.text-xs {
  font-size: var(--text-xs);
} /* ~10px */
.text-sm {
  font-size: var(--text-sm);
} /* ~13px */
.text-base {
  font-size: var(--text-base);
} /* 16px */
.text-lg {
  font-size: var(--text-lg);
} /* ~20px */
.text-xl {
  font-size: var(--text-xl);
} /* ~25px */
.text-2xl {
  font-size: var(--text-2xl);
} /* ~31px */

完美的正方形

css
/* 使用 padding-bottom 创建正方形 */
.square {
  width: 100%;
  padding-bottom: 100%; /* 相对于宽度 */
  position: relative;
  background: blue;
}

.square-content {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* 使用 aspect-ratio(现代浏览器) */
.modern-square {
  width: 100%;
  aspect-ratio: 1 / 1;
}

.video-16-9 {
  width: 100%;
  aspect-ratio: 16 / 9;
}

流式排版

css
/* 使用 clamp 实现流式文字大小 */
h1 {
  font-size: clamp(2rem, 5vw, 4rem);
  /* 最小 2rem, 理想 5vw, 最大 4rem */
}

p {
  font-size: clamp(1rem, 1vw + 0.5rem, 1.5rem);
}

/* 流式间距 */
.section {
  padding: clamp(2rem, 5vw, 5rem) clamp(1rem, 3vw, 3rem);
}

容器查询单位(实验性)

css
/* 基于容器的单位 */
.card {
  container-type: inline-size;
}

.card-title {
  font-size: 5cqw; /* Container Query Width */
}

.card-content {
  padding: 2cqh; /* Container Query Height */
}

单位选择指南

用途推荐单位原因
字体大小rem全局一致性,易于响应式
内外边距(小)px精确控制细节
内外边距(大)rem保持整体比例
宽度%, vw, fr响应式布局
最大宽度px, rem限制极值
边框px精确到像素
阴影px精确控制
行高无单位数字相对于字体大小的倍数
媒体查询em, px一致的断点
动画s, ms时间控制

总结

选择合适的 CSS 单位是构建响应式、可维护网站的基础。没有绝对最好的单位,关键是理解每种单位的特性,根据具体场景做出明智的选择。

核心要点

  • 绝对单位:固定大小,不受上下文影响
    • px - 最常用,精确控制
    • 打印单位(cm, mm, in, pt, pc)- 主要用于打印样式
  • 相对单位:大小相对于其他元素或上下文
    • em - 相对于父元素,有复合效应
    • rem - 相对于根元素,无复合效应,推荐用于全局
    • % - 相对于父元素对应属性
  • 视口单位:相对于浏览器视口
    • vw, vh - 视口宽度和高度
    • vmin, vmax - 视口的最小/最大值
    • lvh, svh, dvh - 移动端视口单位
  • 其他单位:角度(deg, rad)、时间(s, ms)
  • calc() 函数:混合使用不同单位进行计算
  • 实战技巧:响应式排版、完美正方形、流式排版、容器查询
  • 选择指南:根据用途选择最合适的单位