目录
一、功能实现
1、吸顶与悬停
position: sticky;
position: -webkit-sticky;
top: 0;
上述代码中,可以通过调整 top 的值来修改元素距离顶部悬停的位置。
【拓展】“position: sticky”
“position: sticky” 是基于用户的滚动位置来定位的。
“position: sticky” 的特性
粘性定位的元素是依赖于用户的滚动,在 position:relative 与 position:fixed 定位之间切换。它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置。
元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位。这个特定阈值指的是 top, right, bottom 或 left 之一,换言之,指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。
“position: sticky” 的踩坑记
- sticky 不会触发 BFC。
- 样式表 z-index 无效,行内 style 写有效。
【注意】 Internet Explorer, Edge 15 及更早 IE 版本不支持 sticky 定位。 Safari 需要使用 -webkit- prefix。
2、设置标签随文字换行移动
css 设置标签随文字换行移动——vertical-alignhttps://blog.csdn.net/mChales_Liu/article/details/123201887
3、一键置灰
一键置灰的 css 代码:
.app-gray {
filter: grayscale(100%);
}
重点在于加在哪里——只需要加在根元素(html)上就好。
【拓展】
- 给根元素添加 class:
document.documentElement.className += ' app-gray'
- 给跟元素添加 style:
const root = document.querySelector(':root') // html
root.style.setProperty('filter', 'grayscale(100%)')
4、列表滑动——抽屉推拉效果
两种思路:
- translate 改变目标的left值实现滑动。
-
@keyframes + animation 改变目标的left值实现滑动。
1⃣️、translate 改变目标的 left 值实现滑动
<template lang="pug">
.test-touch-wrap(style='width:375px;height:40px;position:relative;overflow:hidden;')
.content(
style='width:475px;position:absolute;top:0;left:0;'
ref='touchDom'
@touchstart.stop='touchstart'
@touchmove.stop='touchmove'
@touchend.stop='touchend'
)
.left(style='float:left;width:375px;height:40px;line-height:40px;') 左边的内容
.right(style='float:right;width:100px;height:40px;line-height:40px;') 右边的内容
</template>
<script>
export default {
props: {
itemIndex: {
type: Number,
default: 0
}
},
data () {
return {
screenWidth: document.body.clientWidth,
startPosition: {},
range: {},
setTouchTime: 0,
cancleTouchTime: 0,
target: 100
}
},
methods: {
touchstart (e) {
const { pageX, pageY } = e.changedTouches[0]
this.startPosition = { pageX, pageY }
},
touchmove (e) {
const { pageX, pageY } = e.changedTouches[0]
this.range = {
x: pageX - this.startPosition.pageX,
y: pageY - this.startPosition.pageY
}
if (Math.abs(this.range.x) > Math.abs(this.range.y)) { // 保证是左右滑动
if (this.range.x < 0 && !this.setTouchTime) { // 第一次向右滑动
if (Math.abs(this.range.x) >= this.screenWidth / 2) { // 滑动距离大于等于屏宽的一半
this.$refs.touchDom.style.left = -this.target + 'px'
this.$refs.touchDom.style.transition = 'left 0.3s ease 0s'
this.$emit('cancel-other-touch-state', this.itemIndex) // 取消其兄弟元素的滑动状态
this.setTouchTime++
} else { // 滑动距离小于屏宽的一半
this.$refs.touchDom.style.left = this.range.x + 'px'
}
} else if (this.range.x > 0 && !this.cancleTouchTime && this.$refs.touchDom?.style?.left) { // 第一次向左滑动,且已经处于右滑的状态了
this.cancelCurrentTouchState()
this.cancleTouchTime++
}
}
},
touchend (e) {
if (Math.abs(this.range.x) < this.screenWidth / 2 && !this.setTouchTime && !this.cancleTouchTime) {
this.cancelCurrentTouchState()
}
if (this.setTouchTime) {
this.setTouchTime = 0
}
if (this.cancleTouchTime) {
this.cancleTouchTime = 0
}
},
cancelCurrentTouchState () {
this.$refs.touchDom.style.left = '0px'
this.$refs.touchDom.style.transition = 'left 0.3s ease 0s'
}
}
}
</script>
【注意】一般 app 端的这种需求会比 pc 端的多。在 app 端实现时,要注意以下几点:
- template 模板里,最大宽度应该是动态屏宽(我暂时写了具体值是为了效果),超出这个屏宽的部分要隐藏掉。
- template 模板里,左右的内容部分用插槽实现更加灵活。
2⃣️、@keyframes + animation 改变目标的 left 值实现滑动
先定义好动画样式:
<style>
.set-touch {
animation: set_touch 0.8s ease 0s 1 forwards;
}
.cancel-touch {
animation: cancel_touch 0.3s ease 0s 1 forwards;
}
@keyframes set_touch{
from {left: 0px;}
to {left: -176px;}
}
@keyframes cancel_touch{
from {left: -176px;}
to {left: 0px;}
}
</style>
然后就是 js 的实现,主要逻辑是,动态增删切换 class。
5、去除滚动条
支持多端兼容:
@cancle-scroll: {
&::-webkit-scrollbar {
display: none;
width: 0px;
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
opacity: 0;
&-thumb {
background: rgba(0,0,0,0);
}
}
}
6、高度塌陷
解决办法:
- 给父元素添加固定高度。不过,不适合高度自适应的布局。
- 给父元素添加overflow:hidden。不过,不适合与定位的一起使用。
- 给所有的浮动盒子最后添加一个空的标签,例如 div,且添加声明 clear:both。不过,多了很多空的标签,造成代码冗余。
- 给高度塌陷的元素添加 min-height: 100vh 样式,让其内容充满屏幕。(推荐)
- 万能清除浮动法。(推荐)
万能清除浮动法:
.clearfix () {
&:after {
content: '';
display: block;
height: 0;
visibility: visible;
clear: both;
}
}
二、CSS 防御
一切使表现和行为偏离预期效果的情景都需要防御。这些问题往往是由于终端环境的多样化造成的。
0、CSS变量默认值
CSS 变量可以实现动态控制元素属性,变量默认值可以保证变量值异常时页面依然能运行。
.box {
color: var(--test-var, blue); /* 定义 --test-var 的默认值是:蓝色 */
}
在上面的 CSS 函数中,函数接受两个参数:
- 第一个参数:自定义属性的名称。
- 第二个参数:(可选的)表示备用值,当自定义属性值无效时生效。
【注意】这个 CSS 变量的默认值 仅对支持 CSS 自定义属性 的浏览器有效,需要考虑浏览器对CSS 自定义属性的兼容性。
1、margin
需要防止元素与元素之间由于挤压空间而造成的重叠等情况。
.desc{
margin-right: 1rem;
}
2、长文本
对长文本的处理无非两种:
- 支持换行
- 限制显示几行,超出省略号
- 省略现示
接下来,假设我们要对一个 width 是 300 像素的文本输入框做长文处理。
若支持换行:
overflow-wrap: break-word;
// 若是flex布局,可以用下面这行代码
flex-wrap: wrap;
若是限制现显示3行 :
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
省略现示:
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
3、滚动
(1)、锁定滚动链接
overscroll-behavior 属性是 overscroll-behavior-x 和 overscroll-behavior-y 的简写。
overscroll-behavior 属性用来:控制元素滚动到边界时的表现。
什么叫“元素滚动到边界时的表现”呢?下面我们来理解一个概念 “滚动链”:
滚动链 —— 在 CSS 世界里,滚动也有冒泡机制,当内部元素滚动到边界时,如果继续滚动,会带动外层祖先元素发生滚。也可以叫做 滚动冒泡 或 滚动穿透。overscroll-behavior 属性可以设置是否阻止该行为。这就好比,在 JS 的事件冒泡机制里,你可以通过 event.stopPropagation 方法去阻止冒泡的发生一样。
{overscroll-behavior: contain | none | auto}
- auto:默认效果
- contain:设置这个值后,默认的滚动边界行为不变(“触底”效果或者刷新),但是临近的滚动区域不会被滚动链影响到,比如对话框后方的页面不会滚动。
- none:临近滚动区域不受到滚动链影响,而且默认的滚动到边界的表现也被阻止。防止节点本身的滚动效果(例如:Android 炫光或 iOS 回弹)
实践:
<div class='one'>
<div class='two'>
<div class='three'>
<div class='four'></div>
</div>
</div>
</div>
.one {
width: 500px;
height:400px;
background: aliceblue;
overflow: scroll;
}
.two {
width:450px;
height:500px;
background: antiquewhite;
margin: 0 auto;
}
.three {
width:200px;
height:200px;
background: darkkhaki;
margin: 0 auto;
overflow: scroll;
}
.four {
width:150px;
height:300px;
background: cadetblue;
margin: 0 auto;
}
现在给 class 是 three 的 div 设置上 overscroll-behavior 属性为 contain:
.three {
width:200px;
height:200px;
background: darkkhaki;
margin: 0 auto;
overflow: scroll;
overscroll-behavior: contain;
}
(2)、合理使用滚动条属性
overflow 属性有两个作用很相近的属性值:
- scroll:当内容大于所占空间时滚动展示。无论滚动到的内容是否为超出容器空间的内容,始终都会展示滚动条。
- auto:当内容大于所占空间时滚动展示。auto 属性会分辩条件——只有滚动到超出容器空间的内容时,才会展示滚动条。
所以,建议使用 “overflow: auto;” 来设置滚动条。
(3)、预留滚动条空间,避免重排
设想这样一个场景:有一个宽度100vw,高度为100vh的容器盒子,容器内展示商品卡片,滑动到页面底部时,触发滑动加载,当触发懒加载时,容器内商品卡片占用的高度已经超出100vh,依据外层容器设置的overflow:auto,内容超出时会展示滚动条,滚动条的出现,使得页面不得不给滚动条让出一定的宽度,这个切换的场景中,由于不得不给滚动条让位置,最外层的元素发生了元素宽度变化,产生了重排的效果,有没有可能避免这一次不必要的重排呢?答案是有的。
使用 scrollbar-gutter 属性来:预留滚动条空间,避免重排。
scrollbar-gutter 属性用来:为滚动条保留空间,防止在内容增长时不必要的布局更改。同时在不需要滚动时避免不必要的视觉效果(不晃动)。
{scrollbar-gutter: auto | stable | both-edges}
- auto:就是默认的表现。没有滚动条的时候,内容尽可能占据宽度,有了滚动条,可用宽度减小。
- stable:如果 overflow 属性计算值不是 visible,则提前预留好空白区域,这样滚动条出现的时候,整个结构和布局都是稳定的。
- both-edges:这个是让左右两侧同时预留好空白区域,目的是让局部绝对居中对称。
【拓展】scrollbar-color 和 scrollbar-width
4、图片
图片的添加就下面两种方式:
- css 添加背景
- img 标签添加图片
(1)、如何防止图片被拉伸或压缩呢?
若是 css 添加背景:
.picture {
background-size: cover;
}
若是 img 标签添加图片:
.picture {
object-fit: cover;
}
(2)、图片上的文字
若要在图片上层展示文字,需考虑:如果图片加载失败,而外层容器的背景色和文字颜色接近,那么文字的展示的效果就不理想了。
解决思路:给容器设置背景色,当图片加载失败时,文字的背景色直接变为容器的背景色,让文字正常显示。至于图片加载失败时左上角的“破图”标记,可以使用伪类进行遮挡美化。
(3)、图片最大宽度
需要对 img 进行 resetCss(样式重置),以避免:当给固定宽高容器设置背景图时,如果背景图尺寸超过容器宽高,图片会溢出。
img {
max-width: 100%;
object-fit: cover;
}
6、弹性元素尺寸 min-* 或者 max-*
使用弹性元素尺寸 min-* 或者 max-* 可以 自动适应部分内容所占空间过大或过小的布局。
7、媒体查询 @media
CSS中的条件判断——根据不同的屏幕尺寸加载该尺寸所对应的样式。
例如:
/* 将 body 的背景色设置为蓝色 */
div {
background-color: black;
}
/* 在小于或等于 800 像素的屏幕上,将背景色设置为黄色 */
@media screen and (max-width: 750px) {
div {
background-color: blue;
}
}
/* 在 600 像素或更小的屏幕上,将背景色设置为红色 */
@media screen and (max-width: 300px) {
div {
background-color: green;
}
}
/* 针对 280px 宽度 */
@media screen and (device-width: 280px){
div {
background-color: red;
}
}
8、粘性定位
position 的粘性定位指的是:通过用户的滚动,元素的 position 属性在 position:relative 与 position:fixed 定位之间切换。
应用场景:滚动吸顶
案例:参见本文的 “吸顶与悬停”
9、浏览器兼容性 CSS 请勿批量处理
根据W3C标准,批量分组选择选择器,如果分组中,其中一个无效,那么整个选择器都将会失效。因此,在遇到浏览器兼容属性时,切勿批量组合书写。(Selectors Level 4)
【参考】