Fullstack 面试复习笔记:HTML / CSS 基础梳理

发布于:2025-06-08 ⋅ 阅读:(18) ⋅ 点赞:(0)

Fullstack 面试复习笔记:HTML / CSS 基础梳理

之前的笔记:

本来是想把H5C3JS的东西放一起整理的,然后看了下有点长……

毕竟主自用,还是先拆开来方便自己复习了

HTML 基础

meta tag

<meta> tag 是 HTML 中用于提供页面元数据(metadata)的标签,它不会直接显示在页面中,但会被浏览器、搜索引擎、社交平台等工具读取。

常见用途包括:

  • 设置字符编码(charset)

  • 控制 viewport(响应式布局)

  • 设置 SEO 信息(如 description, keywords)

  • 定义页面作者

  • 配置浏览器行为(如 http-equiv

  • 常见的 <meta> & 用法

    <!-- 设置字符编码,防止乱码问题 -->
    <meta charset="UTF-8" />
    
    <!-- 响应式设计,配合 viewport 缩放行为 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    
    <!-- SEO:定义页面描述 -->
    <meta name="description" content="A lightweight e-commerce site built with React and Node.js" />
    
    <!-- SEO:定义关键字(现在搜索引擎不怎么用)-->
    <meta name="keywords" content="React, Node.js, MongoDB, E-commerce" />
    
    <!-- 定义作者 -->
    <meta name="author" content="Louise Han" />
    
    <!-- 控制缓存策略 -->
    <meta http-equiv="cache-control" content="no-cache" />
    

semantic syntax

Semantic tags 是指那些 带有语义(semantic meaning) 的 HTML 标签,它们告诉浏览器、开发者和 assistive technology(如 screen reader)“这块内容的作用是什么”。

  • 常见的语义标签

    标签 用途说明 释义
    <header> 页面或 section 的头部区域 页眉区域
    <nav> 网站导航栏 导航栏
    <main> 页面主内容,唯一出现一次 主体内容
    <section> 拥有独立主题的一块内容 内容区块
    <article> 独立的文章、博文、论坛贴文等 独立内容
    <aside> 与主内容相关但不直接相关的信息(如侧边栏) 侧边信息
    <footer> 页面或 section 的底部区域 页脚
    <figure> / <figcaption> 图像 + 图说 图片配文
    <time> 时间元素,可被机器读取 机器可识别的时间
    <mark> 高亮文本 高亮词汇(搜索匹配)
  • 为什么使用 Semantic Tags

    • 对搜索引擎友好(Better SEO
    • 对 screen reader 更友好(提升 Accessibility
    • 可读性提升,便于团队协作和维护
    • 明确结构,有助于浏览器默认样式渲染(如 <nav> 默认有焦点样式)

常见 input type

  • text:单行文本输入(默认类型)

  • password:密码输入,用户输入内容会以圆点/星号显示

  • email:必须为邮箱格式,会启用浏览器校验

  • url:必须为合法的 URL(浏览器校验)

  • number:只能输入数字,可配合 minmaxstep

  • tel:电话号码输入,不会强制格式校验,但移动端会弹出数字键盘

  • search:语义上表示搜索,功能上类似 text,可提供清除按钮(某些浏览器)

  • date:选择日期(浏览器弹出日期选择器)

  • time:选择时间

  • datetime-local:选择本地时间和日期

  • month:选择月份

  • week:选择第几周

  • checkbox:复选框,可多选,值为 true / false

  • radio:单选按钮(需要 name 相同才能形成互斥组)

  • range:滑动条(可配合 min/max/step)

  • file:文件上传,accept 可限定类型

  • color:颜色选择器,返回 HEX 色值

  • hidden:隐藏字段(不显示在页面上,但提交时会包含)

    可以传递包括用户id、CSRF Token之类的字段

    注意不要放敏感信息,毕竟还是可以被JS所访问的

datalist vs options

特性 <datalist> + <input> <select> + <option>
是否可自由输入 ✅ Yes(可选或自填) ❌ No(只能选择)
外观可定制性 基于 <input>,可定制性高 原生样式难以改造
表单提交值 仅提交 <input> 的值 提交 <select> 的选中值
使用场景 搜索框、模糊匹配、辅助推荐 下拉菜单、选项限定

datalist的用法:

<label for="browser">Choose your browser:</label>
<input list="browsers" name="browser" id="browser">

<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Safari">
  <option value="Edge">
</datalist>

select+options的用法:

<select name="fruit">
  <option value="apple">Apple</option>
  <option value="banana">Banana</option>
  <option value="mango" selected>Mango</option>
</select>

form vs div

维度 <form> <div>
语义(Semantics) 表示“表单提交区域” — 属于结构语义标签之一 没有语义,只是一个容器
默认行为 提交时会触发表单事件、支持 submit 操作 不会自动触发提交行为
可访问性支持 默认被 Assistive Technology 识别为表单 屏幕阅读器不会当做表单处理
事件行为支持 可监听 onSubmit 事件 没有 submit 行为
可与按钮协作 <button type="submit"> 可直接触发表单提交 必须手动添加 JS 才能模拟提交
浏览器原生校验 支持如 requiredpattern 等自动校验 不支持,需要自己写 JavaScript 校验逻辑

标签嵌套规则 & DOM 结构

HTML 并不是可以随意嵌套标签的语言,浏览器会根据 HTML 规范对结构做自动修正。如果标签嵌套不当,可能会出现异常、访问性问题,和语义化校验失败

  • 基础语义分类

    分类 示例标签 描述说明
    Metadata content <title>, <style>, <meta> 用于页面 <head> 内,定义页面元信息
    Flow content 绝大多数标签(如 <div>, <p>, <ul> 通常可出现在 <body> 内的所有内容
    Sectioning content <section>, <article>, <nav>, <aside> 定义页面结构和内容区块,具有 outline 层级意义
    Heading content <h1><h6> 用于标识内容标题,必须嵌套在 Sectioning Content 中
    Phrasing content <span>, <a>, <strong>, <img> 行内文本及格式化元素,用于构成段落内部的细节内容
    Embedded content <iframe>, <img>, <video> 嵌入其他资源的标签
    Interactive content <a>, <button>, <details> 具备交互能力的元素,不应彼此嵌套
    Form-associated content <input>, <textarea>, <form> 与表单行为有关的控件或容器
    List content <ul>, <ol>, <li> 有序或无序列表
  • 通用嵌套规则

    外层元素语义类型 可嵌套的内容类型 不合法的内容类型(应避免) 备注 / 举例
    Sectioning content Flow content、Heading content Metadata content <article><h2>Title</h2><p>text</p></article>
    Heading content Phrasing content Block-level content(如 <div>, <p> <h1><em>Title</em></h1>
    Flow content Sectioning、Heading、Phrasing、Embedded、Interactive Metadata content 几乎可嵌套任何主体内容
    Phrasing content 其他 phrasing content(span、a、strong) Block-level content <p><span>hello</span></p>
    List container (<ul> / <ol>) <li>(唯一直接子元素) <div>、直接文本、其他 block(除非包裹在 <li> 中) <ul><div>错</div></ul><ul><li><div>合法</div></li></ul>
    <li> 元素 Flow content(包括 p、div、a、ul) 仅 metadata <li><p>Item</p></li>
    <form> 元素 Flow content、Form-associated content(不能嵌套 <form> <form> <form><input /></form> ✅❌ <form><form>错</form></form>
    <p> 元素 Phrasing content Block-level content(div、ul、table) <p><strong>Yes</strong></p> ✅❌ <p><div>No</div></p>
    Interactive content(a, button) Phrasing(text、span、img) 其他 interactive(a、button) <a><button>错误</button></a><button><span>确定</span></button>
  • 一些个人的总结 & 反思

    • span 不是一定要嵌套在 p 里使用

      span 负责的还是段落内做标记使用,只不过大多数情况下这个段落直译成了 paragraph,也就是 p 标签。不过从其他的UI库中也可以看到,不少的UI库直接使用 span 做样式——比如说封装成button

    • 交互元素之间的嵌套

      其实之前没注意到这个问题,一直到写React的时候碰到了,就是 a 标签 → 由 React Router DOM 提供的 Linkbutton 嵌套的时候出现了问题,就是重定向不工作

      找了一下才发现,HTML规定了交互元素(interactive content)不能互相嵌套,否则会发生不可预期的问题,在我当时的情况下就是重定向失败,点击没有任何的反应

      React本身是不会修正这种问题的,所以实现的时候还是需要注意一下……本地没有报错是运气好,特别是现在本地开发环境React会渲染两次,这个情况确实mask了很多问题。上了production再出现问题就糟糕了……

表单标签进阶

对于 labelfieldsetlegend 这些 表单进阶标签,它们主要起的是结构化和可访问性(accessibility)优化的作用,只需要熟悉它们的作用和用法场景即可

  • <label>

    • 作用:用于描述表单控件的含义(文本说明)

    • 常用写法:

      <label for="username">Username</label>
      <input type="text" id="username" />
      
      <label>
        Username
        <input type="text" />
      </label>
      
    • 优势:

      • 点击 label 可以自动聚焦对应 input
      • 提升可访问性(屏幕阅读器友好)
  • <fieldset>

    • 作用:将多个表单控件逻辑分组,用于视觉区块化和辅助语义划分

    • 使用场景:例如“个人信息”、“支付方式”这样的分块区域

    • 通常搭配 <legend> 使用

    • 示例:

      <fieldset>
        <legend>Personal Info</legend>
        <label for="name">Name:</label>
        <input id="name" type="text" />
        <label for="age">Age:</label>
        <input id="age" type="number" />
      </fieldset>
      
  • <legend>

    • 作用:为 <fieldset> 提供标题说明,是视觉和语义上的「小标题」
    • 注意事项:
      • <legend> 只能直接作为 <fieldset> 的第一个子元素出现
      • 不建议单独使用 <legend>,它没有独立语义意义

Accessibility (A11Y)

Accessibility(可访问性)指的是:**确保网页内容对所有用户都可用,包括视障、听障或行动不便的用户;**常见实践不仅提升用户体验,也有助于 SEO

  • 核心目标

    • 页面结构 语义清晰,便于辅助技术(如屏幕阅读器)识别
    • 所有交互元素都能被 键盘导航
    • 提供 文字替代(alt text) 以支持非视觉用户
    • 使用合适的ARIA 属性增强语义(仅在 HTML 不够时使用)
  • 实用标签

    标签 功能
    label 关联表单元素,提升 screen reader 识别准确性
    fieldset + legend 对表单区域进行语义分组和说明
    button 明确的交互控件,优于滥用 <div> / <a>
    a(超链接) 应该有明确 href,避免仅作按钮用
    nav, header, main, footer 结构语义清晰,有助 assistive tech 理解页面
    alt(图片说明) img 提供描述内容或说明装饰性(如 alt=""
  • 推荐实现

    • 为所有图片添加 alt 描述
    • 使用语义化 HTML 结构
    • 交互元素需可用键盘访问
      • 使用 <button><input> 等原生可交互元素
      • 避免用 <div> 模拟点击(无法 tab focus)
      • 如必须自定义组件,添加 tabindex="0"role="button"
    • 添加 Skip to Content 跳转锚点(推荐大项目)
  • ARIA(Accessible Rich Internet Applications)

    ARIA 是补充机制,优先使用原生语义标签

    ARIA的使用方式包括:

    属性 用途
    aria-label 给元素添加可识别名称
    aria-hidden="true" 隐藏不重要的视觉装饰元素
    role 补充 HTML 结构中缺失的语义,例如 role="dialog"
    aria-live 通知 screen reader 某区域内容动态更新

HTML 加载顺序与性能

浏览器加载顺序是 HTML → CSS → JS,即:

  • 自上而下解析 HTML
  • 遇到 <link rel="stylesheet">阻塞渲染(必须等待 CSS 下载 & 解析)
  • 遇到 <script> (无 async/ defer):阻塞解析(必须等待 JS 执行完,才继续解析 HTML)
    • JS前如果有CSS文件,并且CSS尚未加载完毕,那么JS会等到CSS加载完成后再执行

    • 因此传统做法——在 defer 未出现时——是将JS放到 <body> 最底部,让HTML先完成解析,渲染部分UI

      现代开发则是通过使用 defer + 将 script 放在 <head>,配合模块化打包(vite/webpack)实现更好的加载性能与维护行

    • <script> 加载方式对比

      属性 是否阻塞 HTML 解析 执行时机 执行顺序 使用场景
      默认 ✅ 阻塞 下载完立即执行 顺序执行 样板页 script、页面逻辑入口
      async ❓ 不完全阻塞
      下载时不阻塞解析
      但是下载完成后,执行时会阻塞 下载完立即执行(⚠ 无顺序) ⚠️ 不保证顺序 独立脚本(如广告/统计脚本)
      defer ❌ 不阻塞 DOM 全解析后、DOMContentLoaded 前执行 顺序执行 页面初始化逻辑推荐使用
      preload ❌ 不执行,仅预取 N/A N/A 提前加载 JS,但需配合 <script>
  • 解析完成后,构建 DOM、CSSOM → 生成 Render Tree → 触发绘制 &布局

CSS 样式机制

CSS 选择器分类

类型 示例 说明 Specificity 权重
通配选择器 * 匹配所有元素 0,0,0,0
元素选择器(Element) div, p, a 匹配特定标签 0,0,0,1
类选择器(Class) .card, .active 匹配指定 class 的元素 0,0,1,0
属性选择器(Attribute) [type="text"] 匹配指定属性的元素 0,0,1,0
伪类选择器(Pseudo-class) :hover, :nth-child(2) 选择特定状态 0,0,1,0
ID 选择器(ID) #header, #app 匹配特定 ID 的元素 0,1,0,0
伪元素(Pseudo-element) ::before, ::after 针对元素插入虚拟节点 0,0,0,1(同元素选择器)
组合选择器(Combinator) div .title, ul > li 父子/兄弟等嵌套结构 权重相加(逐个计算)
优先权最高:内联样式 style="color: red;" 直接写在元素上 1,0,0,0(最高)
!important(特例) color: red !important 不属于 specificity,但强制优先 会覆盖正常权重规则(除非被另一条更强的 !important 覆盖)

CSS Specificity 是 4 维度权重,记作 a,b,c,d

  • a:是否为内联样式 → 1,0,0,0
  • b:ID 选择器数量
  • c:Class、属性、伪类
  • d:标签选择器、伪元素

box model

Box Model 是 HTML 元素在页面中所占空间的数学模型。

每个元素都可以看作一个矩形盒子,由以下几部分组成:

  (Outline - 不占空间)
+---------------------------+
|         Margin            |
|  +---------------------+  |
|  |      Border         |  |
|  |  +---------------+  |  |
|  |  |   Padding     |  |  |
|  |  |  +--------+   |  |  |
|  |  |  | Content |   |  |  |
|  |  |  +--------+   |  |  |
|  |  +---------------+  |  |
|  +---------------------+  |
+---------------------------+

层级 是否占据空间 描述说明
outline ❌ 否 仅视觉效果,不影响布局,常用于焦点提示
margin ✅ 是 元素与外部元素的距离
border ✅ 是 包裹 padding + content 的边线
padding ✅ 是 内容与边框之间的内边距
content ✅ 是 实际显示文本/图片的区域
  • 标准盒模型(content-box)→ 默认

    width 为 content的宽度,所以计算的时候需要通过 c o n t e n t + p a d d i n g + b o r d e r content + padding + border content+padding+border 的方式去计算

  • 替代盒模型(border-box)→ 推荐

    width c o n t e n t + p a d d i n g + b o r d e r content + padding + border content+padding+border 的宽度,即元素的整体宽度,计算起来相对省心

    也是现代CSS框架的默认计算方式

display

display 定义了元素的布局行为,是 CSS 中最基础也最重要的属性之一。它决定了元素如何参与文档流以及是否能成为容器

属性值 说明
block 块级元素,占满整行,可设置宽高(如 <div>
inline 行内元素,不可设置宽高(如 <span>
inline-block 兼具行内与块级特性,可并排也可设置宽高
none 元素隐藏且不参与渲染,不占据空间
flex 启用 Flex 一维弹性布局容器
inline-flex 行内弹性容器,可与文字并排显示
grid 启用 Grid 二维网格布局容器
inline-grid 行内网格容器
table 模拟表格布局行为
contents 不渲染元素自身,只保留子元素结构(⚠ 有兼容性问题)
list-item 元素表现为列表项,通常带有 符号

常见场景推荐:

  • 页面区域布局 → 推荐使用 flexgrid
  • 水平排布多个组件 → 使用 inline-blockflex
  • 条件渲染 → 用 display: none 控制显示与隐藏

position 定位机制

position 定义元素脱离文档流的方式,影响其在页面中的位置计算方式

属性值 说明
static 默认值,按照文档流正常排列
relative 相对自身原位置偏移,可配合 top/right/bottom/left 使用
absolute 相对最近的非 static父元素定位,脱离文档流
fixed 相对于 视口(viewport) 定位,常用于吸顶、悬浮按钮
sticky 在滚动时在 relativefixed 之间切换,实现“粘性”效果

配套偏移属性(仅 relative / absolute / fixed / sticky 有效):


top: 10px;
left: 20px;
right: 0;
bottom: auto;

注意:

  • absolute 必须有明确定位上下文,否则会相对 body 定位
  • fixed 不随滚动条滚动,适合做悬浮按钮
  • sticky 需要设置 top 或其他边界,且外层容器不能有 overflow: hidden

实用技巧:

  • 经典居中方法:

    .centered {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
  • 粘性标题栏:

    header {
      position: sticky;
      top: 0;
      background: white;
    }
    

column layout

允许将一个元素的内容分成多个列,类似报纸排版

核心属性包括:

属性名 说明
column-count 指定列的个数
column-width 指定每列的理想宽度(浏览器会根据实际情况调整)
columns 简写形式:columns: column-width column-count;
column-gap 列与列之间的间隙(默认 1em
column-rule 列之间的分隔线(包含宽度、样式、颜色)
break-inside 控制子元素是否可中断换列(避免被拆开)

它的限制与注意事项:

特点 说明
❌ 支持不如 Flex/Grid 丰富 无法灵活控制每列内容的对齐、分布
❌ 不支持嵌套列 嵌套结构时可能会失效或排版错乱
✅ 非常适合内容流排版 如长文本、段落内容、简报式展示

flex layout

Flex 是一种一维布局系统,擅长处理 主轴方向的对齐、伸缩、排序等问题。核心概念是容器(flex container)和项目(flex item)

  • 启用flex的方法比较简单,将 display改成flex即可:

    .container {
      display: flex;        /* 或 inline-flex */
    }
    

    这样所有的自元素都自动成为flex item

  • 主轴方向控制使用 flex-direction:

    .container {
      flex-direction: row | row-reverse | column | column-reverse;
    }
    
  • 换行控制使用 flex-wrap:

    .container {
      flex-wrap: nowrap | wrap | wrap-reverse;
    }
    
  • 主轴对齐:justify-content

    .container {
      justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
    }
    
  • 交叉轴对齐使用 align-items:

    .container {
      align-items: stretch | flex-start | flex-end | center | baseline;
    }
    

    现在比较流行的一种水平/垂直的实现方法,就是使用 justify-content + align-items 实现的

  • 多行对齐:align-content

    .container {
      align-content: stretch | flex-start | flex-end | center | space-between | space-around;
    }
    
  • 子项控制:flex 简写

    .item {
      flex: [flex-grow] [flex-shrink] [flex-basis];
    }
    
  • 子项对齐(覆盖 align-items):align-self

    .item {
      align-self: auto | flex-start | flex-end | center | baseline | stretch;
    }
    
  • 间距控制:gap

    .container {
      gap: 1rem;             /* 行列统一间距 */
      row-gap: 10px;         /* 仅行间距 */
      column-gap: 20px;      /* 仅列间距 */
    }
    

grid layout

Grid 是一种 二维布局系统,适合处理复杂网格、区域布局等需求。与 Flex 不同,Grid 可以同时控制行(row)和列(column)

  • 启用 Grid 布局

    .container {
      display: grid;          /* 或 inline-grid */
    }
    
  • 定义网格行与列

    .container {
      grid-template-columns: 100px 1fr 2fr;    /* 列宽 */
      grid-template-rows: auto 50px;           /* 行高 */
    }
    
  • 设置间距:gap

    .container {
      gap: 10px;             /* 同时设置行列间距 */
      row-gap: 10px;
      column-gap: 20px;
    }
    
  • 放置子项:行列定位

    .item {
      grid-column: 1 / 3;    /* 第1列开始到第3列前结束(跨2列) */
      grid-row: 2 / span 2;  /* 从第2行开始,跨2行 */
    }
    
  • 命名区域(推荐)

    .container {
      grid-template-areas:
        "header header"
        "sidebar main"
        "footer footer";
    }
    
    .item-header {
      grid-area: header;
    }
    
  • 自动排列:auto-fillauto-fit

    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    
  • 对齐内容

    .container {
      justify-items: start | center | end;
      align-items: start | center | end;
    }
    
    

column vs flex vs grid

特性 Column Layout Flexbox Grid
排版方式 垂直分栏 一维(行或列) 二维(行 + 列)
控制力 ⭐️ 中等 ⭐️⭐️⭐️ 强 ⭐️⭐️⭐️⭐️ 最强
内容流动 自动分流 子项自己布局 显式定义区域
使用场景 报纸式文本 UI组件对齐 页面布局骨架

响应式布局&媒体查询

响应式设计是指页面可以根据不同屏幕尺寸、分辨率和设备特性自动调整布局与样式,从而提供良好用户体验的一种设计理念

  • 核心目标

    • 同一个 HTML 页面,适配不同设备(手机、平板、桌面)
    • 自动调整布局、字号、边距、组件显示/隐藏等
    • 避免内容“溢出”或“太小看不清”
  • 实现方法

    主要通过media query去做,基础的模板代码为:

    @media <媒体类型> and (<条件>) {
      /* 只在满足该条件下才生效 */
    }
    

    如:

    /* 屏幕宽度小于等于 768px(平板及以下) */
    @media (max-width: 768px) {
      .sidebar {
        display: none;
      }
    }
    
    /* 屏幕宽度大于等于 1024px(桌面端) */
    @media (min-width: 1024px) {
      body {
        font-size: 16px;
      }
    }
    
  • 常用断点

    断点类型 宽度范围(参考值) 用途
    Extra small (xs) < 576px 手机竖屏
    Small (sm) ≥ 576px 手机横屏
    Medium (md) ≥ 768px 平板设备
    Large (lg) ≥ 992px 小型桌面
    Extra large (xl) ≥ 1200px 常规桌面
    XXL (xxl) ≥ 1400px 大屏显示器
  • 响应式单位 &技巧补充

    单位 说明
    % 相对于父元素的宽/高
    vw 视口宽度的百分比(100vw = 屏幕宽)
    vh 视口高度的百分比(100vh = 屏幕高)
    em/rem 字体相对单位,适用于字号随屏幕变小自动缩放
    clamp() 设定最小、推荐值、最大值,实现响应式字体大小:clamp(14px, 2vw, 18px)
  • 响应式布局技巧

    • 使用 flex-wrap: wrap 或 Grid 布局 + auto-fit

    • 使用 gap 代替传统 margin-right/padding

    • 合理隐藏某些组件:

      @media (max-width: 768px) {
        .menu-sidebar {
          display: none;
        }
      }
      
    • 用容器类限制最大宽度(如 max-width: 1200px; margin: 0 auto;

  • Mobile First

    目前responsive design的主流策略,核心理念是从小屏幕(如手机)出发设计 UI,再逐步为大屏幕添加增强样式

    这种设计用 max-width 更加的合适,反之,如果从 desktop first 则用 min-width

BEM 命名

BEM 是一种 结构化命名规范,用于让 CSS 类名清晰表达组件结构与状态,便于维护、避免冲突

部分 描述 示例
Block 独立的功能模块(可以单独复用) card, nav, form
Element Block 内部的组成部分 card__title, nav__item
Modifier 表示 Block 或 Element 的状态 / 变体 card--highlighted, button--disabled

如:

/* Block */
.button {}

/* Element:使用两个下划线 */
.button__icon {}

/* Modifier:使用两个连字符 */
.button--primary {}
.button__icon--large {}

一般来说用BEM的话,写原生CSS比较多,或者是需要构建比较大的UI库这种情况,我们项目的话,因为有自己的UIF(UI Framework),所以反而会比较多的依赖UIF的实现,有需要重在的情况BEM也帮不上什么忙,就用JSX里的inline css搞定了

SCSS/SASS 简述

底层编译器相同:两者都使用 Dart Sass(现在是官方唯一支持的实现),不过实现的格式有些许的不同:

特性 SASS (.sass) SCSS (.scss)
语法风格 缩进式(无大括号、分号) 类似 CSS(用大括号和分号)
可读性 更简洁,偏向 Ruby 风格 更接近原生 CSS,学习曲线低
支持程度 老项目可能使用 新项目主流使用
推荐程度 可选(老项目或喜欢极简) ✅ 推荐(兼容性、迁移、团队协作)
  • 变量定义

    $primary-color: #3498db;
    
    .button {
      background: $primary-color;
    }
    
  • 嵌套规则(Nested Rules)

    .navbar {
      ul {
        list-style: none;
      }
    
      li {
        display: inline-block;
      }
    }
    
  • Mixin(类似函数,可传参)

    @mixin flex-center {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .container {
      @include flex-center;
    }
    
  • Extend(继承已有样式)

    %base-button {
      padding: 0.5rem 1rem;
      border-radius: 4px;
    }
    
    .btn-primary {
      @extend %base-button;
      background-color: blue;
    }
    
  • 条件和循环(Control Directives)

    $themes: light, dark, blue;
    
    @each $theme in $themes {
      .theme-#{$theme} {
        // 动态类名
      }
    }
    

过渡

元素状态变更时的过渡,一般与 :hover:focus 等伪类配合使用,如:

.button {
  transition: all 0.3s ease-in-out;
}

.button:hover {
  transform: scale(1.05);
}

具体结构为:

transition: <property> <duration> <timing-function> <delay>;

动画

animation:关键帧动画(更复杂),使用方法如下:

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card {
  animation: fade-in 0.6s ease forwards;
}

具体结构为:

animation: <name> <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode>;

常见参数:

  • infinite:无限循环
  • alternate:来回动画
  • forwards:保留最后状态(常用!)

animation vs. transition

transition animation
用途 简单状态切换(如 hover) 复杂序列动画
触发方式 被动(如鼠标 hover) 可自动播放(无须交互)
控制方式 仅开始状态和结束状态 多帧(keyframes)
写法复杂度 中高

视觉可访问性 Visual Accessibility

  • 重要性:

    • WCAG(Web Content Accessibility Guidelines)明确要求视觉元素满足对比和聚焦可见性要求
    • 企业级产品(尤其 B2B/Gov)经常要通过 A11y 审核
    • Tailwind / Chakra / MUI 等现代框架已经内建
  • 颜色对比 color contrast

    元素类型 最低对比度比值
    正文文字 4.5:1
    粗体大文字(≥18px bold / 24px regular) 3:1
    UI 组件边界(如按钮边框) 通常建议 ≥ 3:1

    检查工具包括:

    • WebAIM Contrast Checker
    • Figma 的 A11y 插件
    • VS Code 插件:WCAG Color Contrast Checker
  • 焦点可见性 focus outline

    目标用户:键盘用户(Tab键导航者)、辅助技术用户

    推荐实现方法:

    button:focus,
    a:focus {
      outline: 2px solid #2684FF;
      outline-offset: 2px;
    }
    
    • outline: 视觉边框,不占空间,适合可访问性标示
    • outline-offset: 将 outline 往外或内偏移,不会遮住按钮内容
    • ⚠️ 如果用了 outline: none必须自己补上焦点状态的视觉标识(如 box-shadowborder 等),否则违反可访问性规范
  • 图片与alt文字,之前提过

  • 可感知的状态变化(Visible State Change)

    仅靠颜色可能不太明确,正确方法推荐:

    **<input type="email" aria-invalid="true" />
    <span class="error">邮箱格式不正确</span>**
    

    这个应该是针对色盲/色弱做的优化

  • 深色模式支持 Dark Mode Support

    属于现代设计中的视觉舒适性优化,对于光敏感用户尤为关键

  • 字体大小 / 可缩放性(Zoom & Font Size)

    页面应支持最高到 200% 的缩放,仍能正常操作和阅读

    那……很多网页应该是做不到的……

  • 认知可访问性(Cognitive Accessibility)

    • 避免使用动图、闪烁图像(容易引发癫痫/认知负担)
    • 避免使用过多动画(结合 prefers-reduced-motion
    • 保持按钮文本明确(如“提交表单”比“点我一下”更清晰)