Skip to main content

常见问题

tip
  • 布局谨记三个上下文:
    • containing block - 位置 - 影响 paint, relayout
    • stacking context - z-index
    • block formatting context - flow, float
  • border 不支持渐变
  • -webkit-user-modify
  • BEM - Block Element Modifier
    • by Yandex 2007
    • .block - .block--mod
    • .block__elem - .block__elem--mod
    • 目前已不太推荐,以前全局 CSS 容易冲突,现在很容易用 css module 和控制 scope
  • CSS Reference
.style {
/* 对齐数字 */
font-variant-numeric: tabular-nums;
}

border 渐变

margin 重叠

pure selector

  • 能够被 prefix 的 selector
  • 用于 css module
/* 不是 pure selector */
:global(body) {
}
/* 是 pure selector - 会变成 .xyz body */
body {
}

浏览器兼容问题

  • aspect-ratio - Chrom 88, Safari 15
    • 不支持的时候可能导致 height/width 为 0
    • 使用 padding hack
  • @supports - Chrome 28, Safari 9
  • @supports selector - Chrome 83, Safari 14.1
@supports (aspect-ratio: 1/1) {
aspect-ratio: 1/1;
}
@supports not (aspect-ratio: 1/1) {
/* 补偿 */
}

/* 检测 selector 是否支持 */
@supports selector(:nth-child(1n of a, b)) {
}
// 当前环境版本信息
navigator.userAgent;

// Chrome 61, Safari 9
CSS.supports('aspect-ratio: 1/1');
CSS.supports('aspect-ratio', '1/1');

backdrop-filter

  • Chrome 76+ 正式支持,之前加前缀
    • Chrome 对 backdrop filter 支持不太好
    • 如果页面使用了 mix-blend 会导致 blur 有问题 #1254774
  • Safari 加前缀支持 - 效果正常
  • FF 尚不支持
  • tailwindcss backdrop-filter 可能没有 prefix

通过 before 和 after 来补偿

Optimize

visibility vs display

Containing Block

  • Containing Block 组成
    1. Content area
    2. Padding area
    3. Border area
    4. Margin area
  • 基于 Containing Block 计算的属性
    • 百分比 width, height, padding, margin
    • 位置偏移 - 当 position 为 absolute 或 fixed 时
  • html 为 initial containing block
  • 形成 Containing Block 的场景
    • 受 positon 影响
    • position 为 absolute 或 fixed

stacking context

  • The stacking context
  • 影响 z-index
  • 形成场景
    • position = absolute or relative 且 z-index != auto
    • position = fixed or sticky
    • child of flex 且 z-index != auto
    • child of grid 且 z-index != auto
    • opacity < 1
    • mix-blend-mode != normal
    • isolate
    • contain = layout or paint

  • Compositing and Blending Level 2
    • isolation
      • 强制创建 stacking context
      • 用于配合 mix-blend

避免 z-index 混淆

  • 建立新的 z-index 栈 - isolation: isolate

block formatting context

  • Block formatting context
  • 影响 float, flow 布局
  • 形成场景
    • float != none
    • position = absolute or relative
    • display: inline-block
    • display: table-cell
    • display: table-caption
    • overflow != visible or clip
    • contain: layout, content, or paint
    • flex items
    • grid items

Layout mode

  • Layout mode
    • Normal flow
    • Table
    • Positioned
    • Multi-column - 内容多列 - 类似 报纸
    • Flexible
    • Grid

Boxing

Box typeComposition
Margin boxmargin + border + padding + content
Border boxborder + padding + content
Padding boxpadding + content
Content boxcontent

inline vs block

影响 Layout

  • inline
    • 只能影响 tag 内 - 例如没有 margin
    • 不会影响 layout flow - 不换行
    • 只能包含 数据 和 inline 元素
  • block
    • 通常开启新行
    • 可包含 inline 和 block

元素直接支持 resize

.container {
overflow: hidden; /* required by resize:both */
resize: both;
}

overflow + absolute

重置元素所有属性

.container {
/* 重置除了 unicode-bidi 和 direction 之外的所有属性 */
all: initial;
}

只有键盘控制时才添加焦点外边框,鼠标点击无外边框

  • :focus-visible - 键盘控制产生的 focus
button:not(:focus-visible) {
outline: none;
}

子节点有焦点时父节点添加样式

  • :focus-within

匹配空节点

  • :empty

避免 flex 容器溢出

  • 添加 min-width: 0
  • Why
    • 默认 min-width: auto 允许元素占用更多空间

播放 png 精灵图

display: table 不支持 max-height 和 overflow

  • 建议使用 flex 模拟 table
    • thead 和 tbody 可能不同步
      • overflow-x: hidden 确保两个同步
    • width: 100% 可能显示不完整 - 滚动出的内容背景不完整
      • max-content 显示完整
      • 如果 width 不够会导致右侧滚动条看不到
  • CSS3 display:table, overflow-y:scroll doesn't work

父节点 min-heigh, 子节点百分比 heigh 无效

  • Fix
    1. parent 添加 height:1px;
    2. parent flex flex-col, child flex-1
    3. 如果 parent 的 min-heigh 是数值而非百分比,child 使用 min-height: inherit; 也可以
<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

html, body { height: 100%; margin: 0; } #parent { min-height: 100%; background: pink; } #child { height: 100%;
background: aqua; }

<!-- language: lang-html -->

<div id="parent">
<div id="child">Hello World!</div>
</div>

<!-- end snippet -->

Scroll Snap

https://web.dev/snap-after-layout/

https://caniuse.com/#feat=css-snappoints https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap

https://codepen.io/argyleink/pen/RwPWqKe

@supports (scroll-snap-type: y mandatory) {
.scroll-container {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}

section {
height: 100vh;
scroll-snap-align: center;
}
}

scrollbar

iPhone X 页面内容 padding

  1. CSS 控制
body {
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
  1. viewport-fit=cover
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
/>

css env

:root {
--sat: env(safe-area-inset-top);
--sar: env(safe-area-inset-right);
--sab: env(safe-area-inset-bottom);
--sal: env(safe-area-inset-left);
}
getComputedStyle(document.documentElement).getPropertyValue('--sat');
/* 常见 */
body {
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

font size 适应容器

  1. SVG
<svg viewBox="0 0 56 18">
<text x="0" y="15">Fit Me</text>
</svg>
  1. 外部依赖

性能

margin or not

breakpoint

ChromeWidth
Mobile S320px
Mobile M375px
Mobile L435px
Tablet768px
Laptop1024px
Laptop L1400px
4k2560px
  • min-width - 移动端优先的设计方式
breakpointtailwindbootstrapmui
sm640px576px600px
md768px768px900px
lg1024px992px1200px
xl1280px1200px1536px
2xl,xxl1536px1400px

buma

breakpointbuma
mobile< 768px
tablet>= 768px
desktop>= 1024px
widescreen>= 1216px
fullhd>= 1408px

md 2

sizedevicecolumn
0-599phone4
600-904tablet8
905-1239tablet12
1240-1439labtop12
1440+desktop12

gradient

scroll shadow

Defensive CSS

.flex {
display: flex;
flex-wrap: wrap; /* defensive */
}

img {
object-fit: cover;
}

.long-content {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.spacing {
margin-right: 1rem;
}

.wrapper {
--sizing: auto-fit; /* auto-fill */
display: grid;
grid-template-columns: repeat(var(--sizing), minmax(100px, 1fr));
grid-gap: 1rem;
}

.bg {
background-image: url('..');
background-repeat: no-repeat; /* defensive */
}

.card__title {
overflow-wrap: break-word;
min-width: 0;
}
.modal__body {
overscroll-behavior-y: contain; /*避免 parent 滚动*/
overflow-y: auto;
}
.element {
scrollbar-gutter: stable; /* 避免滚动条出现导致错位 */
}

/* https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover */
@media (hover: hover) {
.card:hover {
/* 避免移动设备 hover */
}
}

table pin column

  1. 使用 div 重新实现 table
  2. position: sticky
  • 需要计算偏移位置
  1. 使用 border-collapse: separate + border-spacing: 0
  • tailwindcss border-separate border-spacing-0

获取所有 CSS 变量

Array.from(document.styleSheets)
.filter((sheet) => sheet.href === null || sheet.href.startsWith(window.location.origin))
.reduce(
(acc, sheet) =>
(acc = [
...acc,
...Array.from(sheet.cssRules).reduce(
(def, rule) =>
(def =
rule.selectorText === ':root'
? [...def, ...Array.from(rule.style).filter((name) => name.startsWith('--'))]
: def),
[],
),
]),
[],
);

text-stroke

text outline, text border

inline flex + flex warp 导致换行

  • 使用 display:contents, 让元素作为 parent 的 children