CSS 八问8 questions on CSS
盒模型、margin vs padding、Flex vs Grid、选择器、预处理器、响应式。The box model, margin vs padding, Flex vs Grid, selectors, preprocessors, responsive design.
这一页有什么On this page9
- 01 什么是盒模型What is the box model?
- 02 margin vs padding
- 03 Flexbox vs Grid
- 04 CSS 选择器有哪些类型What types of CSS selectors are there?
- 05 有几种方式引入 CSSHow many ways are there to include CSS in a project?
- 06 什么是 SCSSWhat is SCSS?
- 07 CSS 预处理器的优缺点What are the advantages and disadvantages of a CSS preprocessor?
- 08 什么是响应式设计,怎么做What is responsive web design, and how do you build it?
- 迁移模式Transfer
- 说清标准盒模型和 border-box 的差别,并解释为什么大家都改成后者Explain the difference between the standard box model and border-box, and why almost everyone switches to border-box
- 在「一维排列」和「二维布局」之间正确地选 Flex 或 GridChoose between Flex and Grid correctly: one direction, or rows and columns at the same time
- 背出选择器优先级的计算规则State the rule for computing selector specificity
- 说明预处理器解决了什么、以及今天它的哪些功能已经被原生 CSS 取代Say what a preprocessor solved, and which of its features plain CSS now covers
CSS 题里只有两道有区分度:盒模型(考你有没有真的调过布局)和 Flex vs Grid(考你选型的判断)。其余几道是背诵题,但答错了很掉分。响应式那道常被追问到 rem / vw / 媒体查询断点怎么定。Only two CSS questions really separate candidates: the box model, which shows whether you have ever had to fix a layout, and Flex vs Grid, which shows your judgement about which tool to pick. The rest are recall questions, but getting one wrong costs a lot. The responsive design question often leads on to rem, vw, and how you choose media query breakpoints.
什么是盒模型What is the box model?
#271 What is the Box Model
一句话:每个元素都是一个盒子, 由内到外四层:content → padding → border → margin。
真正的考点是「width 到底量的是哪一段」:
box-sizing | width: 200px 指的是 | 加上 padding: 20px 后实际占 |
|---|---|---|
content-box(默认) | 只有 content | 240px(200 + 20 × 2) |
border-box | content + padding + border | 200px,content 被挤到 160px |
为什么现在几乎所有项目都全局改成border-box?因为「我说 200 宽就是 200 宽」符合直觉。 默认那套会让你在做「三列各 33.3%」时, 一加 padding 就换行 —— 这是新手最常撞的墙。
会追问:「margin 属于盒子吗?」——border-box 也不包含 margin。 margin 永远在盒子外面,是「盒子之间的距离」。
还会追问 margin 折叠(margin collapse):上下相邻的两个块级元素,上面的 margin-bottom: 20px和下面的 margin-top: 30px不会得到 50px,而是 30px(取较大值)。 这也是很多人「怎么调都差一点」的原因。 Flex 和 Grid 容器的子项不发生折叠。
In one line: every element is a box with four layers from the inside out: content → padding → border → margin.
What is actually being tested is “what exactly does width measure?”
box-sizing | width: 200px means | with padding: 20px it occupies |
|---|---|---|
content-box (default) | content only | 240px (200 + 20 × 2) |
border-box | content + padding + border | 200px; content is squeezed to 160px |
Why does nearly every project switch to border-box globally? Because “when I say 200 wide I mean 200 wide” matches intuition. The default makes three columns at 33.3% wrap the moment you add padding — the wall every beginner hits.
Follow-up: “Is margin part of the box?” — even border-box excludes margin. Margin is always outside; it is the distance between boxes.
They will also ask about margin collapse: two adjacent block elements with margin-bottom: 20px and margin-top: 30px give you 30px, not 50px (the larger wins). This is why spacing so often ends up “slightly off”. Flex and grid children do not collapse.
margin vs padding
#272 Margin vs Padding
一句话:padding 在边框里面, 是「内容和边框的距离」;margin 在边框外面,是「这个盒子和别人的距离」。
实际选哪个,看三条:
- 要不要背景色 / 点击区。padding 属于元素本身,会被背景色覆盖、点它算点到元素; margin 是空白,点不到。按钮想加大点击区一定用 padding。
- 会不会折叠。margin 会上下折叠,padding 永远不会。 想要「稳定的 20px 间距」用 padding 更可控。
- 负值。margin 可以是负数(常用来做重叠、抵消父级 padding), padding 不行。
会追问:「margin: 0 auto 为什么能居中,padding: auto 为什么不行?」—— margin 的 auto 会吃掉剩余空间并平分, padding 根本不支持 auto。 而且这招只对设了宽度的块级元素有效。
In one line: padding is inside the border — the gap between content and border; margin is outside — the gap between this box and everything else.
Three things decide which one you reach for:
- Background and hit area. Padding belongs to the element, so the background paints over it and clicks on it count as clicks on the element; margin is empty space you cannot click. Always use padding to enlarge a button’s hit area.
- Collapsing. Vertical margins collapse; padding never does. For a dependable 20px gap, padding is more predictable.
- Negative values. Margin can be negative (used for overlaps, or to cancel a parent’s padding); padding cannot.
Follow-up: “Why does margin: 0 auto centre something when padding: auto does nothing?” —auto margins absorb the leftover space and split it evenly; padding does not support auto at all. And the trick only works on a block element with a set width.
Flexbox vs Grid
#273 Flexbox vs Grid
一句话:Flex 是一维的 (一行或一列,内容驱动); Grid 是二维的(同时管行和列,布局驱动)。
怎么选,一个判断句就够:「我需要同时控制行和列的对齐吗?」 要 → Grid;不要 → Flex。
| Flex | Grid | |
|---|---|---|
| 维度 | 一维 | 二维 |
| 谁决定尺寸 | 内容(子项说我要多大) | 容器(我先划好格子,你往里放) |
| 典型场景 | 导航栏、按钮组、卡片内部的图文排列、 「左边文字右边按钮」 | 整页骨架(头/侧栏/主体/脚)、 商品瀑布流、日历、表单的标签列 + 输入列 |
| 缺口 | flex-wrap 换行后各行互不知道对方,对不齐 | 要先想清楚格子,改结构比 Flex 麻烦 |
会追问:「能一起用吗?」——正常做法就是一起用: Grid 搭页面骨架,每个格子内部用 Flex 排内容。 答「二选一」反而显得没实战过。
还会追问 flex: 1 是什么:它是三个属性的简写 ——flex-grow: 1; flex-shrink: 1; flex-basis: 0%。 意思是「剩余空间我来占,需要时也可以被压缩, 初始尺寸按 0 算」。 这就是「一个固定宽侧栏 + 一个自适应主体」最短的写法。
In one line: Flex is one-dimensional (a row or a column, content-driven); Grid is two-dimensional (rows and columns together, layout-driven).
One sentence decides it: “Do I need to control alignment across rows and columns at once?” Yes → Grid. No → Flex.
| Flex | Grid | |
|---|---|---|
| Dimensions | One | Two |
| Who decides size | The content (items say how big they are) | The container (cells first, content after) |
| Typical use | Nav bars, button groups, image-plus-text inside a card, “text left, button right” | Page skeleton (header / sidebar / main / footer), product grids, calendars, label-column plus input-column forms |
| Weakness | After flex-wrap, rows know nothing about each other, so nothing lines up | You must plan the cells; restructuring is more work |
Follow-up: “Can you use both?” — using both is the normal answer: Grid for the page skeleton, Flex for the contents of each cell. Saying “pick one” suggests you have not shipped much.
They will also ask what flex: 1 means: it is shorthand for flex-grow: 1; flex-shrink: 1; flex-basis: 0% — “I take the leftover space, I may be compressed, and my starting size counts as zero”. That is the shortest way to write “fixed sidebar plus fluid main area”.
CSS 选择器有哪些类型What types of CSS selectors are there?
#383 What are the different types of CSS selectors?
一句话:按「选中什么」分五类 —— 基础、组合、属性、伪类、伪元素。
- 基础:标签
div、 类.card、id#app、 通用* - 组合:后代
a b(空格)、 直接子元素a > b、 紧邻兄弟a + b、 后面所有兄弟a ~ b - 属性:
[type="text"]、[href^="https"](开头)、[class*="btn"](包含) - 伪类(状态):
:hover、:focus、:nth-child(2n)、:not(.on)、:disabled - 伪元素(造出不存在的元素):
::before、::after、::placeholder、::selection
会追问优先级怎么算—— 这才是真考点。按三位数比大小(id, class, 标签),从左往右比,高位一个也顶不过低位一万个:
| 选择器 | (id, class, 标签) |
|---|---|
div p | 0, 0, 2 |
.card p | 0, 1, 1 |
.card.on | 0, 2, 0 |
#app p | 1, 0, 1 ← 赢过上面所有 |
伪类算一个 class,伪元素算一个标签,:not() 本身不算分但括号里的算。 行内 style 比任何选择器都高,!important 再高一层 ——但别把 !important 当解法, 它通常说明选择器设计已经失控了。
同分怎么办?后写的赢。 这就是为什么覆盖第三方样式时, 把自己的 CSS 放在后面加载往往就够了。
In one line: five families, grouped by what they select — basic, combinator, attribute, pseudo-class, pseudo-element.
- Basic: type
div, class.card, id#app, universal* - Combinators: descendant
a b(space), direct childa > b, adjacent siblinga + b, all following siblingsa ~ b - Attribute:
[type="text"],[href^="https"](starts with),[class*="btn"](contains) - Pseudo-classes (state):
:hover,:focus,:nth-child(2n),:not(.on),:disabled - Pseudo-elements (invent an element):
::before,::after,::placeholder,::selection
The real question is specificity. Compare three numbers — (id, class, type) — left to right, and one high digit beats ten thousand low ones:
| Selector | (id, class, type) |
|---|---|
div p | 0, 0, 2 |
.card p | 0, 1, 1 |
.card.on | 0, 2, 0 |
#app p | 1, 0, 1 ← beats all of the above |
A pseudo-class counts as a class, a pseudo-element as a type, and :not() itself scores nothing but its argument does. Inline style outranks any selector, and !important outranks that — but do not treat !important as a solution; it usually means your selector design has already gone out of control.
What if they tie? The one written later wins. That is why loading your own CSS after a third-party stylesheet is often all you need.
有几种方式引入 CSSHow many ways are there to include CSS in a project?
#270 How many ways to import CSS in your project
一句话:传统上三种 —— 行内 style 属性、页内<style> 标签、外部<link> 文件(外加 CSS 里的@import)。
但面试问这题,其实想听你说现代工程里的做法:
- 普通 import——
import "./styles.css", 打包工具接管,全局生效。 - CSS Modules——
import s from "./x.module.css", 类名自动加哈希,天然不冲突。 - CSS-in-JS(styled-components、emotion)—— 样式写在 JS 里,能用 props 做条件样式。 代价是运行时开销。
- 原子化(Tailwind)—— 不写 CSS,直接堆预设类名。
会追问:「为什么不推荐 @import?」—— 因为它是串行的: 浏览器要先下载并解析外层 CSS, 才发现里面还有个 @import,再去下载。 这形成了一条请求链,直接拖慢首屏。 构建工具里的 @import 是编译期合并的, 不算这个问题 —— 说清这个区别是加分项。
In one line: traditionally three — an inline style attribute, an in-page <style> tag, an external file via <link> (plus@import from within CSS).
But what the interviewer wants is how it is done in a modern build:
- Plain import —
import "./styles.css"; the bundler takes over, styles are global. - CSS Modules —
import s from "./x.module.css"; class names are hashed, so collisions are impossible by construction. - CSS-in-JS (styled-components, emotion) — styles live in JS, so props can drive them. The cost is runtime work.
- Atomic (Tailwind) — you do not write CSS, you compose preset class names.
Follow-up: “Why is @import discouraged?” — because it is serial: the browser must download and parse the outer stylesheet before it even discovers the@import, then fetch again. That request chain delays first paint. @import handled by a build tool is merged at compile time and does not have this problem — pointing out that distinction is what earns the marks.
什么是 SCSSWhat is SCSS?
#275 What is SCSS
一句话:SCSS 是 Sass 的一种语法,CSS 的超集—— 合法的 CSS 就是合法的 SCSS, 但它多了变量、嵌套、mixin、函数这些编程能力, 最后编译成普通 CSS。
Sass 和 SCSS 什么关系?同一个工具的两种写法:.sass 靠缩进、没有大括号和分号;.scss 长得像 CSS。现在基本都用 .scss, 因为可以直接把老 CSS 粘进来。
核心能力四个:变量($brand: #2b6)、 嵌套(层级关系一眼看出来)、@mixin / @include(复用一组声明,可传参)、@use 拆文件。
会追问(这题真正想考的):「现在还需要它吗?」—— 老实说,需求少了很多: 变量被原生 CSS 自定义属性(--brand)取代,而且原生的能在运行时改、 能被 JS 读写、能跟着主题切换,比 SCSS 变量更强(本站的深色模式就是这么做的)。 嵌套也已经进了 CSS 标准。
剩下真正还有价值的是 mixin 和循环生成。 能这么答说明你知道边界在哪。
In one line: SCSS is one of Sass’s two syntaxes and a superset of CSS — valid CSS is valid SCSS — but it adds variables, nesting, mixins and functions, and compiles down to plain CSS.
Sass vs SCSS? Two syntaxes for the same tool:.sass is indentation-based with no braces or semicolons;.scss looks like CSS. .scss is what everyone uses now, because you can paste existing CSS straight in.
Four core abilities: variables ($brand: #2b6), nesting (hierarchy visible at a glance),@mixin / @include (reuse a group of declarations, with arguments), and @use for splitting files.
The follow-up this question really exists for: “Do you still need it?” — honestly, much less. Variables have been superseded by native CSS custom properties (--brand), and the native ones are strictly more capable: they live at runtime, JS can read and write them, and they follow theme switches (this site’s dark mode works exactly that way). Nesting has landed in the CSS standard too.
What genuinely remains valuable is mixins and generated loops. Answering this way shows you know where the boundary is.
CSS 预处理器的优缺点What are the advantages and disadvantages of a CSS preprocessor?
#384 What is a CSS preprocessor? What are the advantages and disadvantages, if any, to using them over plain CSS?
一句话:预处理器是「用一种更强的语言写样式, 再编译成 CSS」。Sass / Less / Stylus 都是。
好处:变量集中管理、嵌套让结构清晰、 mixin 复用、能循环生成(比如 .mt-1 到.mt-10)、能拆成很多小文件再合并。
代价(面试重点问这半边):
- 多一步构建。多一个依赖、多一份配置、 多一处可能出错的地方。
- 嵌套太容易写深。一不注意就写出
.a .b .c .d span, 优先级越滚越高,最后只能靠!important收场。这是预处理器最真实的坑—— 实践里一般限制自己不超过三层。 - 调试要靠 source map。DevTools 里看到的是编译产物,行号对不上。
- 门槛。新人得先学一套额外语法。
结论怎么说:「大项目、有设计系统、需要批量生成样式时值得; 小项目用原生 CSS 加自定义属性就够,因为它当年解决的两个主要问题(变量、嵌套) 原生已经支持了。」 —— 有取舍的回答比一味夸好。
In one line: a preprocessor lets you write styles in a more capable language and compiles them to CSS. Sass, Less and Stylus all qualify.
Upsides: variables in one place, nesting that makes structure obvious, mixins for reuse, loops that generate families of rules (.mt-1 through .mt-10), and splitting into many small files that get merged.
Costs — this is the half they probe:
- An extra build step. One more dependency, one more config, one more place things break.
- Nesting is far too easy to over-use. Before you notice you have written
.a .b .c .d span, specificity keeps climbing, and the only way out is!important. This is the preprocessor’s most real trap — in practice teams cap themselves at about three levels. - Debugging needs source maps. DevTools shows you the compiled output and the line numbers do not match.
- Onboarding cost. Newcomers must learn extra syntax.
How to land the conclusion: “Worth it on large projects with a design system and lots of generated styles; for small projects plain CSS plus custom properties is enough, because the two problems it originally solved — variables and nesting — are now native.” A weighed answer beats unconditional praise.
什么是响应式设计,怎么做What is responsive web design, and how do you build it?
#274 What is responsive web design and how to achieve this
一句话:一套代码在不同屏幕尺寸下 都给出合适的排版,而不是给手机单独做一个站。
四个手段,按重要性排:
- viewport meta——前提,没有它后面全白干(见 #381)。
- 弹性单位—— 宽度用
%/fr/min()/clamp(), 字号用rem,别到处写死px。clamp(16px, 4vw, 24px)一行就能做出「有上下限的流式字号」。 - 媒体查询——
@media (max-width: 768px)改布局。 - 弹性布局——
flex-wrap和grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)),很多时候一行都不用写媒体查询就自适应了。
会追问:「断点怎么定?」—— 正确答案是「按内容定,不是按设备定」: 把浏览器慢慢拉窄,哪里开始难看就在哪里加断点。 追着 iPhone 型号列表定断点是过时做法, 因为设备尺寸年年变。
还会追问 mobile-first:默认样式写窄屏,用 min-width 往上加。 好处是移动端加载的 CSS 最少, 而且「加东西」比「删东西」好写 —— 用 max-width 往下覆盖经常要反复清理属性。
In one line: one codebase that lays out sensibly at any screen size — rather than building a separate mobile site.
Four techniques, most important first:
- The viewport meta tag — the precondition; without it nothing else matters (see #381).
- Flexible units — widths in
%/fr/min()/clamp(), font sizes inrem; stop hard-codingpxeverywhere.clamp(16px, 4vw, 24px)gives you a fluid font size with hard limits in a single line. - Media queries —
@media (max-width: 768px)to change layout. - Flexible layout —
flex-wrapandgrid-template-columns: repeat(auto-fit, minmax(240px, 1fr))often adapt without a single media query.
Follow-up: “How do you choose breakpoints?” — the right answer is “from the content, not from device sizes”: drag the window narrower and add a breakpoint wherever it starts looking wrong. Chasing a list of iPhone dimensions is outdated, because device sizes change every year.
They will also ask about mobile-first: write the narrow layout as the default and add to it with min-width. Mobile then downloads the least CSS, and “adding” is easier to reason about than “undoing” — overriding downwards with max-width usually means repeatedly resetting properties.
换一道题也能用Works on other problems too
考试不会原题重考。真正能带走的是「看到这种信号 → 伸手去拿这个解法」。The exam will not reuse the same question. What you take away is the reflex: see this signal, reach for that solution.
- 盒模型四层 content/padding/border/margin;border-box 让 width 包含 padding 和 border,margin 永远在外面。The box model has four layers: content, padding, border, margin. With border-box, width includes padding and border; margin is always outside the width.
- margin 会上下折叠、可以为负、点不到;padding 不折叠、不能为负、属于点击区。Margin collapses vertically, can be negative, and is not clickable; padding never collapses, cannot be negative, and is part of the clickable area.
- Flex 一维内容驱动,Grid 二维布局驱动;实战是 Grid 搭骨架 + Flex 排内容。Flex works in one direction and follows the content; Grid works in two and follows the layout. In practice: Grid for the page frame, Flex for the content inside it.
- 优先级按 (id, class, 标签) 三位比大小,高位压倒低位;同分后写的赢。Specificity compares three numbers, (id, class, tag), from left to right; a higher number wins outright, and on a tie the rule written later wins.
- @import 会串行请求拖慢首屏,用 link 或构建工具合并。@import makes requests one after another and slows the first paint; use link, or let the build tool merge the files.
- SCSS 的变量和嵌套已被原生 CSS 取代,mixin 和循环生成还有价值。Plain CSS has taken over SCSS variables and nesting; mixins and generating rules in a loop are still worth having.
- 响应式四件套:viewport meta、弹性单位、媒体查询、弹性布局;断点按内容定。Responsive design has four parts: the viewport meta tag, relative units, media queries, and a flexible layout; choose breakpoints by where the content breaks.