css
calc()
- 语法
- width:calc(100% - 80px);
- 此calc()函数用一个表达式作为它的参数,用这个表达式的结果作为值。
- 此表达式可以是(+ - * /)操作符的组合,规定运算符的左右必须有空白符。
- 例子
-
/* 使用指定的外边距指定一个对象 */ .banner { position: absolute; /* fallback for browsers which still doesn't support for `calc()` */ left: 5%; width: 90%; /* overwrite, if the browsers support for `calc()`*/ left: calc(40px); width: calc(100% - 80px); border: 1px solid black; background-color: #f00; text-align: center; } -
<div class="banner">this is a banner</div> -
/* 设置内部元素不超出外部元素的范围 */ input{ padding: 2px; display: block; width: 98%; /* fallback for browsers without support for calc() */ width: calc(100% - 1em); } #formbox { width: 130px; /* fallback for browsers without support for calc() */ width: calc(100% / 6); border: 1px solid black; padding: 4px; } -
<form> <div id="formbox"> <label>Type something:</label> <input type="text"> </div> </form> -
/* 使用CSS变量来嵌套 calc() */ .foo { --widthA: 100px; --widthB: calc(var(--widthA) / 2); --widthC: calc(var(--widthB) / 2); width: var(--widthC); /* 在所有的变量都被展开后, widthC 的值就会变成 calc( calc( 100px / 2) / 2), 简而言之:一个 calc() 里面的 calc() 就仅仅相当于是一个括号。 */ }
-
视口单位 vw、vh
- pc端,视口指的是浏览器的可视区域。
- 移动端,涉及三个视口:Layout Viewport(布局视口)、Visual Viewport(视觉视口)、Ideal Viewport(理想视口)。
- 视口单位的“视口”,pc端指浏览器的可视区域;移动端指Layout Viewport。
- 视口单位主要包括以下4个:
- vw: 1vw等于视口宽度的1%
- vh: 1vh等于视口高度的1%
- vmin: 选取vw、vh中最小的那个
- vmax: 选取vw、vh中最大的那个
- vh和vw:相对于视口的高度和宽度,而不是父元素的。
-
/* 比如:浏览器高度950px,宽度为1920px, 1 vh = 950px/100 = 9.5 px,1vw = 1920px/100 =19.2 px。 */ .left { float: left; width: 50vw; height: 20vh; background-color: blue; text-align: center; line-height: 20vh; font-size: 3rem } .right { float: right; width: 50vw; height: 20vh; background-color: green; text-align: center; line-height: 20vh; font-size: 3rem }
- 视口单位主要包括以下4个:
BFC
- what is BFC?
BFC: 块级格式上下文
以下条件都会为他们的内容创建新的BFC
- 浮动元素
- 绝对/固定定位元素
- 非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions
- 以及overflow值不为"visiable"的块级盒子
- BFC 渲染规则
- 两个块同一个BFC会造成外边距折叠
- BFC的区域不会与浮动元素的box重叠
- BFC是一个独立的容器,外面的元素不会影响里面的元素
- 计算BFC高度的时候浮动元素也会参与计算
- 应用场景
-
防止浮动导致父元素高度塌陷
-
避免外边距折叠 两个块同一个BFC会造成外边距折叠,如果对这两个块分别设置BFC,那么边距重叠的问题就不存在了。
position
- css布局的三种机制
页面布局的核心:使用CSS来摆放盒子的位置
css提供了3种机制来设置盒子的摆放位置,分别是:普通流、浮动、定位
-
普通流(标准流):
- 页面内的标签元素按照从上到下,从左到右的顺序排列
-
浮动:
- 让盒子从普通流中浮起来,多个盒子(div)水平排列成一行
-
定位:
- 将盒子定在一个位置,可以使其漂浮在其它盒子上面,而不影响其它盒子
-
认识定位
概念:定位 = 定位模式 + 边偏移,将盒子定在某一位置
-
边偏移:
- top:定义元素相对于其父元素上边线的距离
- bottom:定义元素相对于其父元素下边线的距离
- left:定义元素相对于其父元素左边线的距离
- right:定义元素相对于其父元素右边线的距离
- 边偏移需要和定位模式联合使用,单独使用无效
- top和bottom不能同时使用
- left和right不能同时使用
-
定位模式(分类): 选择器 {position: 属性值 }
- static:静态定位,默认定位方式
- relative:相对定位,自恋,相对于其原标准流的位置进行定位
- absolute:绝对定位,拼爹,相对于其上一个已定位的父元素定位
- fixed:固定定位,浏览器,相对于浏览器窗口定位
- sticky:粘性定位,relative和fixed的结合体
-
定位模式间的区别
- 静态定位(static) 元素默认的定位方式,不脱标,且边偏移无效
- 相对定位(relative)
相对定位不脱标
- 以自己在标准流位置左上角为基点 +边偏移属性定位元素的位置
- 原来在标准流中的区域继续占有,后面的盒子仍以标准流方式对待它 与浮动对比
- 浮动:多个块级元素在一行显示,脱离标准流
- 相对定位:移动盒子位置,不脱标
- 绝对定位(absolute)
有两个重要概念:
- 完全脱标,不占位置
- 父元素要有定位(相对、绝对、固定定位) 定位口诀:子绝父相
- 固定定位(fixed) 完全脱标,不占位置 只认浏览器的可视窗口
- 粘性定位(sticky) relative + fixed
-
定位的扩展(position)
3.1. 绝对定位的盒子居中
绝对定位不能通过设置`margin:auto设置水平居中
- 水平居中
- 垂直居中
- 水平垂直居中
3.2. 粘性定位
example: MDN
当元素在屏幕内,表现为relative,就要滚出显示器屏幕时,表现为fixed
<style>
article {
max-width: 600px;
margin: 0 auto;
}
article h4,
article footer {
position: -webkit-sticky;
position: sticky;
}
article h4 {
top: 0;
z-index: 1;
}
article footer {
bottom: 50vh;
z-index: -1;
}
</style>
<article>
<section>
<h4>123</h4>
<content>...</content>
<footer>321</footer>
</section>
<section>
<h4>456</h4>
<content>...</content>
<footer>654</footer>
</section>
</article>
- 堆叠顺序(z-index)
在使用定位布局时,可能出现盒子堆叠的情况
应用z-index层叠等级属性来调整盒子的堆叠顺序
z-index的特性如下:
- 属性值:正整数、负整数、0;默认值为0,值越大,盒子越靠上
- 属性值相同,按照书写顺序,后来者居上
- 数字后无单位
- 只能用于相对定位、绝对定位、固定定位的元素,其它元素无效
REM 布局
rem布局的核心就是设置好根元素的font-size
- rem计算
- 适配过程
width: 640px;
- 人为将UI的psd图等分(20份)
- 计算一份的宽度1rem = 640/20 = 32px
- 设置html根元素的font-size = 32px;
- 页面中css的尺寸统一使用rem单位表示
- less 语法
2.1. 介绍
less预处理器: 依然使用css语法,引入变量,混合,运算,嵌套等功能,简化css编写,降低维护成本
2.2. 变量
- 语法:@变量名:值 @sz: 100px; p { font-size: @sz; } // 可运算 h2 { font-size: @sz - 2; }
2.3. 嵌套
.box {
p {
font-size: 14px;
}
ul {
list-style: none;
li {
float: left;
}
}
}
2.4. 混合(函数)
- 定义和调用 // 定义: #函数名() {} / .函数名() {} #public() { width: 200px; height: 200px; } .public() { width: 200px; height: 200px; } div { // 调用 #public() } h2 { .public() }
- 传参/默认值 #public(@w:200px, @h:200px) { width: @w; height: @h; } div { #public(500px, 600px) }
2.5. 在浏览器中预览less文件
- 在html中引入less文件 /** 引入less文件 **/
- 在html中引入less.js文件 // 引入less.js文件
- 媒体查询
- 媒体查询 通过查询当前属于哪种设备,让网页能够在不同设备下正常预览
- 媒体类型
将不同的设备划分为不同的类型,称为媒体类型
- all 所有设备
- print 打印设备
- screen 电脑/平板/手机屏幕
- 媒体特性
- width
- height
- max-width / max-height
- min-width / min-height
- 语法关键字
@media not|only 媒体类型 and (特性条件)
-
and: 将多个媒体特性链接到一块,相当于且
-
not: 排除某个媒体特性,相当于非,可省略
-
only: 指定某个特定的媒体类型,可省略 /** 通过不同的屏幕大小设置 font-size */
/* 功能:计算1rem等于多少font-size的大小 参数: @w 表示屏幕的宽度 @c 表示分割的份数 */ .adapter(@w,@c) { html { font-size: @w/@c; } }
@media screen and (width:320px) { .adapter(320px,20); }
@media screen and (width:360px) { .adapter(360px,20); } ...
-
-
实战项目
-
目录结构
index.html css --adapter.css --adapter.less --base.css --index.css --index.less
-
index.html
Document
<!-- 全场优惠S --> <div class="all-special"> <!-- 标题 --> <div class="title"> <h4 class="fl">全场优惠</h4> <span class="fr">1/1</span> </div> <!-- 内容 --> <div class="content"> <!-- 上 --> <div class="top"> <p>全场满300减10</p> <p>双十一特价优惠全场满就减</p> <p><span class="icon-time"></span>14-11-12 20:12 至 14-11-12 23:12</p> <a href="#">即将开始</a> <img src="./images/sale.png" alt=""> </div> <!-- 下 --> <div class="bottom"> <a href="#"> <span class="icon-edit"></span>编辑 </a> <i></i> <a href="#"> <span class="icon-share"></span>分享 </a> </div> </div> </div> <!-- 全场优惠E --> -
adapter.less
/* 功能:计算1rem等于多少font-size的大小 参数: @w 表示屏幕的宽度 @c 表示分割的份数 */ .adapter(@w,@c) { html { font-size: @w/@c; } }
@media screen and (width:320px) { .adapter(320px,20); } @media screen and (width:360px) { .adapter(360px,20); } @media screen and (width:375px) { .adapter(375px,20); } @media screen and (width:414px) { .adapter(414px,20); } @media screen and (width:412px) { .adapter(412px,20); }
-
index.less
.main { width: 100%; max-width: 640px; min-width: 320px; margin:0 auto; } // 默认按照640/20 html { font-size: 32px; }
// 顶部导航 .top-title { img { width: 100%; } }
// ----------------------将有关的尺寸全部转换为rem------------------------
// 全场优惠 .all-special { padding:0 26/32rem; // 标题 .title { height: 78/32rem; line-height: 78/32rem; font-size: 28/32rem; span { color: #666; } } // 下 .bottom { height: 80/32rem; background: #fff; display: flex; i { height: 48/32rem; width: 1px; background: #666; display: block; margin-top: 15/32rem; } a { flex: 1; text-align: center; line-height: 80/32rem; font-size: 26/32rem; span { color: #55bc75; } } } } }
移动端1px解决方案
产生原因: DPR(devicePixelRatio) 设备像素比
- window.devicePixelRatio = 物理像素/css像素
目前主流屏幕DPR=2(iphone8)、3(iphone 8 pluse)
设备的物理像素要实现1px,而DPR=2,故css的像素只能是0.5
ios 8+系统支持,安卓系统不支持
一、使用box-shadow实现***
box-shadow: 0 -1px 1px -1px #e5e5e5, //上边线
1px 0 1px -1px #e5e5e5, //右边线
0 1px 1px -1px #e5e5e5, //下边线
-1px 0 1px -1px #e5e5e5; //左边线
优点: 使用简单,圆角可实现
缺点: 模拟实现
二、使用伪元素
- 单条border .set-onepx { position: relative; &::after { content: ''; position: absolute; display: block; background-color: #000; width: 100%; height: 1px; transform: scale(1, 0.5); // Y方向缩小0.5倍 top: 0; left: 0; } }
- 四条border .set-onepx-all { position: relative; &::after { content: ''; position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform-origin: left top; transform: scale(0.5); box-sizing: border-box; border: 1px solid #000; border-radius: 4px; } }
- 总结:
- 全机型兼容,实现了真正的1px,而且可以圆角
- 暂用了after伪元素,影响清除浮动
三、设置viewport的scale值*
利用viewport + rem + js实现
<html>
<head>
<title>1px question</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<style>
html {
font-size: 1px;
}
* {
padding: 0;
margin: 0;
}
.top_b {
border-bottom: 1px solid #E5E5E5;
}
.a,.b {
box-sizing: border-box;
margin-top: 1rem;
padding: 1rem;
font-size: 1.4rem;
}
.a {
width: 100%;
}
.b {
background: #f5f5f5;
width: 100%;
}
</style>
<script>
var viewport = document.querySelector("meta[name=viewport]");
//下面是根据设备像素设置viewport
if (window.devicePixelRatio == 1) {
viewport.setAttribute('content', 'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');
}
if (window.devicePixelRatio == 2) {
viewport.setAttribute('content', 'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');
}
if (window.devicePixelRatio == 3) {
viewport.setAttribute('content', 'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');
}
var docEl = document.documentElement;
var fontsize = 32* (docEl.clientWidth / 750) + 'px';
docEl.style.fontSize = fontsize;
</script>
</head>
<body>
<div class="top_b a">下面的底边宽度是虚拟1像素的</div>
<div class="b">上面的边框宽度是虚拟1像素的</div>
</body>
</html>
CSS3
一、2D 转换
可实现元素的位移、旋转、缩放、倾斜
- translate-位移
语法: transform:translate(x,y)
- 代码 盒子居中总结 .box { position: relative; width: 600px; height: 600px; } .item1 { position: absolute; width: 100px; height: 100px; background: #0f0; /* 方案一 / / left: 0; right: 0; top: 0; bottom: 0; margin: auto; / / 方案二 / / left: 50%; top: 50%; margin-left: -50px; margin-top: -50px; / / 方案三 */ left: 50%; top: 50%; transform: translate(-50%, -50%); }
- 总结
- translate最多设置两个值,x水平,y垂直
- translate偏移的位置,参照自身原有的位置
- translate设置负值,会实现逆向移动
- 设置一个值,只有水平方向有效
- 可以设置百分比,百分比参照的是自身的大小
- 轮子滚动
- rotate-旋转
语法: transform:rotate(+-deg)
-
代码 .item { width: 100px; height: 100px; /* 顺时针45deg, 逆时针-45deg */ transform: rotate(-90deg); background: #000; }
-
总结
- 单位: deg
- 正值: 顺时针
- 负值: 逆时针
- transform-origin: 旋转源点
语法: transform-origin: 水平 垂直;
- 代码 .item { transform-origin: left top; }
- 总结
- 默认按照中心点旋转
- 水平: left|center|right|px|%
- 垂直: top|center|bottom|px|%
- scale-缩放
语法: transform:scale(number,number);
- 代码 .item { width: 100px; height: 100px; margin: 100px auto; transform: scale(2); background: #000; }
- 总结
- 最多设置两个值,第一个表缩放宽度,第二个表高度
- 0~1 表缩小,>1 表放大
- 只有一个值,表示宽高一起缩放
- skew-倾斜
语法: transform:skew(deg,deg);
- 代码 .item { width: 100px; height: 100px; margin: 100px auto; transform: skew(45deg, 0deg); background: #000; }
- 总结
- 值1表示左右倾斜,值2表示上下倾斜
- 单位deg,可以是负值
二、3D 转换
- 位移
语法:
-
transform: translateX(100px);
-
transform: translateY(100px);
-
transform: translateZ(100px);
-
代码
-
总结
- perspective:px;设置3D透视,可实现进大远小
- 给设置了transform属性元素的上级设置
- 透视
语法: perspective:600px;
- 总结
- 设置3D透视,可实现近大远小
- 主要给设置了transform属性元素的上级元素设置透视
- 旋转
语法: 围绕XYZ轴旋转
- transform: rotateX(deg)
- transform: rotateY(deg)
- transform: rotateZ(deg)
-
代码
-
立方体案例 body: 设置 perspective:1000px;实现近大远小效果 父元素.box: 设置
- transform-style:preserve-3d;通知浏览器此元素按照3D效果渲染
- transition: 2s;开启过渡效果 XYZ轴: 永远都是顺时针旋转为正
三、动画-animation
语法:
- animation-name: name(动画名称);
- animation-duration: 时间(s/ms);
- animation-timing-function: linear(匀速)|ease(慢快慢)|ease-in(缓慢开始)|ease-out(缓慢结束)ease-in-out(慢开慢结);
- animation-delay: 时间(s/ms);
- animation-iteration-count: 次数|infinite(无限);
- animation-play-state: paused(暂停)|running(运行);
- animation: name 1s infinite 3s linear;
-
实例-地图大数据热点
```html <div class="origin"> <span class="shire shire1"></span> <span class="shire shire2"></span> </div>
浏览器的回流与重绘(Reflow&Repaint)
一、写在前面
预备知识
- 浏览器使用流式布局模型(Flow Based Layout)
- 浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了Render Tree
- 有了Render Tree,我们就知道了所有节点的样式,然后计算它们在页面上的大小和位置,最后把节点绘制到页面上
- 由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,它们可能需要多次计算,通常要花3倍同等元素的时间,因此要避免使用table布局
一句话: 回流必将引起重绘,重绘不一定会引起回流
二、回流 (Reflow)
当Render Tree中部分或全部元素的尺寸、结构或某些属性发生变化时,浏览器重新渲染部分或全部文档的过程称为回流
- 会导致回流的操作:
- 页面首次渲染
- 浏览器窗口大小发生改变
- 元素尺寸或位置改变
- 元素内容变化(文字数量/图片大小等)
- 元素字体大小变化
- 添加或删除可见的DOM元素
- 激活CSS伪类(如: :hover...)
- 查询某些属性或调用某些方法
- 一些常用且会导致回流的属性和方法:
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- scrollIntoView()、scrollIntoViewIfNeeded()
- getComputedStyle()
- getBoundingClientRect()
- scrollTo()
三、重绘 (Repaint)
当页面中元素样式的改变并不影响它在文档流中的位置时(如: color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,此过程称为重绘
四、性能影响
回流比重绘的代价要更高
- 有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也要产生回流
- 现代浏览器会对频繁的回流或重绘操作进行优化
- 浏览器会维护一个队列,将所有引起回流和重绘的操作放入队列中,当队列中的任务数量或时间间隔达到一个阈值时,浏览器将会清空队列,进行一次批处理,这样可将对此回流和重绘变成一次
当访问以下属性后方法时,浏览器会立刻清空队列:
因为队列中可能会有影响到这些属性或方法返回值的操作,所以浏览器会强行清空队列,确保获取的值是最精确的
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- width、height
- getComputedStyle()
- getBoundingClientRect()
五、如何避免
CSS
- 避免使用table布局
- 尽可能在DOM树的最末端改变class
- 避免设置多层内联样式
- 将动画效果应用到position属性为absolute或fixed的元素上
- 避免使用css表达式(如: calc())
JavaScript
- 避免频繁操作样式,最好一次性重写style属性,或将样式列表定义为class并一次性更改class属性
- 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中
- 也可以先为元素设置display:none; 操作结束后再把它显示出来。因为在display属性为none的元素上进行DOM操作不会引发回流和重绘
- 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来
- 对具有复杂动画的元素使用绝对定位absolute,使其脱离文档流,否则就会引起父元素及后续元素频繁回流