使用+或~美化选项框
- 要点:
<label>
使用+
或~
配合for
绑定radio
或checkbox
的选择行为 - 场景:选项框美化、选中项增加选中样式
- 兼容:+、~
<div class="bruce flex-ct-x"> <ul class="beauty-selection"> <li> <input type="radio" name="radioName" id="fed-engineer" hidden> <label for="fed-engineer"></label> <span>前端工程师</span> </li> <li> <input type="radio" name="radioName" id="bed-engineer" hidden> <label for="bed-engineer"></label> <span>后端工程师</span> </li> <li> <input type="radio" name="radioName" id="fsd-engineer" hidden> <label for="fsd-engineer"></label> <span>全栈工程师</span> </li> </ul> </div> <style lang="scss"> .beauty-selection { display: flex; li { display: flex; align-items: center; margin-left: 20px; &:first-child { margin-left: 0; } } input:checked + label { background-color: $orange; } label { margin-right: 5px; padding: 2px; border: 1px solid $orange; border-radius: 100%; width: 18px; height: 18px; background-clip: content-box; cursor: pointer; transition: all 300ms; &:hover { border-color: $blue; background-color: $blue; box-shadow: 0 0 7px $blue; } } span { font-size: 16px; } } </style>
使用:focus-within分发冒泡响应
- 要点:表单控件触发
focus
和blur
事件后往父元素进行冒泡,在父元素上通过:focus-within
捕获该冒泡事件来设置样式 - 场景:登录注册弹框、表单校验、离屏导航、导航切换
- 兼容::focus-within、:placeholder-shown
<div class="bruce flex-ct-x"> <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 type="radio" name="sex" id="male"> <label for="male">Boy</label> </li> <li> <input type="radio" name="sex" id="female"> <label for="female">Girl</label> </li> </ul> <button type="button">注册</button> </form> </div> <style lang="scss"> .bruce { background-color: #999; } .bubble-distribution { position: relative; margin-top: 50px; padding: 25px; border-radius: 2px; width: 320px; background-color: #fff; h3 { font-weight: bold; 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, $blue 50%, transparent 0) repeat-x, linear-gradient(90deg, $blue 50%, transparent 0) repeat-x, linear-gradient(0deg, $blue 50%, transparent 0) repeat-y, linear-gradient(0deg, $blue 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; outline: none; border: 1px solid #e9e9e9; border-radius: 2px; width: 100%; height: 40px; transition: all 300ms; &:focus:valid { border-color: $blue; } &:focus:invalid { border-color: $red; } } input[type=radio] { position: absolute; width: 0; height: 0; &:checked + label { border: 3px solid transparent; background-color: $blue; 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 { overflow: hidden; margin-top: 10px; outline: none; border: none; border-radius: 2px; width: 100%; height: 40px; background-color: $blue; 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
触发单元格的样式变化来描绘鼠标运动轨迹 - 场景:鼠标跟随轨迹、水波纹、怪圈
- 兼容::hover
@function randomNum($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(randomNum(255), randomNum(255), randomNum(255), .8); } } } } }
使用max-height切换自动高度
- 要点:通过
max-height
定义收起的最小高度和展开的最大高度,设置两者间的过渡切换 - 场景:隐藏式子导航栏、悬浮式折叠面板
- 兼容:max-height
<div class="bruce flex-ct-x"> <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 lang="scss"> .auto-height { width: 300px; li { margin-top: 5px; cursor: pointer; &:first-child { margin-top: 0; } &:hover p { border-bottom-width: 1px; max-height: 600px; } } h3 { padding: 0 20px; height: 40px; background-color: $red; cursor: pointer; line-height: 40px; font-size: 16px; color: #fff; } p { overflow: hidden; padding: 0 20px; border: 1px solid $red; border-top: none; border-bottom-width: 0; max-height: 0; line-height: 30px; transition: all 500ms; } } </style>
使用transform模拟视差滚动
- 要点:通过
background-attachment:fixed
或transform
让多层背景以不同的速度移动,形成立体的运动效果 - 场景:页面滚动、视差滚动文字阴影、视差滚动文字虚影
- 兼容:background-attachment、transform
<div class="bruce"> <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 lang="scss"> $bg: "https://yangzw.vip/static/codepen/bg.jpg"; .bruce { overflow: auto; perspective: 1px; transform-style: preserve-3d; p { height: 300px; line-height: 300px; text-align: center; font-size: 20px; color: $red; } } .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: $red; transform: translateZ(-1px); } &:nth-child(2) { color: $blue; transform: translateZ(-2px); } &:nth-child(3) { color: $green; transform: translateZ(-3px); } } } <style>
使用animation-delay保留动画起始帧
- 要点:通过
transform-delay
或animation-delay
设置负值时延保留动画起始帧,让动画进入页面不用等待即可运行 - 场景:开场动画
- 兼容:transform、animation
<div class="bruce flex-ct-x"> <ul class="initial-keyframe"> <li></li> <li></li> <li></li> </ul> </div> <style lang="scss"> .initial-keyframe { position: relative; width: 100px; height: 100px; li { position: absolute; border-radius: 100%; width: 100%; height: 100%; background-color: $green; 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
设置横向自由拉伸来调整目标元素的宽度 - 场景:富文本编辑器、分栏阅读
- 兼容:resize
<div class="bruce flex-ct-x"> <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 lang="scss"> .stretching-column { overflow: hidden; border: 1px solid $blue; width: 600px; height: 300px; line-height: 20px; font-size: 16px; color: $orange; .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 $blue; } } } .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>