默认只显示问题 —— 先自己在心里答一遍,再展开对答案。答不上来就标「不会」,下次抽认卡会先抽它。Only the question shows by default. Answer it in your head first, then open the answer. Mark the ones you miss; the flashcard round puts those first.
0 / 105道自评过self-assessed
0会Got it0模糊Shaky0不会No idea105还没做Not seen
正在读这台浏览器里的标记…Reading your marks from this browser…
标记不是打分,是给下一轮排队Marks are a queue, not a score
标「不会」的题会排到抽认卡最前面,标「会」的进低频池排最后。所以别客气 —— 觉得答得磕磕巴巴就标「模糊」。准备好了就去抽认卡。“No idea” jumps to the front of the next round; “got it” drops to the back. So be honest — if it came out shaky, mark it shaky. Then go run a flashcard round.
In one line: a block element takes the whole line and you can set its width and height; an inline element flows with the text and is sized by its content.
There are exactly three differences worth remembering:
Line breaks — block elements break before and after (div, p, h1, ul); inline ones do not (span, a, strong, img).
Width and height — settable on block elements, ignored on inline ones.
Margin and padding — all four sides work on block elements; on inline elements vertical margin does nothing, and vertical padding overflows visually without pushing the line apart.
Follow-up: “What about inline-block?” — it is the compromise: no line break (like inline) but width, height and vertical margin all work (like block). Nav buttons use it constantly.
Also asked: “img is inline, so why can you set its size?” — because it is a replaced element: its content comes from an external resource, so the browser makes an exception. Same for input and video. Getting this one right scores points.
In one line: a click travels the DOM in three phases — down from window to the target (capture), fires on the target, then back up to window (bubble). Capture goes outside-in, bubbling goes inside-out.
The third argument to addEventListener picks the phase you listen in: false (the default) is bubbling, true (or { capture: true }) is capture.
Why is bubbling the default? Because what you almost always want to know is “what did the user click”, and inside-out is the natural direction for that — it is also what makes event delegation possible (see #289).
Follow-up: “How do you stop it?”
e.stopPropagation() — stop travelling further up (or down).
e.stopImmediatePropagation() — also skip other listeners on the same element.
e.preventDefault() — cancels the default behaviour (link navigation, form submit) and has nothing to do with propagation. These two get mixed up most often; do not confuse them.
Also asked: “Which events do not bubble?” —focus, blur, load, mouseenter, mouseleave. When you need to delegate, use their bubbling counterparts: focusin / focusout / mouseover / mouseout.
JavaScript三个阶段的完整顺序The full order of the three phases示意Illustrative
面试里画得出这个顺序,基本就过了。注意目标元素上的监听器不分捕获/冒泡,按注册顺序执行。If you can draw this order in an interview, that question is handled. One detail: on the target element itself there is no capture or bubble distinction, so those listeners run in the order they were registered.
In one line:meta carries information about the page — browsers, search engines and social platforms read it; users never see it.
Only four of them actually matter day to day:
<meta charset="UTF-8"> — must be first in the head. Without it non-ASCII text turns to mojibake, because the browser has to know the encoding before it can parse the bytes that follow.
viewport — the precondition for mobile. Without this line a phone browser pretends it is 980px wide and scales the whole page down, which throws away every responsive rule you wrote (see #274).
description — the snippet in search results. It does not affect ranking, but it affects click-through.
Open Graph (og:title, og:image) — the card shown when the link is shared into Slack, Twitter or a chat app.
Follow-up: “Does keywords still do anything?” — no. Google stopped reading it long ago because it was abused into keyword stuffing. Knowing this shows you are not reciting an old tutorial.
In one line: the tag name itself states the role of the content — header / nav / main /article / section / aside /footer — whereas div and span say nothing at all.
Do not answer “the code looks nicer”. Semantics buys you two things you can actually measure:
Screen readers can navigate. A blind user can jump to the main content or list every heading — and those features depend on tag semantics. On a page of nothing but divs, a screen reader can only read from the top.
Search engines know which part is the article. Content in main weighs more than content in aside.
Follow-up: “So how do you choose between section and div?” — the test is “does this block have its own heading?” If it does (you could give it an h2), use section. If it is a wrapper you added purely for layout, use div. A container that exists for styling should be a div — forcing it to be a section just pollutes the document outline.
Accessibility (a11y) — can people with disabilities use it: vision, hearing, motor, cognitive.
Usability — how smoothly can people who can use it, use it: can they find things, understand them, avoid mis-taps.
Inclusion — how wide is the net: older users, slow connections, small screens, non-native speakers, someone operating one-handed while holding a child.
The three nest: accessibility is part of inclusion, and anything with poor usability is worse for everyone.
One example each — examples are what the interviewer wants:
a11y: write alt on images; tie a label to its input with htmlFor; make sure Tab reaches every interactive element and do not delete the focus ring with outline: none.
usability: label the button “Save draft” rather than “Submit”; put the validation error on the field that failed, not a generic banner at the top of the page.
inclusion: at least 4.5:1 contrast for body text; never use colour as the only carrier of meaning (someone with red-green colour blindness cannot see that “red means wrong”, so add an icon or a word); make the first screen usable on 3G.
Follow-up: “How do you test it?” — walk the main flow with the keyboard only; run Lighthouse’s a11y audit in Chrome DevTools; scan with the axe extension. Naming the tools is more convincing than naming the concepts.
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-boxexcludes 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: 30pxgive you 30px, not 50px (the larger wins). This is why spacing so often ends up “slightly off”. Flex and grid children do not collapse.
CSS全局重置示意Illustrative
1/* 几乎每个项目开头都有这三行 */
2*,
3*::before,
4*::after{
5box-sizing:border-box;
6}
1/* Almost every project starts with these three lines */
会不会折叠。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.
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实际项目里的分工示意Illustrative
1/* Grid 搭骨架 */
2.layout{
3display:grid;
4grid-template-columns:240px1fr;/* 侧栏固定,主体吃剩下的 */
5grid-template-rows:56px1fr;
6min-height:100vh;
7}
8
9/* 格子内部用 Flex 排内容 */
10.topbar{
11display:flex;
12align-items:center;
13justify-content:space-between;
14gap:12px;
15}
16
17/* 「固定宽 + 自适应」的经典两行 */
18.sidebar{flex:00240px;}/* 不长不缩,就 240 */
19.content{flex:1;}/* 剩下全归我 */
1/* Grid for the skeleton */
2.layout{
3display:grid;
4grid-template-columns:240px1fr;/* sidebar fixed, main takes the rest */
5grid-template-rows:56px1fr;
6min-height:100vh;
7}
8
9/* Flex for the content inside a cell */
10.topbar{
11display:flex;
12align-items:center;
13justify-content:space-between;
14gap:12px;
15}
16
17/* The classic two lines for "fixed width plus fill the rest" */
18.sidebar{flex:00240px;}/* never grows, never shrinks, stays 240 */
19.content{flex:1;}/* takes everything that is left */
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.
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.
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.
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.
99 道来自面试题库 #269–#387;TypeScript 深度那 6 道是 DrillLab 自出的(senior 补强,卡片上有标注)。答案都是 DrillLab 写的,所以讲解里的代码块一律标「示意」。每道题都能点回它出处的那一节课。99 questions come from the interview bank (#269–#387); the 6 TypeScript deep-dive ones are DrillLab-made (marked on the card). All answers are written by DrillLab, so every code block here is labelled “demo”. Each card links back to the lesson it came from.