Skip to content

CSS 核心概念面试题集

CSS 核心概念、选择器、定位、BFC 等高频面试题

A. 面试宝典

基础题

1. CSS 选择器

┌─────────────────────────────────────────────────────────────┐
│                    CSS 选择器类型                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  基础选择器:                                                │
│  ──────────────────────────────────────────────────────────│
│  *              全部元素                                    │
│  div            元素选择器                                  │
│  .class         类选择器                                    │
│  #id            ID 选择器                                   │
│  [attr]         属性选择器                                  │
│                                                              │
│  组合选择器:                                                │
│  ──────────────────────────────────────────────────────────│
│  div, p         并集(div 和 p)                            │
│  div p          后代(div 里所有 p)                         │
│  div > p        子代(div 的直接子 p)                       │
│  div + p        相邻兄弟(div 后紧邻的 p)                   │
│  div ~ p        通用兄弟(div 后所有兄弟 p)                 │
│                                                              │
└─────────────────────────────────────────────────────────────┘

属性选择器:

css
/* 存在属性 */
[title] { }

/* 属性等于值 */
[type="text"] { }

/* 属性包含值(空格分隔) */
[class~="box"] { }

/* 属性以值开头 */
[href^="https"] { }

/* 属性以值结尾 */
[src$=".png"] { }

/* 属性包含子串 */
[href*="example"] { }

/* 属性以值开头或以值-开头 */
[lang|="en"] { }

伪类选择器:

css
/* 动态伪类 */
a:link     { }  /* 未访问 */
a:visited  { }  /* 已访问 */
a:hover    { }  /* 悬停 */
a:active   { }  /* 激活 */
a:focus    { }  /* 聚焦 */

/* 结构伪类 */
:first-child    { }  /* 第一个子元素 */
:last-child     { }  /* 最后一个子元素 */
:nth-child(n)   { }  /* 第 n 个子元素 */
:nth-child(2n)  { }  /* 偶数子元素 */
:nth-child(odd) { }  /* 奇数子元素 */
:only-child     { }  /* 唯一子元素 */

:first-of-type  { }  /* 同类型第一个 */
:last-of-type   { }  /* 同类型最后一个 */
:nth-of-type(n) { }  /* 同类型第 n 个 */

/* 状态伪类 */
:checked    { }  /* 选中 */
:disabled   { }  /* 禁用 */
:enabled    { }  /* 启用 */
:empty      { }  /* 空元素 */
:not(sel)   { }  /* 否定 */
:is(sel)    { }  /* 匹配任一 */
:where(sel) { }  /* 同 :is,但优先级为 0 */
:has(sel)   { }  /* 包含(父选择器) */

伪元素选择器:

css
::before      { }  /* 前置内容 */
::after       { }  /* 后置内容 */
::first-line  { }  /* 首行 */
::first-letter{ }  /* 首字母 */
::selection   { }  /* 选中文本 */
::placeholder { }  /* 占位符 */

2. 选择器优先级

┌─────────────────────────────────────────────────────────────┐
│                    选择器优先级计算                          │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  优先级权重(从高到低):                                    │
│  ──────────────────────────────────────────────────────────│
│  !important              无穷大(慎用)                     │
│  内联样式 (style="")     1000                              │
│  ID 选择器               100                               │
│  类/伪类/属性选择器      10                                │
│  元素/伪元素选择器       1                                 │
│  通配符 *                0                                 │
│                                                              │
│  计算示例:                                                 │
│  ──────────────────────────────────────────────────────────│
│  #nav .item a:hover     = 100 + 10 + 1 + 10 = 121         │
│  div.container p        = 1 + 10 + 1 = 12                  │
│  [type="text"]          = 10                               │
│                                                              │
└─────────────────────────────────────────────────────────────┘

优先级规则:

css
/* 1. !important 最高 */
.box { color: red !important; }

/* 2. 相同优先级,后者覆盖前者 */
.box { color: red; }
.box { color: blue; }  /* 生效 */

/* 3. 更具体的选择器胜出 */
.container .box { color: red; }   /* 0,0,2,0 - 生效 */
.box { color: blue; }              /* 0,0,1,0 */

/* 4. 继承样式优先级最低 */
body { color: red; }
p { color: blue; }  /* p 元素使用 blue */

3. 定位(Position)

┌─────────────────────────────────────────────────────────────┐
│                    Position 定位类型                         │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  static(默认):                                           │
│  - 正常文档流                                               │
│  - top/right/bottom/left 无效                              │
│                                                              │
│  relative(相对定位):                                      │
│  - 相对于自身原始位置偏移                                    │
│  - 保留原始空间                                             │
│  - 创建定位上下文                                           │
│                                                              │
│  absolute(绝对定位):                                      │
│  - 脱离文档流                                               │
│  - 相对于最近的定位祖先                                      │
│  - 没有定位祖先则相对于 ICB(初始包含块)                    │
│                                                              │
│  fixed(固定定位):                                        │
│  - 脱离文档流                                               │
│  - 相对于视口                                               │
│  - 滚动时位置不变                                           │
│                                                              │
│  sticky(粘性定位):                                       │
│  - 相对定位和固定定位的混合                                  │
│  - 滚动到阈值前是 relative                                  │
│  - 滚动到阈值后是 fixed                                     │
│                                                              │
└─────────────────────────────────────────────────────────────┘

定位示例:

css
/* 相对定位 */
.relative {
  position: relative;
  top: 10px;
  left: 20px;
}

/* 绝对定位 */
.parent {
  position: relative;  /* 创建定位上下文 */
}
.absolute {
  position: absolute;
  top: 0;
  right: 0;
}

/* 固定定位 */
.fixed-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
}

/* 粘性定位 */
.sticky-nav {
  position: sticky;
  top: 0;
  /* 滚动到顶部时固定 */
}

/* 居中技巧 */
.center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

4. BFC(块级格式化上下文)

┌─────────────────────────────────────────────────────────────┐
│                    BFC 块级格式化上下文                      │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  触发 BFC 的条件:                                          │
│  ──────────────────────────────────────────────────────────│
│  1. 根元素(html)                                          │
│  2. float 不为 none                                         │
│  3. position 为 absolute 或 fixed                          │
│  4. overflow 不为 visible                                   │
│  5. display 为 inline-block, table-cell, table-caption     │
│  6. display 为 flex, grid                                  │
│  7. display: flow-root(推荐)                             │
│                                                              │
│  BFC 的特性:                                               │
│  ──────────────────────────────────────────────────────────│
│  1. 内部盒子垂直排列                                        │
│  2. 同一 BFC 内相邻 margin 会合并                           │
│  3. BFC 区域不与 float 元素重叠                             │
│  4. BFC 是独立容器,内外不互相影响                          │
│  5. BFC 可以包含浮动元素(清除浮动)                        │
│                                                              │
└─────────────────────────────────────────────────────────────┘

BFC 应用:

css
/* 1. 清除浮动(父元素塌陷) */
.clearfix {
  display: flow-root;  /* 推荐 */
  /* 或 overflow: hidden; */
}

/* 2. 阻止 margin 合并 */
.wrapper {
  overflow: hidden;  /* 创建 BFC */
}
.wrapper .child {
  margin: 20px;  /* 不会与外部 margin 合并 */
}

/* 3. 自适应两栏布局 */
.sidebar {
  float: left;
  width: 200px;
}
.main {
  overflow: hidden;  /* 创建 BFC,不与浮动重叠 */
}

5. 层叠上下文(Stacking Context)

┌─────────────────────────────────────────────────────────────┐
│                    层叠上下文                                │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  创建层叠上下文的条件:                                      │
│  ──────────────────────────────────────────────────────────│
│  1. 根元素(html)                                          │
│  2. position: relative/absolute + z-index 非 auto          │
│  3. position: fixed/sticky                                  │
│  4. flex/grid 子项 + z-index 非 auto                        │
│  5. opacity < 1                                             │
│  6. transform 非 none                                       │
│  7. filter 非 none                                          │
│  8. isolation: isolate                                      │
│                                                              │
│  层叠顺序(从下到上):                                      │
│  ──────────────────────────────────────────────────────────│
│  1. 层叠上下文的背景和边框                                  │
│  2. z-index 为负值                                          │
│  3. 块级盒子                                                │
│  4. 浮动盒子                                                │
│  5. 行内盒子                                                │
│  6. z-index: 0 / auto                                       │
│  7. z-index 为正值                                          │
│                                                              │
└─────────────────────────────────────────────────────────────┘
css
/* 层叠上下文示例 */
.parent {
  position: relative;
  z-index: 1;  /* 创建层叠上下文 */
}

.child {
  position: absolute;
  z-index: 999;  /* 不会超出父元素的层叠上下文 */
}

/* 隔离层叠上下文 */
.isolated {
  isolation: isolate;  /* 创建新的层叠上下文 */
}

进阶题

6. Margin 塌陷与合并

┌─────────────────────────────────────────────────────────────┐
│                    Margin 问题                               │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  1. Margin 合并(相邻元素):                               │
│  ┌─────────────────┐                                        │
│  │ margin-bottom:20│                                        │
│  └─────────────────┘                                        │
│          ↓ 合并后取较大值 20px                              │
│  ┌─────────────────┐                                        │
│  │ margin-top: 10  │                                        │
│  └─────────────────┘                                        │
│                                                              │
│  2. Margin 塌陷(父子元素):                               │
│  父元素没有 border/padding/BFC                              │
│  子元素的 margin-top 会"穿透"到父元素外                     │
│                                                              │
└─────────────────────────────────────────────────────────────┘

解决方案:

css
/* 解决 margin 合并 */
/* 方案1:只设置一边的 margin */
.box { margin-bottom: 20px; }
.box + .box { margin-top: 0; }

/* 解决 margin 塌陷 */
/* 方案1:父元素加边框 */
.parent { border-top: 1px solid transparent; }

/* 方案2:父元素加 padding */
.parent { padding-top: 1px; }

/* 方案3:父元素创建 BFC */
.parent { overflow: hidden; }
.parent { display: flow-root; }  /* 推荐 */

7. 居中方案

css
/* ============= 水平居中 ============= */

/* 1. 行内元素 */
.parent {
  text-align: center;
}

/* 2. 块级元素(定宽) */
.block {
  width: 200px;
  margin: 0 auto;
}

/* 3. Flex */
.parent {
  display: flex;
  justify-content: center;
}

/* ============= 垂直居中 ============= */

/* 1. 单行文本 */
.text {
  height: 50px;
  line-height: 50px;
}

/* 2. Flex */
.parent {
  display: flex;
  align-items: center;
}

/* 3. 绝对定位 + transform */
.child {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

/* ============= 水平垂直居中 ============= */

/* 1. Flex(推荐) */
.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 2. Grid */
.parent {
  display: grid;
  place-items: center;
}

/* 3. 绝对定位 + transform */
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* 4. 绝对定位 + margin auto(定宽高) */
.child {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  width: 200px;
  height: 100px;
}

/* 5. 表格布局 */
.parent {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}

8. 响应式设计

css
/* 媒体查询 */
/* 移动优先 */
.box {
  width: 100%;
}

@media (min-width: 576px) {
  .box { width: 50%; }
}

@media (min-width: 768px) {
  .box { width: 33.33%; }
}

@media (min-width: 992px) {
  .box { width: 25%; }
}

@media (min-width: 1200px) {
  .box { width: 20%; }
}

/* 桌面优先 */
.box {
  width: 20%;
}

@media (max-width: 1199px) {
  .box { width: 25%; }
}

/* 响应式断点 */
/*
  xs: < 576px   手机竖屏
  sm: 576px+    手机横屏
  md: 768px+    平板
  lg: 992px+    笔记本
  xl: 1200px+   桌面
  xxl: 1400px+  大屏
*/

/* 容器查询(CSS Container Queries) */
.card-container {
  container-type: inline-size;
  container-name: card;
}

@container card (min-width: 400px) {
  .card {
    display: flex;
  }
}

/* 响应式单位 */
.responsive {
  /* 视口单位 */
  width: 50vw;   /* 视口宽度的 50% */
  height: 100vh; /* 视口高度的 100% */
  font-size: 2vmin; /* vw 和 vh 的较小值 */

  /* 相对单位 */
  font-size: 1rem;  /* 根元素字体大小 */
  padding: 1em;     /* 当前元素字体大小 */

  /* clamp 函数 */
  font-size: clamp(16px, 4vw, 24px);
  width: clamp(200px, 50%, 600px);
}

9. CSS 变量(自定义属性)

css
/* 定义变量 */
:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  --font-size-base: 16px;
  --spacing: 8px;
  --border-radius: 4px;
}

/* 使用变量 */
.button {
  background-color: var(--primary-color);
  padding: calc(var(--spacing) * 2);
  border-radius: var(--border-radius);
  font-size: var(--font-size-base);
}

/* 带默认值 */
.box {
  color: var(--text-color, #333);
}

/* 局部覆盖 */
.dark-theme {
  --primary-color: #0d6efd;
  --text-color: #fff;
  --bg-color: #212529;
}

/* JavaScript 操作 */
// 获取变量
getComputedStyle(document.documentElement)
  .getPropertyValue('--primary-color');

// 设置变量
document.documentElement.style
  .setProperty('--primary-color', '#ff0000');

10. CSS 动画

css
/* Transition 过渡 */
.box {
  transition: all 0.3s ease;
  /* transition: property duration timing-function delay; */

  transition-property: transform, opacity;
  transition-duration: 0.3s;
  transition-timing-function: ease-in-out;
  transition-delay: 0s;
}

.box:hover {
  transform: scale(1.1);
  opacity: 0.8;
}

/* Animation 动画 */
@keyframes slideIn {
  0% {
    transform: translateX(-100%);
    opacity: 0;
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 或使用 from/to */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.animated {
  animation: slideIn 0.5s ease-out forwards;
  /* animation: name duration timing-function delay iteration-count direction fill-mode; */

  animation-name: slideIn;
  animation-duration: 0.5s;
  animation-timing-function: ease-out;
  animation-delay: 0s;
  animation-iteration-count: 1;  /* infinite */
  animation-direction: normal;   /* reverse, alternate */
  animation-fill-mode: forwards; /* backwards, both */
  animation-play-state: running; /* paused */
}

/* 性能优化:使用 transform 和 opacity */
/* 这两个属性不触发重排重绘,由 GPU 加速 */
.performant {
  transform: translateX(100px);
  opacity: 0.5;
}

/* will-change 提示浏览器优化 */
.will-animate {
  will-change: transform, opacity;
}

避坑指南

常见错误正确做法
使用 px 固定尺寸使用 rem/em/% 响应式单位
!important 滥用提高选择器优先级
浮动未清除使用 BFC 或 clearfix
z-index 层级混乱建立 z-index 管理规范
动画性能差只用 transform/opacity
选择器嵌套过深控制在 3 层以内

B. 实战文档

常用布局模式

css
/* 1. 两栏布局(左固定右自适应) */
.layout-two-column {
  display: flex;
}
.sidebar {
  width: 200px;
  flex-shrink: 0;
}
.main {
  flex: 1;
}

/* 2. 三栏布局(圣杯/双飞翼) */
.layout-three-column {
  display: flex;
}
.left, .right {
  width: 200px;
  flex-shrink: 0;
}
.center {
  flex: 1;
}

/* 3. 等高布局 */
.equal-height {
  display: flex;
}
.equal-height > * {
  flex: 1;
}

/* 4. 粘性页脚 */
body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
main {
  flex: 1;
}
footer {
  flex-shrink: 0;
}

/* 5. 卡片网格 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}

/* 6. 瀑布流(Masonry) */
.masonry {
  columns: 3;
  column-gap: 20px;
}
.masonry-item {
  break-inside: avoid;
  margin-bottom: 20px;
}

常用样式片段

css
/* 文本截断 */
.text-ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 多行截断 */
.text-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* 清除浮动 */
.clearfix::after {
  content: '';
  display: table;
  clear: both;
}

/* 隐藏滚动条 */
.hide-scrollbar {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE/Edge */
}
.hide-scrollbar::-webkit-scrollbar {
  display: none; /* Chrome/Safari */
}

/* 自定义滚动条 */
.custom-scrollbar::-webkit-scrollbar {
  width: 8px;
}
.custom-scrollbar::-webkit-scrollbar-track {
  background: #f1f1f1;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
  background: #888;
  border-radius: 4px;
}

/* 平滑滚动 */
html {
  scroll-behavior: smooth;
}

/* 禁止选中 */
.no-select {
  user-select: none;
}

/* 图片自适应 */
.img-responsive {
  max-width: 100%;
  height: auto;
}

/* 图片覆盖 */
.img-cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 毛玻璃效果 */
.glass {
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
}

/* 阴影 */
.shadow-sm { box-shadow: 0 1px 2px rgba(0,0,0,0.1); }
.shadow-md { box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
.shadow-lg { box-shadow: 0 10px 15px rgba(0,0,0,0.1); }

/* 渐变 */
.gradient {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

/* 三角形 */
.triangle {
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-bottom: 15px solid #333;
}

/* 圆形 */
.circle {
  width: 50px;
  height: 50px;
  border-radius: 50%;
}

CSS Reset

css
/* Modern CSS Reset */
*, *::before, *::after {
  box-sizing: border-box;
}

* {
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
}

input, button, textarea, select {
  font: inherit;
}

p, h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}

a {
  color: inherit;
  text-decoration: none;
}

ul, ol {
  list-style: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

基于 VitePress 构建