前端开发必会的HTML/CSS硬知识
Posted Bonnie加油站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端开发必会的HTML/CSS硬知识相关的知识,希望对你有一定的参考价值。
知识点
盒模型
选择器优先级
水平垂直居中
浮动与清除浮动
flex布局
H5新特性
CSS动画
CSS预处理器(Autoprefixer)
真题
请说出3个H5新增的块元素,并介绍他们的应用场景
aside:表示article元素内容之外,与article元素内容相关的辅助信息。(当前文章的其他引用, 备注,侧边栏,广告等有别于主要内容的部分)
figure:代表一个块级图像,还可以包含说明。figure添加标题时,与figcaption元素结合使用。
dialog:表示几个人直接的对话。与dt和dd元素结合使用,dt表示讲话者,dd表示讲话内容
<dialog id="dialo">
<dt>老师</dt>
<dd>乐乐,5+3等于多少</dd>
<dt>乐乐</dt>
<dd>等于8</dd>
<dt>老师</dt>
<dd>答对了!乐乐棒极了</dd>
</dialog>
<button id="open">open</button>
<button id="close">close</button>
<script>
var dialog = document.getElementById('dialo');
var openBtn = document.getElementById('open');
var closeBtn = document.getElementById('close');
openBtn.addEventListener('click',function(){
dialog.show();
})
closeBtn.addEventListener('click',function(){
dialog.close();
});
</script>
thead:表格表头
tfoot:表格页脚
行内元素和块元素的区别
块元素可以设置宽高
行内元素不可以。
html元素分为行内、块状、行内块元素三种。
1、三者是可以通过display属性任意转换的
inline 行内元素 block 块状元素 inline-block行内块元素
<style>
span {
display: block;
width: 100px;
height: 38px;
background-color: red;
}
div {
display: inline;
width: 100px;
height: 38px;
background-color: green;
}
i {
display: inline-block;
width: 100px;
height: 38px;
background-color: yellow;
}
</style>
<span>行内转块</span>
<div>块转行</div>
<i>行转行内块</i>
block:独占一行,可以设置宽高
inline: 宽高由内容撑开
inline-block:可以设置宽高
行内元素特征: (span、b、i)
1、设置宽高无效
2、设置margin的上下无效,左右有效,设置padding上下左右都有效(并且会撑大空间)
3、不会自动换行
附:55的9次方
<sub>55</sub>
<sup>9</sup>
块级元素特征:(p nav aside header footer section article ul-li address)
1、可以设置宽高
2、设置margin、padding的上下左右都有效
3、独占一行
4、多个块状元素一起写,默认排列从上至下
行内块元素
1、能设置宽高
2、不会自动换行
3、多个行内块一起写,默认从左至右排列
(在html5中,可以自定义标签,在任意标签加上display属性就好。)
请说出3个CSS浏览器前缀
-ms- 兼容IE浏览器
-moz-兼容firefox
-o-兼容opera
-webkit- 兼容chrome和safari
div {
-ms-transform: rotate(0);
-webkit-transform: rotate(0);
-moz-transform: rotate(0);
-o-transform: rotate(0);
transform: rotate(0);
}
CSS前缀补全:autoprefixer
请介绍下盒子模型
标准盒模型 width = content
怪异盒模型(IE5.X 和 6 ) width = content+ padding + border (不要给元素添加具有指定宽度的内边距,而是尝试将内边距或外边距添加到元素的父元素和子元素。)
解决IE8及更早版本不兼容问题可以在HTML页面声明 <!DOCTYPE html>即可。
实例:margin:20px,border:10px,padding:10px;width:200px;height:50px;
标准盒模型占用宽:margin2+padding2+border2+width=202+102+102+200 = 280
标准盒模型占用高:margin2+padding2+border2+height=202+102+102+50 = 130
盒子的实际宽度大小为:padding2+border2+width = 240
实际高度:padding2+border2+height = 90
ie占用宽:margin2+width=240
ie占用高:margin2+height=90
盒子的实际宽度大小为:width = 200
实际高度:height = 50
box-sizing都有哪些值?他们的宽高分别如何计算?
box-sizing: content-box(标准盒模型)|border-box(怪异盒模型)|inherit(继承父元素);
content-box的宽高由content决定
border-box的宽高由content+padding+border决定
什么是边界塌陷(或边界重叠)?
BFC(块状格式化上下文,独立的盒子,布局不受外部影响,但是如果同一个BFC中,同级块状元素的margin-top和margin-bottom会重叠)
1、兄弟div(上下margin塌陷)
2、父子div(如果父级div没有padding\border\inlinecontent, 子级div的margin会向上查找边界塌陷的div,直到找到某个标签包括border\padding\inline content的其中一个,然后按此div进行margin)
<style>
.parent {
width: 300px;
height: 150px;
background-color: yellow;
margin: 20px;
/* overflow: hidden; */
}
.parent>div {
width: 100px;
height: 50px;
background-color: red;
overflow: hidden;
}
.sm {
width: 10px;
height: 10px;
background-color: blue;
margin: 10px;
}
</style>
<div class="parent">
<div>
<div class="sm">cc</div>
</div>
</div>
解决办法:overflow:hidden; 防止溢出部分,隐藏溢出部分。
overflow:auto .制作一条滚动条,当元素溢出,用滚动条将溢出部门展示出来。
什么是BFC(格式化上下文)?如何实现?
具有BFC特征的元素可以看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素。
只要元素满足下面的任一条件,都会触发BFC特征。
1、body根元素
2、position: fixed|absolute(绝对定位元素)
3、float(浮动元素) 除了none
4、overflow: hidden|auto|scroll (除了visible之外的值)
5、display: inline-block\ table-cells\flex (具有table-的属性)
问题:
1、解决边界塌陷问题
2、解决浮动元素导致父元素高度塌陷问题
3、解决阻止元素被浮动元素覆盖问题
多个inline元素之间会有空隙,为什么?如何解决?
元素被当成行内元素排版时,元素直接的空白符会被浏览器处理,根据white-spack的处理方式(默认是normal,合并多余空白),Html代码在回车换行时被转成一个空白符,在字体不为0的情况下,空白符占据一定宽度,所以inline-block元素之间就出现了空隙。
这些元素之间的间距会随字体的大小而变化,当行内元素font-size:16px时,间距为8px。
解决办法:1、多个inline元素写在同一行
2、将父级元素的font-size:0
3、给inline元素添加float的样式
4、设置子元素的margin为负值
5、设置父元素display:table和word-spacing:-1em
请实现三列布局,要求:背景色分别为red、green、blue;左右各定宽200px;中间随屏幕大小变化;内容互不遮挡;方法越多越好(顺便复习一下三角形)
法一:笔者真的无地自容,废了九牛二虎之力写了一个
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请实现三列布局,要求:背景色分别为red、green、blue;左右各定宽200px;中间随屏幕大小变化</title>
<style>
.container{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
font-size: 0px;
}
.left{
display: inline-block;
width: 200px;
height: 100%;
background-color: red;
}
.main{
display: inline-block;
width: calc(100% - 400px);
height: 100%;
background-color: green;
}
.right{
display: inline-block;
width: 200px;
height: 100%;
background-color: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
</body>
</html>
法二:Flex布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请实现三列布局,要求:背景色分别为red、green、blue;左右各定宽200px;中间随屏幕大小变化</title>
<style>
.container{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
}
.left{
width: 200px;
background-color: red;
}
.main{
flex: 1;
background-color: green;
}
.right{
width: 200px;
background-color: blue;
}
</style>
</head>
<body>
<!--
flex:1的含义
flex-grow : 1; // 这意味着div将以与窗口大小相同的比例增长
flex-shrink : 1; // 这意味着div将以与窗口大小相同的比例缩小
flex-basis : 0; // 这意味着div没有这样的起始值,并且将根据可用的屏幕大小占用屏幕。例如:- 如果包装器中有3个div,则每个div将占用33%。-->
<div class="container">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
</body>
</html>
法三:BFC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请实现三列布局,要求:背景色分别为red、green、blue;左右各定宽200px;中间随屏幕大小变化</title>
<style>
.container{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.left{
float: left;
width: 200px;
height: 100%;
background-color: red;
}
.right{
float: right;
width: 200px;
height: 100%;
background-color: blue;
}
.main{
width: auto;
height: 100%;
overflow: hidden;
background-color: green;
}
</style>
</head>
<body>
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
</div>
</body>
</html>
法四:table\table-cell
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请实现三列布局,要求:背景色分别为red、green、blue;左右各定宽200px;中间随屏幕大小变化</title>
<style>
.container{
width: 100%;
height: 400px;
display: table;
}
.left{
width: 200px;
height: 100%;
background-color: red;
display: table-cell;
}
.right{
width: 200px;
height: 100%;
background-color: blue;
display: table-cell;
}
.main{
width: auto;
height: 100%;
background-color: green;
display: table-cell;
}
</style>
</head>
<body>
<div class="container">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
</body>
</html>
浮动会出现什么问题,如何清除浮动?
1、浮动会导致父元素高度塌陷
2、会覆盖其他元素
清楚浮动:
1、父元素加上overflow:hidden
2、在浮动元素的后面(同级),添加一个div,属性是clear:both
3、在父元素添加一个伪元素
.clearfix:after {
display: block;
height: 0;
visibility: hidden;
clear: both;
content: '';
}
.clearfix{ //IE6模式下
zoom:1;
}
4、在父元素添加双伪元素
.clearfix:before, .clearfix:after {
display: table;
content: '';
}
.clearfix:after {
clear: both;
}
.clearfix {
zoom: 1; //兼容IE6下
}
如何实现中间部分最先加载?
使用圣杯布局。
基础:
margin和padding的百分比都是相对父元素的宽度来设置的。
absolute和float两个元素,默认绝对定位覆盖在浮动元素上面。设置z-index:-1后,浮动元素在绝对定位元素的上面。
设置position:relative后,元素相对于自身进行定位。(相对于元素在文档中的初始位置)
↑注意:使用相对定位,无论是否移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其他框。
position:absolute,如果没有已定位的元素,就会找到body。
↑注意:absolute和float不能写在同一个元素(relative和float可以),absolute或者float会隐式改变display的类型(display:none除外)。设置position:absolute,float:left,float:right任意一个值,都会使元素变成display:inline-block。即使设置display:inline,display:block也无效。
float在IE6下的双边距bug就是用display:inline来解决的。position:relative不会隐式改变display。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 100%;
height: 500px;
padding: 0 300px 0 200px;
box-sizing: border-box;
/* box-sizing差点忘了 border-box的宽度是内容+border+padding 而content-box的宽度只是内容 */
}
.container>div {
float: left;
height: 100%;
}
.main {
width: 100%;
background-color: green;
}
.left {
width: 200px;
margin-left: -100%;
position: relative;
left: -200px;
background-color: red;
}
.right {
width: 300px;
margin-left: -300px;
position: relative;
left: 300px;
background-color: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
</body>
</html>
写一个双飞翼布局:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 100%;
height: 500px;
}
.container>div {
float: left;
height: 100%;
}
.main {
width: 100%;
}
.submain {
height: 100%;
/* 浮动元素的子元素不给高度,相当于高度为0 */
background-color: green;
margin: 0 300px 0 200px;
}
.left {
width: 200px;
margin-left: -100%;
background-color: red;
}
.right {
width: 300px;
margin-left: -300px;
background-color: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="main">
<div class="submain"></div>
</div>
<div class="left"></div>
<div class="right"></div>
</div>
</body>
</html>
最简易的布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 100%;
height: 500px;
}
.container>div {
height: 100%;
}
.main {
margin: 0 300px 0 200px;
background-color: green;
}
.left {
width: 200px;
float: left;
background-color: red;
}
.right {
width: 300px;
float: right;
position: relative;
top: -500px;
/* 添加上面两行的原因是,main是块级元素,独占一行,right元素会在第二行显示。*/
background-color: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
</body>
</html>
如何保证三列等高,并随着最高的一列变化?
html:
<div class="container">
<div class="left">
<p>aaa</p>
</div>
<div class="main">
<p>bbb</p>
<p>bbb</p>
<p>bbb</p>
</div>
<div class="right">
<p>ccc</p>
<p>ccc</p>
</div>
</div>
法一:table、table-cell(父元素的display为table,子元素为table-cell)
<style type="text/css">
.container {
display: table;
margin: 0 auto;
border: 1px solid black;
}
.container>div {
width: 200px;
display: table-cell;
}
.left {
background-color: red;
}
.main {
background-color: orange;
}
.right {
background-color: yellow;
}
</style>
法二:Flex布局(父元素设置display:flex; 子元素设置flex:1;)
<style type="text/css">
.container {
display: flex;
width: 600px;
margin: 0 auto;
border: 1px solid black;
}
.container>div {
flex: 1;
/* flex-grow:1; flex-shrink 1;flex-basis:0;
div与窗口大小相同的比例增长、缩小,div没有起始值,并且将根据可用屏幕大小占用屏幕
*/
}
</style>
法三:margin/padding互补(子元素的margin设为-999em,padding设为999em)
<style type="text/css">
.container {
width: 600px;
margin: 0 auto;
border: 1px solid black;
overflow: hidden;
}
.container>div {
float: left;
width: 200px;
margin-bottom: -999em;
padding-bottom: 999em;
}
</style>
position都有哪些值?是针对包裹元素定位吗?
relative 相对定位 (相对元素在文档中的初始位置定位)
absolute绝对定位(相对于定位元素定位,最顶级是body)
fixed 固定定位 (相对窗口定位)
static 文档流
一个220x220的元素A,一个20x20的元素B,B中有一个文字“C”,字体大小15px。要求,A在屏幕中央,B在A中央,文字“C”在B中央,中央即为水平垂直都居中。不限方法,越多越好
<div class="container">
<div class="a">
<div class="b">C</div>
</div>
</div>
法一:flex
<style type="text/css">
.container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
}
.a {
width: 200px;
height: 200px;
background-color: red;
display: flex;
align-items: center;
justify-content: center;
}
.b {
width: 20px;
height: 20px;
font-size: 15px;
background-color: yellow;
display: flex;
align-items: center;
justify-content: center;
}
</style>
法二:定位(left:50%; top:50%;transform: translateX(-50%) translateY(-50%))
.container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.a,
.b {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
.a {
width: 200px;
height: 200px;
background-color: red;
}
.b {
width: 20px;
height: 20px;
font-size: 15px;
background-color: yellow;
}
</style>
若A的宽度随屏幕宽度变化,并满足左右边距各20px,如何实现?
.a{
width: calc(100% - 40px);
}.container {
margin: 0 20px;
}
.a {
width: 100%;
}
若A的高度等于A宽度的50%,如何实现?
.a {
width: calc(100vw - 40px);
height: calc((100vw - 40px)/2);
}
宽度不一定,但是想让box为正方形;
比如width:50%;之后设置该box为正方形设置height:0;padding-bottom:50%;
CSS的选择器有哪些?优先级高低如何判断?
id、class、tag、属性(a[href=""] )派生选择器
不同级优先级:
!important>内联>id>class = 属性 = 伪类 >标签 = 伪元素 > 通配符(*)
同一级别:
后来居上 (后写覆盖先写)
内联样式 > 内部样式表 > 外部样式表 > 导入样式 @import
优先级相同时会发生什么?
样式被覆盖
列举几条常用的CSS reset,是否了解normalize.css?
* { margin:0; padding:0;}
ol, ul { list-style:none;}
body {line-height:1;}
normalize.css是一个css reset的替代方案。
保护有用的浏览器默认样式而不是完全去掉
一般化样式:为大部分html元素提供
修复浏览器自身的bug
优化css可用性
解释代码
如何做到一个list中奇数和偶数行的背景色不一样?
ul>li:nth-child(2n+1) {
background-color: red;
}
ul>li:nth-child(2n) {
background-color: yellow;
}
如何做到一个list的第一行没有上边框?
ul>li:first-child {
border-top: none;
}
请描述一下浏览器从开始解析HTML到渲染结束都经历了什么?
解析HTML文件,创建DOM树
解析CSS,形成CSS对象模型
将CSS与DOM合并,构建渲染树(rendering tree)
布局和绘制
浏览器解析CSS是从左开始还是从右?为什么?
从右。
因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点);
而从左向右的匹配规则的性能都浪费在了失败的查找上面。
什么是reflow和repaint?
repaint:重绘(改变不影响元素在网页中的位置的元素样式时,根据浏览器新属性重新绘制一次。不会带来重新布局)
例如:bg-c border-color ......
reflow:重排(改变元素在网页中的布局和位置)
例如:浏览器放大缩小、DOM元素的增删改、内容变化,包括表单内的文本变化、CSS属性的计算和改变、添加或者删除样式表、伪类激活(悬停)、更改类属性
display:none; 重排 (不占空间)
visibility: hidden; 重绘 (占空间)
overflow:hidden; 重绘+重排 (占空间,超出隐藏)
HTML的解析会因为什么阻塞?静态文件引用如何放置合理?
css加载不会堵塞html解析
css加载会堵塞dom树渲染
css加载会堵塞js语句的执行
js的加载会堵塞html解析
css文件放前面,js文件放在html和css的后面
为了让用户减少看到白屏的时间,做一下这个优化。
cdn加速
css代码压缩
合理使用浏览器缓存(设置cache-control,expires,E-tag。注意,文件更新后,缓存带来的影响。可以在文件名字后面加一个版本号)
减少http请求
为什么要用语义化标签?
增加代码的可读性,以及便于代码维护
便于SEO
让浏览器或者网络爬虫更好地解析以及分析内容
如何适配移动端?(https://www.jianshu.com/p/43dea9fc2eb1)
meta viewport
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximun-scale=1.0; minimun-scale=1.0; user-scalable=no">
图片适配
//使用这个
img {max-width:100%} //最大宽度显示为自身的100%
//不用这个
img {width: 100%} //宽度为外层容器的宽度 图片会被无情地拉伸media 媒体查询
media screen and (min-width:1000px) {
body{
background:red;
}
}动态rem方案(跟媒体查询配合,实现响应式布局)
· 为html设置基准值 font-size:100px
·页面上的使用,margin:500px 400px; => margin:5rem 4rem; 因为rem是相对根html计算的 x/100 = ?rem
·根据当前屏幕的宽度和设计稿的宽度,算出html的基准值 假设当前屏幕宽度为375px 设计稿上是640px
当前屏幕宽度/设计稿宽度 = x / 100 => x = 当前屏幕宽度/设计稿宽度*100 = 58.59375 px
动态计算 js代码(function (){
const desWid = 640
const winWid = document.documentElement.clientWidth
const oMain = document.getElementById('main')
const ratio = winWid / desWid
if(winWid > desWid) {
oMain.style.width = desWid + 'px'
oMain.style.margin = '0 auto'
return
}
oMain.style.fontSize = ratio*100 + 'px'
} ())
除了px还有什么单位?都如何计算?
任意浏览器的默认字体高都是16px。
px:相对于显示屏分辨率而言
em: 相对于父元素 .father{font-size:16px;} .son{font-size:2em} 2em = 2*16
为了简化演算,在body上设置font-size:62.5%,1em = 16*62.5% = 10px , 12px = 1.2em, 16px = 1.6em
重新计算那些被放大的字体的em数值。避免字体大小的重复声明。(例如,#content{font-size:1.2em} #content p {font-size:1em // 1.2*1 = 1.2em = 12px 第一个em是继承font-size:62.5% 第二个是继承#content的})rem:相对于html根元素 html{font-size:20px;} .div{font-size:2rem} 2rem = 2*20
rpx: 微信小程序(规定屏幕宽为750rpx)
如何实现0.5px的边框?
用transform:scale(0.5)
下边框有线
<style>
<style>
div{
width: 200px;
height: 200px;
position: relative;
background-color: pink;
}
div::before{
content: '';
position: absolute;
top: -50%;
bottom: -50%;
left: -50%;
right: -50%;
border-bottom: 1px solid black;
transform: scale(0.5);
}
</style>
</style>
<div>11</div>
四条边都有线
<style>
div{
width: 200px;
height: 200px;
position: relative;
background-color: pink;
}
div::before{
content: '';
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border: 1px solid black;
transform-origin: 0 0;
/* 设置元素基点 x和y坐标 */
transform: scale(0.5);
}
</style>
用渐变写一个
<style>
div{
width: 200px;
height: 200px;
position: relative;
background-color: pink;
}
div::after{
content: ' ';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1px;
background-image:linear-gradient(0deg, transparent 50%, black 50%)
}
</style>
写个波浪线
<style>
div{
height: 0.25em;
width: 20rem;
background-size: 0.5em 0.5em;
background-image: linear-gradient(45deg, transparent 45%, red 55%, transparent 60%), linear-gradient(135deg, transparent 45%, red 55%, transparent 60%);
background-repeat: repeat-x;
}
</style>
如何禁止用户缩放?
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
缩放系数是0.0-1.0 用户缩放选项是yes|no
ios10之后不接受meta标签,监听gesturestart,阻止默认事件
document.addEventListener('gesturestart',function(e) {
e.preventDefault()
})
如何禁止用户全选文字内容?
法一:css
body {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
法二:js
在需要禁止的dom加上这句
ontouchstart="return false;"
备注:手机uc浏览器,meta标签的name=browsermode content= application 这样就无法调起长菜单
以上是关于前端开发必会的HTML/CSS硬知识的主要内容,如果未能解决你的问题,请参考以下文章
前端必会的 HTML+CSS 常用技巧 之 虚线的特殊实现方式
前端必会的 HTML+CSS 常用技巧 之 移动端 1px 边框
前端必会的 HTML+CSS 常用技巧 之 移动端 1px 边框