HTML + CSS

30 阅读13分钟

1. 如何理解HTML中的语义化标签

  • 在合适的地方使用合适的标签
  • 使用语义化的优点
    • 代码结构清晰,方便阅读,有利于团队合作开发
    • 方便其他设备解析(如盲人阅读器)以语义的方式来渲染网页
    • 有利于搜索引擎优化(SEO)
  • 常见的语义化标签
    • header/nav/article/section/aside/footer

2. HTML5有哪些新标签

  • article --- 表示文章、博客条目
  • nav --- 定义导航链接的部分
  • header --- 定义文档的页眉
  • video --- 定义视频
  • audio --- 定义声音
  • canvas --- 用来定义图形容器,必须使用脚本来绘制图形

3. Canvas和SVG的区别是什么

  • 简介
    • Canvas是HTML5新出的标签,Canvas是画布,利用JavaScript在网页绘制图像
    • SVG是可缩放矢量图
  • 绘制的图形格式不同
    • Canvas的工具getContext绘制出来的图形或传入的图形都依赖分辨率,能够以.png和.jpg格式保存存储图像,可以说是位图
    • SVG可以在H5中直接绘制,但绘制的是矢量图
    • 位图依赖分辨率,矢量图不依赖分辨率
  • Canvas不支持事件处理器,SVG支持事件处理器
    • Canvas绘制的图像都在Canvas这个画布里面,是Canvas的一部分,不能用JavaScript获取已经绘制好的图形元素
    • SVG绘图时,每个图形都是以DOM节点的形式插入到页面中,可以用JavaScript或者其他方法直接操作
  • 适用范围不同
    • Canvas是逐像素进行渲染的,一旦图形绘制完成,就不会继续被浏览器关注
    • SVG是通过DOM元素来显示的
    • SVG适合带有大量渲染区的应用程序,比如地图;而Canvas适合有许多对象要被频繁重绘的图形密集型游戏

4. BFC

  • block format context(块级格式化上下文)
    • 是页面的一块渲染区域,并且有一套渲染规则,决定了子元素如何定位,以及与其他元素之间的排列、布局之间的关系
    • BFC是一个独立的布局环境,相当于一个容器,在其中按照一定的规则对块级元素进行摆放,并且不会影响其他布局环境中的盒子,如果一个元素触发了BFC则BFC中的元素不受外界的影响
  • 块级元素在标准流中的布局是属于BFC的
  • 特点
    • 垂直方向上,自上而下排布
    • 垂直方向的间距由margin决定
    • 同一个BFC中,盒子之间的margin会折叠
    • BFC中,每个元素的左边缘紧挨着包含块的左边缘
    • 计算BFC高度时,需要计算浮动元素的高度
    • BFC内部不会影响外部元素
    • BFC区域不会与浮动的元素发生重叠
  • 创建BFC的条件
    • display: flex/inline-block/grid
    • float: left/right
    • position: absolute/fixed
    • overflow: auto
  • 作用
    • 解决margin折叠问题
    • 解决高度塌陷问题
    • 可以设置两栏布局(左边float: left/右边overflow: hidden)

5. 水平居中和垂直居中

  • 水平居中
    • text-align: center;
    • position: relative; left: 50%; transform: translateX(-50%);
    • width: 200px; height: 200px; position: absolute; left: 0; right: 0; margin: 0 auto;
    • display: flex: justify-content: center;
  • 垂直居中
    • line-height
    • position: relative; top: 50%; transform: translateY(-50%);
    • width: 200px; height: 200px; position: absolute; top: 0; bottom: 0; margin: auto 0;
    • display: flex; align-items: center;

6. 清除浮动

  • display: block; content: ""; clear: both;

7. 盒子模型

  • box-sizing: content-box
    • content
  • box-sizing: border-box
    • content + padding + border

8. flex布局

  • flex-container
    • flex-direction --- row/row-reverse/column/columb-reverse
    • flex-nowrap --- wrap/nowrap/wrap-reverse
    • flex-flow
    • justify-content --- flex-start/flex-end/cneter/space-between/space-around/space-evenly
    • align-items --- normal/stretch/flex-start/flex-end/center/baseline
    • align-content --- flex-start/flex-end/center/space-between/space-around/space-evenly
  • flex-items
    • flex-shrink
    • flex-grow
    • flex-basic
    • flex
    • align-self
    • order

9. 回流、重绘

  • 网页的解析过程
    • 浏览器输入域名
    • 域名(DNS)解析,获取IP地址
    • 根据IP地址找到对应的服务器
    • 服务器返回对应的资源
  • 浏览器渲染页面的过程
    • HTML解析
      • 默认情况下,服务器会给浏览器返回index.html文件,所以解析HTML文件是所有步骤的开始
      • 解析HTML,会生成DOM Tree
    • 生成CSS规则
      • 解析过程中,如果遇到CSS的link元素,那么会由浏览器负责下载对应的CSS文件(下载CSS文件不会影响DOM的解析)
      • 浏览器下载完CSS文件后,就会对CSS文件进行解析,生成CSSOM Tree
    • 构建Render Tree
      • 当有了DOM Tree和CSSOM Tree后,就可以两个结合起来构建Render Tree
      • Link元素不会阻塞DOM Tree的构建过程,但是会阻塞Render Tree的构建过程
      • Render Tree和DOM Tree不是一一对应的关系
    • 布局
      • 在Render Tree的基础上进行布局(Layout)以计算每个节点的几何体
      • 渲染树会显示哪些节点以及其他的样式,但是不展示每个节点的尺寸、位置等信息
      • 布局是确定呈现树中所有节点的宽度、高度、尺寸位置
    • 绘制
      • 在绘制节点时,浏览器将布局节点计算的每个frame转为屏幕上实际的像素点
      • 包括将元素的可见部分进行绘制,比如文本、颜色、边框、阴影、替换元素
  • 回流(reflow)
    • 什么是回流
      • 第一次确定节点的大小和位置,称之为布局
      • 之后对节点的大小、位置修改重新计算,称之为回流
    • 什么情况下引起回流
      • DOM结构发生改变(节点的新增、删除)
      • 改变了布局(width、height等)
      • 窗口resize
      • 调用getComputedStyle方法获取尺寸、位置信息
  • 重绘
    • 什么是重绘
      • 第一次渲染内容称之为绘制
      • 之后重新渲染称之为重绘
    • 什么情况下会引起重绘
      • 比如修改背景色、文字颜色、边框颜色、样式等
      • 回流一定会引起重绘,所以回流是一件很消耗性能的事情
    • 如何避免回流
      • 修改样式尽量一次性修改
      • 尽量避免频繁操作DOM
      • 尽量避免使用getComputedStyle获取尺寸、位置
      • position

10. 元素不可见

  • display: none; ---- 脱离文档流,不占用空间,元素不可见
  • visibility: hidden; --- 不脱离文档流,占用空间,元素不可见,不可点击
  • opacity: 0; --- 不脱离文档流,占用空间,元素不可见,可以点击

11. 文本溢出省略号效果

/* 单行 */
p {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* 多行 */
p {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
    width: 600px;
}

12. transform/transition/animation

13. position元素定位

  • 标准流(position flow)
    • 默认情况下,元素按照标准流进行布局
    • 从左到右,从上到下;块级元素独占一行,行内级元素与其他行内级元素在一行显示
    • 在标准流中,margin、padding可以对元素进行定位,但是会影响其他元素;position也可以对元素进行定位,脱离了标准流
  • position
    • 允许从正常的文档流布局中取出元素
  • static
    • 静态定位,默认值
    • 不脱离标准流;不能用top/bottom/left/right进行定位
  • relative
    • 相对定位
    • 脱离标准流;可以用top/bottom/left/right进行定位,定位参照物是自己原来的位置
    • 应用场景:不影响其他元素,对当前元素进行微调
  • fixed
    • 固定定位
    • 脱离标准流:可以用top/bottom/left/right进行定位,定位参照物是视口
  • absolute
    • 绝对定位
    • 脱离标准流;可以用top/bottom/left/right进行定位,定位参照物事当前元素的定位祖先元素,如果没有定位祖先元素就是视口
  • sticky
    • 粘性定位

14. SEO

  • 什么是SEO
    • SEO就是搜索引擎优化,SEO通过了解搜索引擎的运行规则来调整网站,以提高网站的曝光度,以及网站的排名
  • SEO的关键点
    • 关键词分析
    • 网站架构分析
    • 网站目录和页面优化
    • 内容发布和链接布置
    • 与搜索引擎对话
    • 网站流量分析
  • 措施
    • 关键词优化
    • 合理的网站结构
    • 内部优化
    • 外部链接优化

15. defer/async

  • defer
    • 在<script>元素中设置defer属性,相当于告诉浏览器立即下载,但延迟执行
    • HTML5规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于DOMContentLoaded事件执行
    • 在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoaded事件出发前执行
    • 因此最好只包含一个延迟脚本
  • async
    • async只适用于外部脚本文件,并告诉浏览器立即下载文件
    • 并不保证按照它们的先后顺序执行
    • 因此确保两者之间互不依赖非常重要
    • 指定async属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容。
  • <script>标签
    • 一个普通的<script>标签的加载和解析都是同步的,会阻塞DOM的渲染,这也就是我们经常会把<script>写在<body>底部的原因之一
    • 为了防止加载资源而导致的长时间的白屏,另一个原因是js可能会进行DOM操作,所以我们要在DOM全部渲染完后再执行
  • defer和async在网络加载过程是一致的,都是异步执行的
  • 区别
    • 两者的区别在于脚本加载完成之后何时执行
    • 可以看出defer更符合大多数场景对应用脚本加载和执行的要求,如果存在多个有defer属性的脚本,那么它们是按照加载顺序执行脚本的
    • 而对于async,它的加载和执行是紧紧挨着的,无论声明顺序如何,只要加载完成就立刻执行,它对于应用脚本用处不大,因为它完全不考虑依赖

16. CSS3的新特性

  • 选择器
    • 属性选择器:[attr=value]
    • 伪类选择器::hover/:active
    • 伪元素选择器:::before/::after
    • 多重选择器:逗号分隔,element1,element2
  • 盒模型:box-sizing属性改变了默认的CSS盒模型,使其更容易进行布局
  • 盒阴影:box-shadow
  • 渐变:linear-gradient
  • 过渡:transition
  • 动画:@keyframes
  • 变形:transform
  • 多列布局:column-count/column-width
  • 媒体查询
  • 弹性盒子布局
  • 网格布局:grid
  • 过滤效果:filter

17. 物理像素、逻辑像素、像素密度

  • 物理像素
    • 物理像素是构成电子屏幕显示的基本单位,每个物理像素由屏幕内部的一个或一组发光元件组成,它们决定了屏幕显示的最小颗粒度。在不同设备上,物理像素的大小和间距可能不同
  • 逻辑像素
    • 逻辑像素是操作系统和浏览器用来计量屏幕尺寸和布局的基础单位,有时也称为设备独立像素或CSS像素
    • 在理想状态下,1个逻辑像素应该对应1个物理像素,但在高分辨率的屏幕上,为了保持良好的视觉效果,1个逻辑像素可能对应多个物理像素
  • 像素密度
    • 像素密度是指在一个屏幕区域内,每尺寸包含的物理像素数量。像素密度越高,意味着同样尺寸的屏幕可以容纳更多的像素,从而使得图像更加细腻清晰
  • @2x和@3x
    • 在移动端开发时,由于不同设备的屏幕尺寸、分辨率和像素密度差异很大,为了确保UI元素和图片在各种设备上都能正确显示且保持清晰,开发者通常会使用多种分辨率的图片资源
    • @2x和@3x图片资源是iOS和Android开发中常见的一种图片适配策略
    • @2x表示图片的实际像素是设计原图的一倍,适用于像素密度较高的屏幕,即一个逻辑像素对应两个物理像素
    • @3x则表示图片的像素是设计原图的三倍,对应于像素密度更高的屏幕,一个逻辑像素对应三个物理像素

18. 1px问题

  • 1px的问题
    • 在一些Retina屏幕的机型上,移动端页面的1px会变得很粗,呈现出不止1px的效果
    • 原因很简单是 CSS中的1px并不能和移动设备上的1px划等号
    • 它们之间的比例关系有一个专门的属性来描述:window.devicePixelRatio = 设备的物理像素 / CSS像素
  • 解决方法一:直接写0.5px
    <!-- 在JS中拿到window.devicePixelRatio的值,然后这个值通过JSX或者模板语法给到CSS的data里,达到这样的效果 -->
    <div id="container" data-device={window.devicePixelRatio}></div>
    <!-- 然后就可以在CSS中用属性选择器来命中devicePixelRatio的值为某一值的情况 -->
    #container[data-device="2"] {
        border: 0.5px solid #333;
    }
    
  • 解决方法二:伪元素先放大后缩小
    /* 在目标元素的后面追加一个::after伪元素,让这个元素布局为absolute之后、整个伸展开铺在目标元素上,然后把它的宽和高都设置为目标元素的两倍,border值设为1px。接着借助CSS动画特效中的防缩能力,把整个伪元素缩小为原来的50%。此时伪元素的宽高刚好和原有的目标元素堆砌,而border也缩小为了1px的1/2,间接的实现了0.5px的效果 */
    #container[data-device=“2”] {
        position: relative;
    }
    #container[data-device=“2”]::after {
        position: absolute;
        top: 0;
        left: 0;
        width: 200%;
        height: 200%;
        content: “”;
        transform: scale(0.5);
        transform-origin: left top;
        box-sizing: border-box;
        border: 1px solid #ccc;
    }
    
  • 解决方法三:viewport缩放来解决
    <meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
    <!-- 针对像素比为2的页面,把整个页面缩放为了原来的1/2大小。这样,本来占用2个物理像素的1px样式,现在占用的就是一个标准为例像素。-->
    <!-- 根据像素比的不同,这个缩放比例可以被计算为不同的值,用js代码实现如下:-->
    const scale = 1 / window.devicePixelRatio;
    <!-- 这里 metaEl 指的是 meta 标签对应的 Dom -->
    metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);
    

19. 浏览器的兼容性问题

  • 浏览器CSS样式初始化
    • * { margin: 0; padding: 0 }
  • 浏览器私有属性
    • 我们经常会在某个CSS的属性前增加一些前缀,比如-webkit-,-moz- ,-ms-,这些就是浏览器的私有属性
    • -moz代表firefox浏览器私有属性
    • -ms代表IE浏览器私有属性
    • -webkit代表chrome、safari私有属性
    • -o代表opera私有属性
  • CSS hack语法
    • 有时我们需要针对不同的浏览器或不同版本写特定的CSS样式,这种针对不同的浏览器/不同版本写相应的CSS code的过程,叫做CSS hack
    • CSS hack的写法大致归纳为3种:条件hack、属性级hack、选择符级hack
  • 自动化插件
    • Autoprefixer是一款自动管理浏览器前缀的插件
    • webpack 中配置 postcss-loader 和 postcss-preset-env 也可以处理兼容问题

20. 浏览器内核

  • 浏览器内核是浏览器最核心的部分,负责对网页语法的解释并渲染页面
  • 浏览器内核可以分成两部分
    • 渲染引擎:负责获取网页的内容并显示
    • JS引擎:负责解析JavaScript语言
  • 常见的浏览器内核
    • IE:Trident内核,也是俗称的IE内核
    • Chrome:统称为Chromium内核或Chrome内核,以前是Webkit内核,现在是Blink内核
    • Firefox:Gecko内核,俗称Firefox内核
    • Safari:Webkit内核
    • Opera:最初是自己的Presto内核,后来是Webkit,现在是Blink内核