01-HTML+CSS八股文

6/28/2022

# HTML+CSS(码路教育)

# 1. html5有哪些新特性?

(1)Canvas绘图
(2)SVG绘图
(3)地理定位
(4)Web Worker
    web worker 是运行在后台的 JS,独立于其他脚本,不会影响页面的性能。
(5)Web Storage
    1.Cookie技术 ( 兼容性好,数据不能超4kb,操作复杂)
    2.(兼容性差,数据8MB,操作简单)sessionStorage
    3.localStorage
(6)Web Socket
    WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端
1
2
3
4
5
6
7
8
9
10
11

# 2. position有哪些属性?

1. position: relative;相对定位
2. position: absolute;绝对定位
3. position: fixed;固定定位
4. position:static:默认值
5. position: sticky 粘性定位
6. position: inherit 规定应该从父元素继承 position 属性的值
7. position: initial 设置该属性为默认值
1
2
3
4
5
6
7

# 3. 请说出1px,1rem,1vh,1em各自代表的含义?

rem
    rem是全部的长度都相对于根元素<html>元素。通常做法是给html元素设置一个字体大小,然后其他元素的长度单位就为rem。

em 
    元素用em的话是相对于该元素的font-size

vw/vh
    全称是 Viewport Width 和 Viewport Height,视窗的宽度和高度,相当于 屏幕宽度和高度的 1%,不过,处理宽度的时候%单位更合适,处理高度的 话 vh 单位更好。

px
    px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。

一般电脑的分辨率有{1920 * 1024}等不同的分辨率,1920 * 1024 前者是屏幕宽度总共有1920个像素,后者则是高度为1024个像素
1
2
3
4
5
6
7
8
9
10
11
12
13

# 4. 简述优雅降级与渐进增强

渐进增强(progressive enhancement)
    针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

优雅降级(graceful degradation)
    一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

区别:
    1)优雅降级是从复杂的现状开始,并试图减少用户体验的供给;渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。
    2)渐进增强观点认为应该关注于内容本身,这使得渐进增强成为一种更为合理的设计范例;优雅降级观点认为应该针对那些最高级、最完善的浏览器来设计网站。
1
2
3
4
5
6
7
8
9

# 5. 重绘与重排

重绘:
    重绘是一个元素外观的改变所触发的浏览器行为(例如改变visibility,outline,background等属性),浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。

重排:
    重排时更明显的一种改变,可以理解为渲染树需要重新计算。常见的触发重排的操作:
    1)DOM元素的几何属性变化
    2)DOM树的结构变化(例如节点的增减、移动)
    3)获取某些属性(例如offsetTop,offsetLeft,offsetHeight,offsetWidth,clientWidth,clientHeight等)
    4)改变元素的一些样式(例如调整浏览器窗口大小)

两者的区别:
    1)重绘不会带来重新布局,并不一定伴随着重排。
    2)在实践中,应该尽量减少重排次数和缩小重排的影响范围。有以下几种方法:
    3)[ ] 将多次改变样式属性的操作合并成一次操作
    4)[ ] 将需要多次重排的元素,position属性设为absolute或fixed,使其脱离文档流,这样它的变化就不会影响到其他元素
    5)[ ] 在内存中多次操作节点,完成后再添加到文档中去
    6)[ ] 如果要对一个元素进行复杂的操作,可以将其display属性设置为none使其隐藏,待操作完成后再显示
    7)[ ] 在需要经常获取那些引起浏览器重排的属性值时,要缓存到变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 6. 解释下浮动和它的工作原理?清除浮动的方法

浮动元素脱离文档流,不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。

使用空标签清除浮动:
    这种方法是在所有浮动标签后面添加一个空标签 定义css clear:both. 弊端就是增加了无意义标签。

使用after伪对象清除浮动:
    该方法只适用于非IE浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素;

overflow: hidden;

浮动外部元素
1
2
3
4
5
6
7
8
9
10
11

# 7. 如何让一个盒子在页面垂直水平居中

  • 方法一:已知宽高
div {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    margin: auto;
}
1
2
3
4
5
6
7
8
  • 方法一:未知宽高
div {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}
1
2
3
4
5
6

# 8. 前端性能优化方案

1、减少DOM操作 
2、部署前,图片压缩,代码压缩 
3、优化js代码结构,减少冗余代码 
4、减少http请求,合理设置HTTP缓存 
5、使用内容分发cdn加速 
6、静态资源缓存 
7、图片延迟加载
1
2
3
4
5
6
7

# 9. css选择器优先级顺序

由上到下依次降低:
    ID 选择器, 如 #id{}
    类选择器, 如 .class{}
    属性选择器, 如 a[href="segmentfault.com"]{}
    伪类选择器, 如 :hover{}
    伪元素选择器, 如 ::before{}
    标签选择器, 如 span{}
    通配选择器, 如 *{}
1
2
3
4
5
6
7
8

# 10. CSS3有哪些新特性

border-radius   圆角
box-shadow   阴影
text-shadow   文字阴影
gradient   线性渐变
transform  旋转、缩放、移动或倾斜
scale  缩放
translate   位移
媒体查询   多栏布局   多背景
1
2
3
4
5
6
7
8

# 11. 什么是空元素?

即没有内容的HTML元素,例如:br、meta、hr、link、input、img
1

# 12. 如何实现浏览器内多个标签页之间的通讯

定时器setInterval + cookie:
    1)在页面A设置一个使用 setInterval 定时器不断刷新,检查 Cookies 的值是否发生变化,如果变化就进行刷新的操作。
    2)由于 Cookies 是在同域可读的,所以在页面 B 审核的时候改变 Cookies 的值,页面 A 自然是可以拿到的。
    3)这样做确实可以实现我想要的功能,但是这样的方法相当浪费资源。虽然在这个性能过盛的时代,浪费不浪费也感觉不出来,但是这种实现方案,确实不够优雅。

使用localstorage:
    1)localstorage是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session是会话级的存储空间,每个标签页都是单独的)。
    2)直接在window对象上添加监听即可:window.addEventListener('storage', (e) => console.log(e))
    3)onstorage以及storage事件,针对都是非当前页面对localStorage进行修改时才会触发,当前页面修改localStorage不会触发监听函数。然后就是在对原有的数据的值进行修改时才会触发,比如原本已经有一个key会a值为b的localStorage,你再执行:localStorage.setItem('a', 'b')代码,同样是不会触发监听函数的。
1
2
3
4
5
6
7
8
9

# 13. 为什么要初始化css样式

浏览器差异:
    不同浏览器对有些标签的默认值是不同的,如果没对css初始化会出现浏览器之间的页面显示差异

提高编码质量:
    如果不初始化,整个页面做完会很糟糕,重复的css样式很多
1
2
3
4
5

# 14. CSS3新增的伪类有哪些?

p:first-of-type 选择属于其父元素的首个元素
p:last-of-type 选择属于其父元素的最后元素
p:only-of-type 选择属于其父元素唯一的元素
p:only-child 选择属于其父元素的唯一子元素
p:nth-child(2) 选择属于其父元素的第二个子元素
1
2
3
4
5

# 15. 说说对canvas,svg,webgl的理解

1)Canvas 是HTML5新增的一个元素对象,名副其实就是一个画布,浏览器 js 配有相应的操作api,可以不再依赖其他的API或组件而直接绘图,相当于2D的API。Canvas 适用于位图,高数据量高绘制频率(帧率)的场景,如动画、游戏;
2)SVG 是给数据就可以绘制点、线、图形的,基于 XML 的标记语言;SVG 适用于矢量图,低数据量低绘制频率的场景,如图形、图表;
3)WebGL(全写Web Graphics Library)是一种3D绘图标准,通俗说WebGL是canvas绘图中的3D版本。因为原生的WebGL很复杂,我们经常会使用一些三方的库,如three.js等,WebGL 主要用来做 3D 展示、动画、游戏。
1
2
3

# 16. 浏览器是如何渲染UI的?

1)浏览器获取HTML文件,然后对文件进行解析,形成DOM Tree
2)与此同时,进行CSS解析,生成Style Rules
3)接着将DOM Tree与Style Rules合成为 Render Tree
4)接着进入布局(Layout)阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标
5)随后调用GPU进行绘制(Paint),遍历Render Tree的节点,并将元素呈现出来
1
2
3
4
5

# 17. em、rem的区别

em是相对长度单位,相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对浏览器的默认字体尺寸。它会继承父级元素的字体大小,因此并不是一个固定的值。

rem是CSS3新增的一个相对单位(root em,根em),使用rem为元素设定字体大小事,仍然是相对大小但相对的只是HTML根元素。
1
2
3

# 18. 解释csssprites,如何使用。

Css精灵把一堆小的图片整合到一张大的图片上,减轻服务器对图片的请求数量。
1

# 19. 浏览器工作原理

用户界面 、2. 网络 、3. UI后端 、4. 数据存储 、5. 浏览器引擎 、6. 渲染引擎 、7. js解释器
1

# 20. 介绍一下你对浏览器内核的理解?

主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。

渲染引擎:
    负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。

JS引擎则:
    解析和执行javascript来实现网页的动态效果。最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。
1
2
3
4
5
6
7

# 21. 常见的浏览器内核有哪些?

Trident内核:IE,360,傲游,搜狗,世界之窗,腾讯等。[又称MSHTML]
Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等
Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;]
Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]
1
2
3
4

# 22. 一个页面上有大量的图片,加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。

(1)图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。
(2)如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。
(3)如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。
(4)如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。
1
2
3
4

# 23. 如何进行seo优化?

1、合理的title、description、keywords:搜索对着三项的权重逐个减小,title值强调重点即可;description把页面内容高度概括,不可过分堆砌关键词;keywords列举出重要关键词。
2、语义化的HTML代码,符合W3C规范:语义化代码让搜索引擎容易理解网页
3、重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,保证重要内容一定会被抓取
4、重要内容不要用js输出:爬虫不会执行js获取内容
5、少用iframe:搜索引擎不会抓取iframe中的内容
6、非装饰性图片必须加alt属性
7、提高网站速度:网站速度是搜索引擎排序的一个重要指标。
1
2
3
4
5
6
7

# 24. 如何实现0.5px边框

  • border+border-image+linear-gradient的方式
/* <div class="border"></div> */
.border {
    width: 200px;
    height: 200px;
    background-color: red;
    margin: 0 auto;
    border-bottom: 1px solid blue;
    border-image: linear-gradient(to bottom, transparent 50%, Green 50%) 0 0 100% 0;
}
1
2
3
4
5
6
7
8
9
  • 伪元素+background-image的方式
/* <div class="border"></div> */
.border {
    width: 200px;
    height: 200px;
    background-color: red;
    margin: 0 auto;
    position: relative;
}

.border:before {
    content: " ";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100px;
    height: 1px;
    background-color: blue;
    background-image: linear-gradient(to bottom transparent 50%, blue 50%);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  • 定位+伪元素+transfrom缩放(scale)的方式
 /* <div class="border"></div> */
 .border {
     width: 200px;
     height: 200px;
     background-color: red;
     margin: 0 auto;
     position: relative;
 }
1
2
3
4
5
6
7
8

# 25. less和sass的区别

Less是基于JavaScript,是在客户端处理的;Sass是基于Ruby的,是在服务器端处理的。

关于变量在Less和Sass中的唯一区别就是Less用@,Sass用$。

输出设置,Less没有输出设置,Sass提供4中输出选项:nested, compact, compressed 和 expanded。

Sass支持条件语句,可以使用if{}else{},for{}循环等等,而Less不支持。
1
2
3
4
5
6
7

# 26. 页面导入样式时,使用link和@import有什么区别

1、link属于XHTML标签,除了加载CSS外,还能用于定义RSS(简易信息聚合,是一种基于XML标准,在互联网上被广泛采用的内容包装和投递协议),rel连接属性等作用;@import是CSS提供的,只能用于加载CSS;
2、页面被加载时,link会同时被加载;而@import引用的CSS会等到页面被加载完成后再加载;
3、link是XHTML标签,没有兼容问题;而@import只有在IE5以上才能被识别;
4、link支持使用JavaScript控制DOM修改样式;而@import不支持。
1
2
3
4

# 27. 谈谈你对 BFC 的理解?

BFC: 块级格式化上下文, 是一块独立的渲染区域 (触发了BFC, 这块区域就是一块独立的渲染区域)
    会将处于BFC的内容 和 处于BFC外的内容 隔离

触发BFC的方式:
    1. position: absolute/fixed
    2. float: left / right;   浮动的元素多个放在一起, 会互相隔开
    3. overflow: 非visible hidden/auto/scroll
    4. display: inline-block

BFC应用:
    1. 处理块级元素, 上下margin合并的问题
    2. 处理margin塌陷
    3. 清除浮动
    4. 实现自适应布局
        左边固定, 右边自适应
        flex => display: flex; 左边定宽, 右边 flex: 1;
        浮动 => 先浮动占位置, 再中间盒子overflow: hidden
        定位 => 先定位, 再设置padding即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 28. 说说你对元素语义化的理解

元素语义化就是⽤正确的元素做正确的事情。虽然在理论上,所以的html元素都可以通过css样式实现相同的事情,但是这么做会使事情复杂化,所以我们需要元素语义化来降低复杂度。

元素语义化在我们实际的开发中有很多好处,⽐如:
    1)提⾼代码的阅读性和可维护性;
    2)减少coder之间的沟通成本;
    3)能让语⾳合成⼯具正确识别⽹⻚元素的⽤途,以便做出正确的反应
    4)有利于SEO(Search Engine Optimization)
1
2
3
4
5
6
7

# 29. HTML 中有哪些语义化标签

header
footer
main
aside
article
section
address
summary/details
menu
h1/h2/h3/h4/h5/h6
img
p
strong/italic
1
2
3
4
5
6
7
8
9
10
11
12
13

# 30. 什么是 URL 编码 (URL Encode)

encodeURI ⽤来编码URI,其不会编码保留字符。

encodeURIComponent ⽤来编码 URI参数,除了字符:A-Z a-z 0-9 - _ . ! ~ * ' ( ),都将会转义。
1
2
3

# 31. 说说你对SEO的理解

SEO就是搜索引擎优化(Search Engine Optimization),SEO通过了解搜索引擎的运⾏规则来调整⽹站,以提⾼⽹站的曝光度,以及⽹站的排名。

Google 搜索引擎的⼯作流程主要分为三个阶段:

抓取:
    Google 会使⽤名为“抓取⼯具”的⾃动程序搜索⽹络,以查找新⽹⻚或更新后的⽹⻚。Google 会将这些⽹⻚的地址(即⽹址)存储在⼀个⼤型列表中,以便⽇后查看。我们会通过许多不同的⽅法查找⽹⻚,但主要⽅法是跟踪我们已知的⽹⻚中的链接。

编⼊索引:
    Google 会访问它通过抓取得知的⽹⻚,并会尝试分析每个⽹⻚的主题。Google 会分析⽹⻚中的内容、图⽚和视频⽂件,尝试了解⽹⻚的主题。这些信息存储在 Google 索引中,⽽ Google 索引是⼀个存储在海量计算机中的巨⼤数据库。

呈现搜索结果:
    当⽤户在 Google 上进⾏搜索时,Google 会尝试确定最优质的搜索结果。“最佳”结果取决于许多因素,包括⽤户的位置、语⾔、设备(桌⾯设备或⼿机)以及先前⽤过的搜索查询。例如,在⽤户搜索“⾃⾏⻋维修店”后,Google 向巴黎⽤户显示的答案与向⾹港⽤户显示的答案有所不同。⽀付费⽤不能提⾼⽹⻚在 Google 搜索结果中的排名,⽹⻚排名是完全依靠算法完成的。
1
2
3
4
5
6
7
8
9
10
11
12

# 32. 说明text-align居中的条件

text-align : 直接翻译过来设置⽂本的⽔平对⻬⽅式 (是继承属性)(是继承属性)
text-align 并不控制块元素⾃⼰的对⻬,只控制它的⾏内内容的对⻬
MDN解释: 定义⾏内内容(例如⽂字)如何相对它的块⽗元素对⻬(可以设置图⽚居中)
W3C官⽅⽂档解释: 设置⾏内(inline-level)元素(没有填满⽗元素)在快级⽗元素的对⻬⽅式
1
2
3
4

# 33. 说说盒⼦模型包含哪些内容?

内容
    通过宽度和⾼度设置

内边距
    通过padding设置
    padding: padding-top padding-right padding-bottom padding-left;

边框
    通过border设置
    border: border-width border-style border-color

外边距
    通过margin设置
    margin: margin-top margin-right margin-bottom margin-left
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 34. 说说你对margin的传递和折叠的理解

margin的传递⼀般是⽗⼦块元素之间,有margin-top传递,margin-bottom传递.
    1)margin-top传递: 当块级元素的顶部线和⽗元素的顶部线重叠,那么这个块级元素的margin-top值会传递给⽗元素
    2)margin-bottom传递:当块级元素的底部线和⽗元素的底部线重叠,那么这个块级元素的marginbottom值会传递给⽗元素

折叠: 指的是 垂直⽅向上相邻的2个margin(margin-top、margin-bottom)有可能会合并为1个margin.

它有两个兄弟块级元素之间的上下margin的折叠,也有⽗⼦块元素之间的margin折叠
1
2
3
4
5
6
7

# 35. CSS 隐藏⻚⾯中某个元素的⼏种⽅法

display: none
    通过 CSS 操控 display,移出⽂档流

opacity: 0
    透明度为 0,仍在⽂档流中,当作⽤于其上的事件(如点击)仍有效

visibility: hidden
    透明度为 0,仍在⽂档流中,但作⽤于其上的事件(如点击)⽆效,这也是visibility:hidden 与 opacity: 0 的区别

content-visibility
    移出⽂档流,但是再次显示时消耗性能低

绝对定位于当前⻚⾯的不可⻅位置
    position: absolute;
    top: -9000px;
    left: -9000px;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 36. box-sizing有什么作⽤?content-box和border-box的区别

box-sizing⽤来设置盒⼦模型中宽⾼的计算⽅式:
    content-box: padding、border都布置在width、height外边
    border-box: padding、border都布置在width、height⾥边
1
2
3

# 37. 为什么会发⽣样式抖动

因为没有指定元素具体⾼度和宽度,⽐如数据还没有加载进来时元素⾼度是 100px(假设这⾥是100px)
数据加载进来后,因为有了数据,然后元素被撑⼤,所有出现了抖动
1
2

# 38. 伪类与伪元素有什么区别?

伪类使⽤单冒号,⽽伪元素使⽤双冒号。如 :hover 是伪类, ::before 是伪元素
伪元素会在⽂档流⽣成⼀个新的元素,并且可以使⽤ content 属性设置内容
1
2

# 39. 什么是视⼝(viewport)?

pc端的视⼝:
    就是浏览器的可视区域

移动端视⼝:
    布局视⼝
        会按照⼀个默认宽度980px,来布局⼀个⻚⾯盒⼦的内容
        为了可以显示完整的⻚⾯,会对整个⻚⾯进⾏缩⼩
    视觉视⼝
        显示在可视区域的视⼝,就是视觉视⼝
    理想视⼝
        当布局视⼝ = 视觉视⼝的时候,就是理想视⼝
        怎样是这理想视⼝呢?
1
2
3
4
5
6
7
8
9
10
11
12

# 40. 移动端适配的⽅案有哪些?

百分⽐布局:
    因为不同属性百分⽐的值,相对的可能是不同的参照物,所以百分⽐往很难统⼀。

视⼝ + ( rem + 动态HTML的 font-size ):
    动态计算 HTML font-zise:
        ⽤媒体查询来修改HTML font-size( 缺点不能实时改变font-size的⼤⼩ )
        ⾃⼰编写JS来实现修改HTML font-size的⼤⼩(可以实时修改字体⼤⼩)
        是引⽤lib-flexiable库来实现(原理是JS动态改HTML font-size⼤⼩)
    px 转成rem:
        ⼿动计算 rem
        Less的映射来计算
        postcss-pxtorem插件来实现(需依赖webpack或Vite)
        cssrem VSCode插件来实现
视⼝ + vw
    px转成rem
        ⼿动计算vw
        Less的映射来计算
        postcss-px-to-viewport的插件(需依赖webpack或Vite)
        ccsrem VSCode插件

flex弹性布局
    flex container 属性
    flex item 属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 41. 说出不同像素之间的差异?

分为三种像素:设备像素(物理像素),设备独⽴像素(逻辑像素),css像素

设备像素(物理像素)
    1)是指显示器上真实的像素,在购买显示器或者⼿机的时候,提到的设备分辨率就是设备像素的⼤⼩
    2)iPhone X的分辨率 1125 x 2436,指的就是设备像素

设备独⽴像素(逻辑像素)
    1)如果⾯向开发者我们使⽤设备像素显示⼀个100px的宽度,那么在不同屏幕上显示效果会是不同的
    2)开发者针对不同的屏幕很难进⾏较好的适配,编写程序必须了解⽤户的分辨率来进⾏开发
    3)所以在设备像素之上,操作系统为开发者进⾏抽象,提供了逻辑像素的概念
    4)⽐如你购买了⼀台显示器,在操作系统上是以1920x1080设置的显示分辨率,那么⽆论你购买的是2k、4k的显示器,对于开发者来说,都是1920x1080的⼤⼩
    5)如果物理像素很⼤的时候,⽐如2k,4k等,可以理解为⼀个逻辑像素⾥⾯由多个物理像素来渲染的

css像素
    1)默认情况下就是设备独⽴像素(也就是逻辑像素)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 42. 如何解决移动端 Retina 屏 1px 像素问题

在移动端 Web 开发中,UI 设计稿中设置边框为 1 像素,前端在开发过程中如果出现 border:1px ,测试会发现在 Retina 屏机型中,1px 会⽐较粗,即是较经典的移动端 1px 像素问题。

以 iphone6 为例,iphone6 的屏幕宽度为 375px ,设计师做的视觉稿⼀般是750px ,也就是 2x ,这个时候设计师在视觉稿上画了 1px 的边框,于是你就写了 border:1px ,所以1px边框问题产⽣了。

对设计师来说它的 1px 是相对于 750px 的(物理像素),对你来说你的 1px 是相对于 375px 的(css像素),实际上你应该是 border:0.5px 。下⾯来看⼀下解决⽅案:
1
2
3
4
5
  • 0.5px 实现
.border-1px {
    border: 1px solid #999
}

@media screen and (-webkit-min-device-pixel-ratio: 2) {
    .border-1px {
        border: 0.5px solid #999
    }
}

/* dpr=2 和 dpr=3 情况下 border 相差⽆⼏,下⾯代码可以省略*/
@media screen and (-webkit-min-device-pixel-ratio: 3) {
    .border-1px {
        border: 0.333333px solid #999
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 但在 IOS7 及以下和 Android 等其他系统⾥, 0.5px 将会被显示为 0px 。所以我们需要通过 JS 检测浏览器能否处理 0.5px 的边框
if (window.devicePixelRatio && devicePixelRatio >= 2) {
    var testElem = document.createElement('div');
    testElem.style.border = '.5px solid transparent';
    document.body.appendChild(testElem);
}
if (testElem.offsetHeight == 1) {
    document.querySelector('html').classList.add('hairlines');
}
document.body.removeChild(testElem);
}

// 优点:简单,没有副作⽤
// 缺点:⽀持 iOS 8+,安卓待兼容
1
2
3
4
5
6
7
8
9
10
11
12
13
  • viewport + rem 实现, 通过设置缩放,让 CSS 像素等于真正的物理像素。
const scale = 1 / window.devicePixelRatio;
const viewport = document.querySelector('meta[name="viewport"]');
if (!viewport) {
    viewport = document.createElement('meta');
    viewport.setAttribute('name', 'viewport');
    window.document.head.appendChild(viewport);
}
viewport.setAttribute('content', 'width=device-width,user-scalable=no,initialscale=' +
    scale + ',maximum-scale=' + scale + ',minimum-scale=' + scale);
// 设置根字体⼤⼩
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;
// 在CSS中⽤rem单位就⾏了

// 缺点:
// 通过 JS 对⽂档进⾏修改,所以性能上有⼀定影响
// 会对项⽬中所有使⽤ rem 单位的对象进⾏影响。如果是⽼项⽬,则会全部更改 css 样式(不适合⽼项⽬改造)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 伪元素 + transform 实现(推荐)
/* 为什么⽤伪元素? 因为伪元素 ::after 或 ::before 是独⽴于当前元素,可以单独对其缩放⽽不影
响元素本身的缩放
基于 media 查询判断不同的设备像素⽐对线条进⾏缩放: */

.border-1px:before {
    content: '';
    position: absolute;
    top: 0;
    height: 1px;
    width: 100%;
    background-color: #999;
    transform-origin: 50% 0%;
}

@media only screen and (-webkit-min-device-pixel-ratio:2) {
    .border-1px:before {
        transform: scaleY(0.5);
    }
}

@media only screen and (-webkit-min-device-pixel-ratio:3) {
    .border-1px:before {
        transform: scaleY(0.33);
    }
}

/* 注意:如果需要满⾜圆⻆,需要给伪类也加上 border-radius
优点:兼容性好,⽆副作⽤,推荐使⽤ */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  • svg 实现(推荐)
/* 因为 svg 是⽮量图形,它的 1px 对应的物理像素就是 1px
可以搭配 PostCSS 的 postcss-write-svg 使⽤: */
@svg border-1px {
    height: 2px;

    @rect {
        fill: var(--color, black);
        width: 100%;
        height: 50%;
    }
}

.svg {
    border: 1px solid transparent;
    border-image: svg(border_1px param(--color #00b1ff)) 2 2 stretch;
}

/* 优点:实现简单,可以实现圆⻆,
缺点:需要学习 svg 语法 */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 43. 如何计算⽩屏时间和⾸屏加载时间

⽩屏时间:
    window.performance.timing.domLoading - window.performance.timing.navigationStart

⾸屏时间:
    window.performance.timing.domInteractive - window.performace.timing.navigationStart
1
2
3
4
5

# 44. 如何⾃定义滚动条的样式

滚动条相关样式都是伪元素,以 scrollbar 打头,有以下伪元素,从 -webkit 中可⻅兼容性⼀般,不过⽆所谓,现在 Chrome 浏览器占⼤头
::-webkit-scrollbar — 整个滚动条.
::-webkit-scrollbar-button — 滚动条上的按钮 (上下箭头).
::-webkit-scrollbar-thumb — 滚动条上的滚动滑块.
::-webkit-scrollbar-track — 滚动条轨道.
::-webkit-scrollbar-track-piece — 滚动条没有滑块的轨道部分.
::-webkit-scrollbar-corner — 当同时有垂直滚动条和⽔平滚动条时交汇的部分.
::-webkit-resizer — 某些元素的 corner 部分的部分样式(例:textarea 的可拖动按钮).
1
2
3
4
5
6
7
8
  • 但其实最常⽤的是以下⼏个伪元素:滚动条、滑块、轨道,如下滚动条设置成功
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

::-webkit-scrollbar-track {
    border-radius: 3px;
    background: rgba(0, 0, 0);
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
}

::-webkit-scrollbar-thumb {
    border-radius: 3px;
    background: rgba(0, 0, 1);
    box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Last Updated: 1/12/2023, 6:49:17 PM