使用overflow-scrolling支持弹性滚动
iOS页面
非body元素
的滚动操作会非常卡(Android不会出现此情况),通过overflow-scrolling:touch
调用Safari原生滚动来支持弹性滚动,增加页面滚动的流畅度
使用transform启动GPU硬件加速
有时执行动画可能会导致页面卡顿,可在特定元素中使用硬件加速来避免这个问题
使用attr()抓取data-*
在标签上自定义属性
data-*
,通过attr()
获取其内容赋值到content
上
场景:提示框
<div class="bruce flex-ct-y" data-title="使用attr()抓取节点属性">
<a class="hover-tips btn-1" href="https://www.baidu.com" data-msg="Hello World">提示框</a>
<a class="hover-tips btn-2" href="https://www.baidu.com"></a>
</div>
<style>
.hover-tips {
position: relative;
padding: 0 20px;
border-radius: 10px;
height: 40px;
background-color: #66f;
line-height: 40px;
color: #fff;
& + .hover-tips {
margin-top: 10px;
}
&.btn-1 {
&::after {
position: absolute;
left: 0;
top: 0;
border-radius: 5px;
width: 100%;
height: 100%;
background-color: rgba(#000, .5);
opacity: 0;
text-align: center;
font-size: 12px;
content: attr(data-msg);
transition: all 300ms;
}
&:hover::after {
left: calc(100% + 20px);
opacity: 1;
}
}
&.btn-2:empty::after {
content: attr(href);
}
}
</style>
使用:valid和:invalid校验表单
``使用伪类
:valid
和:invalid
配合pattern
校验表单输入的内容
使用pointer-events禁用事件触发
通过
pointer-events:none
禁用事件触发(默认事件、冒泡事件、鼠标事件、键盘事件等),相当于``的disabled
场景:限时点击按钮(发送验证码倒计时)、事件冒泡禁用(多个元素重叠且自带事件、a标签跳转)
<div class="bruce flex-ct-x" data-title="使用pointer-events禁用事件触发">
<a class="disabled-trigger" href="https://www.baidu.com">点我</a>
</div>
<style>
.disabled-trigger {
padding: 0 20px;
border-radius: 10px;
height: 40px;
background-color: #66f;
pointer-events: none;
line-height: 40px;
color: #fff;
}
</style>
使用+或~美化选项框
``使用
+
或~
配合for
绑定radio
或checkbox
的选择行为
场景:选项框美化、选中项增加选中样式
<div class="bruce flex-ct-x" data-title="使用+或~美化选项表单">
<ul class="beauty-selection">
<li>
<input id="fed-engineer" type="radio" name="radioName" hidden>
<label for="fed-engineer"></label>
<span>前端工程师</span>
</li>
<li>
<input id="bed-engineer" type="radio" name="radioName" hidden>
<label for="bed-engineer"></label>
<span>后端工程师</span>
</li>
<li>
<input id="fsd-engineer" type="radio" name="radioName" hidden>
<label for="fsd-engineer"></label>
<span>全栈工程师</span>
</li>
</ul>
</div>
<style>
.beauty-selection {
display: flex;
li {
display: flex;
align-items: center;
& + li {
margin-left: 20px;
}
}
input:checked + label {
background-color: #f90;
}
label {
margin-right: 5px;
padding: 2px;
border: 1px solid #f90;
border-radius: 100%;
width: 18px;
height: 18px;
background-clip: content-box;
cursor: pointer;
transition: all 300ms;
&:hover {
border-color: #09f;
background-color: #09f;
box-shadow: 0 0 7px #09f;
}
}
span {
font-size: 16px;
}
}
</style>
使用:focus-within分发冒泡响应
表单控件触发
focus
和blur
事件后往父元素进行冒泡,在父元素上通过:focus-within
捕获该冒泡事件来设置样式
场景:登录注册弹框、表单校验、离屏导航、导航切换
<div class="bruce flex-ct-x" data-title="使用:focus-within分发冒泡响应">
<form class="bubble-distribution">
<h3>注册</h3>
<div class="accout">
<input type="text" placeholder="请输入手机或邮箱" pattern="^1[3456789]\d{9}$|^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$" required>
<img src="https://b-gold-cdn.xitu.io/v3/static/img/greeting.1415c1c.png">
</div>
<div class="password">
<input type="password" placeholder="请输入密码(6到20位字符)" pattern="^[\dA-Za-z_]{6,20}$" required>
<img src="https://b-gold-cdn.xitu.io/v3/static/img/blindfold.58ce423.png">
</div>
<div class="code">
<input type="text" placeholder="请输入邀请码(6位数字)" pattern="^[\d]{6}$" maxLength="6" required>
<button type="button">查询</button>
<img src="https://b-gold-cdn.xitu.io/v3/static/img/greeting.1415c1c.png">
</div>
<img src="https://b-gold-cdn.xitu.io/v3/static/img/normal.0447fe9.png">
<ul>
<li>
<input id="male" type="radio" name="sex">
<label for="male">Boy</label>
</li>
<li>
<input id="female" type="radio" name="sex">
<label for="female">Girl</label>
</li>
</ul>
<button type="button">注册</button>
</form>
</div>
<style>
.bruce {
background-color: #999;
}
.bubble-distribution {
position: relative;
margin-top: 50px;
padding: 25px;
border-radius: 2px;
width: 320px;
background-color: #fff;
h3 {
font-size: 16px;
color: #333;
}
div {
margin-top: 10px;
}
img {
position: absolute;
left: 50%;
bottom: 100%;
margin: 0 0 -20px -60px;
width: 120px;
}
ul {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
height: 30px;
line-height: 30px;
}
li {
position: relative;
width: 45%;
transition: all 300ms;
&:focus-within {
background: linear-gradient(90deg, #09f 50%, transparent 0) repeat-x,
linear-gradient(90deg, #09f 50%, transparent 0) repeat-x,
linear-gradient(0deg, #09f 50%, transparent 0) repeat-y,
linear-gradient(0deg, #09f 50%, transparent 0) repeat-y;
background-position: 0 0, 0 100%, 0 0, 100% 0;
background-size: 8px 1px, 8px 1px, 1px 8px, 1px 8px;
animation: move 500ms infinite linear;
}
}
input[type=text],
input[type=password] {
padding: 10px;
border: 1px solid #e9e9e9;
border-radius: 2px;
width: 100%;
height: 40px;
outline: none;
transition: all 300ms;
&:focus:valid {
border-color: #09f;
}
&:focus:invalid {
border-color: #f66;
}
}
input[type=radio] {
position: absolute;
width: 0;
height: 0;
&:checked + label {
border: 3px solid transparent;
background-color: #09f;
color: #fff;
}
}
label {
display: block;
border-bottom: 1px solid #ccc;
width: 100%;
background-clip: padding-box;
cursor: pointer;
text-align: center;
transition: all 300ms;
}
button {
margin-top: 10px;
border: none;
border-radius: 2px;
width: 100%;
height: 40px;
outline: none;
background-color: #09f;
cursor: pointer;
color: #fff;
transition: all 300ms;
}
.accout,
.password,
.code {
img {
display: none;
margin-bottom: -27px;
}
&:focus-within {
img {
display: block;
}
& ~ img {
display: none;
}
}
}
.code {
display: flex;
justify-content: space-between;
button {
margin-top: 0;
}
input {
&:not(:placeholder-shown) {
width: 70%;
& + button {
width: 25%;
}
}
&:placeholder-shown {
width: 100%;
& + button {
width: 0;
opacity: 0;
}
}
}
}
}
@keyframes move {
to {
background-position: 6% 0, -6% 100%, 0 -6%, 100% 6%;
}
}
</style>
使用:hover描绘鼠标跟随
将整个页面等比划分成小的单元格,每个单元格监听
:hover
,通过:hover
触发单元格的样式变化来描绘鼠标运动轨迹
场景:鼠标跟随轨迹、水波纹、怪圈
.bruce(data-title="使用:hover描绘鼠标跟随")
ul.mouse-following
- for (var i = 0; i < 500; i++)
li
<style>
@function random-num($max, $min: 0, $u: 1) {
@return ($min + random($max)) * $u;
}
.mouse-following {
display: flex;
overflow: hidden;
flex-wrap: wrap;
height: 100%;
cursor: pointer;
li {
position: relative;
width: 30px;
height: 30px;
&::before {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
border-radius: 100%;
background-color: transparent;
content: "";
transform: scale3d(.1, .1, 1);
transition: all 500ms ease-in;
}
&:hover {
&::before {
transform: scale3d(1.8, 1.8, 1.8);
transition: transform 0s;
}
}
@for $i from 1 through 500 {
&:nth-child(#{$i}):hover {
&::before {
background-color: rgba(random-num(255), random-num(255), random-num(255), .8);
}
}
}
}
}
</style>
使用max-height切换自动高度
通过
max-height
定义收起的最小高度和展开的最大高度,设置两者间的过渡切换
场景:隐藏式子导航栏、悬浮式折叠面板
<div class="bruce flex-ct-x" data-title="使用max-height切换自动高度">
<ul class="auto-height">
<li>
<h3>列表1</h3>
<p>内容1<br>内容2<br>内容3<br>内容4</p>
</li>
<li>
<h3>列表2</h3>
<p>内容1<br>内容2<br>内容3<br>内容4</p>
</li>
<li>
<h3>列表3</h3>
<p>内容1<br>内容2<br>内容3<br>内容4</p>
</li>
</ul>
</div>
<style>
.auto-height {
width: 300px;
li {
cursor: pointer;
& + li {
margin-top: 5px;
}
&:hover p {
border-bottom-width: 1px;
max-height: 600px;
}
}
h3 {
padding: 0 20px;
height: 40px;
background-color: #f66;
cursor: pointer;
line-height: 40px;
font-size: 16px;
color: #fff;
}
p {
overflow: hidden;
padding: 0 20px;
border: 1px solid #f66;
border-top: none;
border-bottom-width: 0;
max-height: 0;
line-height: 30px;
transition: all 500ms;
}
}
</style>
使用transform模拟视差滚动
通过
background-attachment:fixed
或transform
让多层背景以不同的速度移动,形成立体的运动效果
场景:页面滚动、视差滚动文字阴影、视差滚动文字虚影
<div class="bruce" data-title="使用transform模拟视差滚动">
<ul class="parallax-scrolling">
<li>translateZ(-1px)</li>
<li>translateZ(-2px)</li>
<li>translateZ(-3px)</li>
</ul>
<p>内容</p>
<ul class="parallax-scrolling">
<li>translateZ(-1px)</li>
<li>translateZ(-2px)</li>
<li>translateZ(-3px)</li>
</ul>
</div>
<style>
$bg: "https://static.yangzw.vip/codepen/lake.jpg";
.bruce {
overflow-x: hidden;
overflow-y: auto;
perspective: 1px;
transform-style: preserve-3d;
p {
height: 300px;
line-height: 300px;
text-align: center;
font-size: 20px;
color: #f66;
}
}
.parallax-scrolling {
display: flex;
justify-content: center;
align-items: center;
height: 1000px;
background: url($bg) no-repeat center fixed;
li {
width: 500px;
text-align: center;
font-weight: bold;
font-size: 60px;
&:nth-child(1) {
color: #f66;
transform: translateZ(-1px);
}
&:nth-child(2) {
color: #09f;
transform: translateZ(-2px);
}
&:nth-child(3) {
color: #3c9;
transform: translateZ(-3px);
}
}
}
</style>
使用animation-delay保留动画起始帧
通过
transform-delay
或animation-delay
设置负值时延保留动画起始帧,让动画进入页面不用等待即可运行
场景:开场动画
<div class="bruce flex-ct-x" data-title="使用animation-delay保留动画首帧">
<ul class="initial-keyframe">
<li></li>
<li></li>
<li></li>
</ul>
</div>
<style>
.initial-keyframe {
position: relative;
width: 100px;
height: 100px;
li {
position: absolute;
border-radius: 100%;
width: 100%;
height: 100%;
background-color: #3c9;
transform: rotate(0) translate(-80px, 0);
animation: rotate 3s linear infinite;
&:nth-child(2) {
animation-delay: -1s;
}
&:nth-child(3) {
animation-delay: -2s;
}
}
}
@keyframes rotate {
to {
transform: rotate(1turn) translate(-80px, 0);
}
}
</style>
使用resize拉伸分栏
通过
resize
设置横向自由拉伸来调整目标元素的宽度
场景:富文本编辑器、分栏阅读
<div class="bruce flex-ct-x" data-title="使用resize拉伸多列分栏">
<div class="stretching-column">
<div class="left">
<div class="resize-bar"></div>
<div class="resize-line"></div>
<div class="resize-text">ABCDEFGHIJKLMNOPQRSTUVWXYZ</div>
</div>
<div class="right">ABCDEFGHIJKLMNOPQRSTUVWXYZ</div>
</div>
</div>
<style>
.stretching-column {
overflow: hidden;
border: 1px solid #09f;
width: 600px;
height: 300px;
line-height: 20px;
font-size: 16px;
color: #f90;
.left {
overflow: hidden;
float: left;
position: relative;
height: 100%;
}
.right {
overflow: hidden;
padding: 10px;
height: 100%;
background-color: #f0f0f0;
word-break: break-all;
}
.resize-bar {
overflow: scroll;
width: 200px;
height: 100%;
opacity: 0;
resize: horizontal;
&::-webkit-scrollbar {
width: 200px;
height: 100%;
}
&:hover,
&:active {
& ~ .resize-line {
border-left: 1px dashed #09f;
}
}
}
.resize-line {
position: absolute;
right: 0;
top: 0;
bottom: 0;
border-left: 1px solid #ccc;
border-right: 2px solid #f0f0f0;
pointer-events: none;
}
.resize-text {
overflow-x: hidden;
position: absolute;
left: 0;
right: 5px;
top: 0;
bottom: 0;
padding: 10px;
word-break: break-all;
}
}
</style>