CSS开发技巧——行为技巧

CSS开发技巧——行为技巧
  • 使用overflow-scrolling支持弹性滚动

    iOS页面非body元素的滚动操作会非常卡(Android不会出现此情况),通过overflow-scrolling:touch调用Safari原生滚动来支持弹性滚动,增加页面滚动的流畅度

    • 场景:iOS页面滚动
  • 使用transform启动GPU硬件加速

    有时执行动画可能会导致页面卡顿,可在特定元素中使用硬件加速来避免这个问题

    • 场景:动画元素(绝对定位、同级中超过6个以上使用动画)
  • 使用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绑定radiocheckbox的选择行为

    • 场景:选项框美化选中项增加选中样式

    • <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分发冒泡响应

    表单控件触发focusblur事件后往父元素进行冒泡,在父元素上通过: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:fixedtransform让多层背景以不同的速度移动,形成立体的运动效果

    • 场景:页面滚动视差滚动文字阴影视差滚动文字虚影

    • <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-delayanimation-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>
      
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值