假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
本篇文章主要总结 web 前端开发过程当中一些相对比较细节的常用样式
在我们给一个相对敏感项目全屏加水印的时候,可以简单的使用 fixed 定位一块全尺寸的透明蒙版去实现,但是同样会出现一个问题就是这个蒙版会阻塞页面原有的点击事件,这时候只要给它加上 pointer-events: none;
属性便可轻松解决
<style>
.warp {
position: relative;
overflow: hidden;
}
.watermark-mask {
width: 700%;
height: 700%;
top: -300%;
left: -300%;
transform: rotate(-40deg);
transform-origin: 50% 50%;
/* 此处为了掩饰用了 absolute,实际应该 fixed */
position: absolute;
pointer-events: none;
}
</style>
<div class="warp">
<div class="content">
<p>假设这里是内容</p>
<button onclick="alert(1)">点击这里</button>
<p>假设这里是内容</p>
<p>假设这里是内容</p>
<p>假设这里是内容</p>
<p>假设这里是内容</p>
<p>假设这里是内容</p>
<p>假设这里是内容</p>
<p>假设这里是内容</p>
<p>假设这里是内容</p>
</div>
<div class="watermark-mask" id="watermark-mask"></div>
</div>
<script>
function addWaterMarker(str) {
let can = document.createElement('canvas')
const mask = document.querySelector('#watermark-mask')
const fontSize = 18 // 字体大小
const vMargin = 5 * fontSize
const xMargin = 300
mask.appendChild(can)
can.width = 600 //画布的宽
can.height = 2 * (vMargin + fontSize) //画布的高度
can.style.display = 'none'
var cans = can.getContext('2d')
cans.font = `${fontSize}px Microsoft YaHei` //画布里面文字的字体
cans.fillStyle = "rgba(0, 0, 0, 0.20)" //画布里面文字的颜色
cans.fillText(str, 0, fontSize * 2 + vMargin * 3 / 2) //画布里面文字的间距比例
cans.fillText(str, xMargin, fontSize * 2 + vMargin * 3 / 2) //画布里面文字的间距比例
cans.fillText(str, xMargin / 2, fontSize + vMargin / 2) //画布里面文字的间距比例
cans.fillText(str, xMargin / 2 - xMargin, fontSize + vMargin / 2) //画布里面文字的间距比例
cans.fillText(str, xMargin / 2 + xMargin, fontSize + vMargin / 2) //画布里面文字的间距比例
mask.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")" //把画布插入到mask中
}
const time = new Date()
const formatObj = {
y: time.getFullYear(),
m: time.getMonth() + 1,
d: time.getDate(),
h: time.getHours(),
i: time.getMinutes(),
s: time.getSeconds()
}
const fillZero = (field) => {
const value = formatObj[field]
if (value < 10) {
return '0' + value
} else {
return value
}
}
//调用这个方法即可
const str = `马云海 ${fillZero('y')}-${fillZero('m')}-${fillZero('d')} ${fillZero('h')}:${fillZero('i')}:${fillZero('s')}`
addWaterMarker(str)
</script>
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
假设这里是内容
这是 CSS3 一个鲜为人知的属性,这个属性只用于 iOS (移动开发当中个人认为最容易出兼容性问题的就是 IOS)。当你点击一个链接或者通过 Javascript 定义的可点击元素的时候,它就会出现一个半透明的灰色背景。要重设这个表现,你可以设置-webkit-tap-highlight-color 为任何颜色。在大部分情况这个属性是无关痛痒的。但是在万变的需求当中总是要痛的,举个例子在移动端开发当中一个过小可被点击图标是挺常见的事情,通常我们会为了用户能够更好的点击到它可用一个稍微大一些透明 div 盖在上方来接收点击,这种增加用户点击热区的范围的方法在移动端页面开发是非常实用的,这时候 webkit-tap-highlight-color 的默认半透明灰色背景会带来很不好的体验,建议全局设置
*{webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-appearance:none}
这样的属性永绝后患。
这是 CSS3 一种常用的过渡动画属性,也是较为简单方便的一种,你甚至可以添加一个.trasition_3s{-webkit-transition:.3s;transition:.3s}这样的类,在想要用的地方为所欲为。比如 hover 效果过渡,长宽变化过渡,淡入淡出...只需要简简单单加上一个类 trasition_3s 就能够得到不错的效果。这里可以注意一下细节:
对于很多仔细看过 flex 布局的小伙伴肯定是了解过 flex-grow 属性,但是大部分都知道它是做什么的并不知道有什么用。下面我将介绍一个可以用到的场景,通常一个网页我们都知道有 header,footer 两个基本万年遍两个组件,高度呢也是基本固定的,那么问题来了,当一个页面自身高度不够高的时候,会导致整个网页的高度小于浏览器的高度,这就很尴尬了,虽然不影响使用以及功能,不过看着就不是很好看,当然也有人想了我把中间设置一个固定高度网页撑起来呢,很明显用户的窗口高度不是我们能控制的除非你用 js 去计算不然很难计算出中间的高度需要多少最为合适。那用 CSS 的 calc 属性来定义高度呢?实际开发当中我们会遇到各种奇怪的问题,比如头部或者底部的高度恰巧就变化了呢(真的有虽然大部分高度不变还是有特例的页面存在),calc 属性依旧不能带来最好的体验?嘿嘿,这里我们就可以巧妙的使用 flex 布局来解决,具体方法如下:
<style>
* {
padding: 0;
margin: 0px;
}
.bg_000 {
background: #000;
}
.h50 {
height: 50px;
cursor: pointer;
transition: .3s;
}
.flex {
display: flex;
}
.flex_column {
flex-direction: column;
}
.flex1 {
flex: 1;
}
.h50:hover {
height: 100px;
}
.h50:active {
height: 100px;
}
</style>
<div class="flex flex_column" style="min-height:100vh">
<div class="h50 bg_000"></div>
<div class="flex1"></div>
<div class="h50 bg_000"></div>
</div>
产品的需求总是千奇百怪的,我曾经就遇到一个奇葩问题,项目用户头像的尺寸尚未统一有横着的长方形有竖着的长方形,列表却需要用统一大小圆形遍历用户头像。这个需求如果用 JS 做会相当复杂,但是 CSS 中 background-size 可以轻松解决这个需求
例如:
<style>
.portrait {
width: 50px;
height: 50px;
border-radius: 50%;
background: url('https://dummyimage.com/320x180/0388e3&text=320x180') center center;
background-size: cover;
}
</style>
<div class="portrait"></div>
关于 cover 的运用,也是如此类似的不同尺寸展示需求,这里我就不多阐述,直接上代码自行体验感受:
<style>
.pic {
width: 200px;
height: 300px;
background: url('https://dummyimage.com/320x180/0388e3&text=320x180') center center
no-repeat black;
background-size: contain;
}
</style>
<div class="pic"></div>
通过对 div 的边框设置可以轻易画出各种三角形,具体原理利用一个 0 高度 0 宽度的 div,当边长不为 0 的时候,利用相互平行的两条边设置颜色为 transparent,然后把不与他们平行的一条边设置为一种颜色组合成一个三角形,具体实现如下,需要改变角度 方向可以自行调节测试,还是挺有意思的,实际运用方面替代一些小地方需要三角形的纯色贴图还是很有方便的
TIP
Element UI 里面的 Tooltip
组件就是用类似的原理去实现的小角
<style>
.triangle {
height: 0px;
width: 0px;
border-top: 8px solid black; /* 三角形的高度*/
border-left: 8px solid transparent; /* 左右边宽度的总和为三角形最长边长度*/
border-right: 8px solid transparent;
}
</style>
<div class="triangle"></div>
大部分情况计算标签实际高度时候是需要包含计算 padding
的,比如一个长宽 10px
的 div
有 padding: 5px;
那么它的实际高度就是 20px(10 + 5 + 5)
,但是如果设置了 box-sizing:border-box;
的话那么为元素设定的宽度和高度决定了元素的边框盒,也就是无论你 padding
多少,div 只要设置了长宽 10px
,则实际上长宽都是 10px
position 定位大家熟悉的 relative、fixed、absolute 这里就不过多介绍了,这里介绍的一个黑科技 sticky。先简单介绍一下它的特点:
在 PC 上面对于极少部分的兼容性并不算特别理想,但是对于目前大部分移动设备都是适用,在各种电商详情页(拥有过长的 TAB 页)上这样需求非常常见,下面写个例子:
<body style="height:10000px">
<!-- 滚动滚动条试试? -->
<p>占位</p>
<p>占位</p>
<p>占位</p>
<div style="position:sticky; top: 0px;background:rgba(0, 0, 0, 0.2)">
sticky
</div>
<p>占位</p>
<p>占位</p>
<p>占位</p>
<p>占位</p>
<p>占位</p>
<p>占位</p>
<p>占位</p>
</body>
对于过长的当行文字添加.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}这样的样式就可以实现文字过长用省略号代替,这里注意一点三个属性缺一不可,通常我也单独会在通用样式表里面添加这样的样式,若需使用直接标签新增 ellipsis 类即可。但是还是有那种多行简介超过 2 行的文字出现省略号代替的情况,这时候就需要用到-webkit-line-clamp 这样的属性,可以轻松解决
例如:
<style>
.ellipsis2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
word-wrap: break-word;
word-break: break-all;
}
</style>
<div class="ellipsis2" style="width: 100px">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
按理说设计方面页面最小的字体就是 12px,浏览器所能够支持的最小字体大小也是 12px,但是在脑洞大开的产品经理眼里一起皆有可能,确确实实有的时候会用到小于 12px 的文字,两种解决方式第一直接用图片,第二使用 transform:scale(0.9,0.9)
,但是这里需要注意一点的时候缩放后的换行布局排版需要格外的注意,感兴趣的小伙伴可以试试或者等真的遇到这样需求的时候稍稍注意些这个问题,当然大部分情况可以通过设置transform-origin
轻松解决
IOS系统常见的毛玻璃特效看起来很舒服,其实H5实现起来也很方便,主要使用backdrop-filter
(opens new window)实现,核心代码如下
.navbar, .sidebar {
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
}
<style>
.container {
height: 100px;
border: 2px solid black;
}
.container .mid-box {
background: #0388e3;
width: 50px;
height: 50px;
position: relative;
top: 50%;
transform: translateY(-50%);
}
</style>
<div class="container">
<div class="mid-box"></div>
</div>
align-items: center
轻松搞定,关键外层盒子高度任意变化都会依旧保持垂直居中(推荐不过需要考虑兼容要求,移动端基本都可以使用)<style>
.flex-container {
height: 100px;
border: 2px solid black;
display: flex;
align-items: center;
}
.flex-container .mid-box {
background: #0388e3;
width: 50px;
height: 50px;
}
</style>
<div class="flex-container">
<div class="mid-box"></div>
</div>
<td valign="middle">
(不赞成使用HTML5 不支持。HTML 4.01 已废弃
)这里想要强调一点
千万不要用尝试用 margin 去做垂直定位,至于为什么可以看 margin 重叠
margin重叠算是前端开发比较容易被忽视的一个点,原因来自于BFC一个重要特性,同一个BFC下外边距会发生折叠具体参考BFC,这里强调一点做垂直居中的时候千万不要用margin去做定位完成,不然极有可能引来一系列问题。
先做个总结margin重叠仅存在于垂直方向,水平方向不存在重叠。也就是说只有在没有浮动的块标签(display:block
)中会出现margin重叠,感兴趣的小伙伴可以复制以下代码测试一下
<style>
.box1{
/* float: left; */
/* display: inline-block; */
width: calc(100% - 100px);
height: 50px;
margin: 50px;
border: 2px solid black
}
</style>
<div class="box1"></div>
<div class="box1"></div>
<div class="box1"></div>
<style>
.box2{
/* float: left; */
display: inline-block;
width: calc(100% - 100px);
height: 50px;
margin: 50px;
border: 2px solid black
}
</style>
<div class="box2"></div>
<div class="box2"></div>
<div class="box2"></div>
<style>
.box3{
float: left;
/* display: inline-block; */
width: calc(100% - 100px);
height: 50px;
margin: 50px;
border: 2px solid black
}
</style>
<div class="box3"></div>
<div class="box3"></div>
<div class="box3"></div>
will-change 我是在element UI里面看到的,觉得很新鲜就查了下用法很简单如下:
TIP
chrome Rendering里面 FPS meter勾上即可观察,尝试删除will-change会出现明显低 fps 情况,加了之后明显相对稳定(说实话区别不是特别大,可能新属性支持不是特别好,反正加上就好了)
如果机器过好可以尝试缩短 transition
时间
切记请勿乱用,最好可以利用父标签 hover
伪类动态添加,更不能全局添加此属性
<style>
.box{
width: 50px;
height: 80px;
border: 1px solid;
opacity: 1;
transition: .2s;
cursor: pointer;
background: url(https://dummyimage.com/320x180/0388e3&text=320x180);
background-size: cover;
}
.box:hover{
will-change: height, opacity;
}
.box:active{
width: 320px;
height: 180px;
opacity: .5;
}
</style>
<div class="box"></div>
开启硬件加速的方法还有 transform: translateZ(0);
在 Chrome and Safari 中,当我们使用 CSS transforms 或者 animations 时可能会有页面闪烁的效果,下面的代码可以修复此情况:
{
backface-visibility: hidden;
perspective: 1000;
}
在一个div
里面写入多个span
标签,会发现他们之间自带一个很小的边距,如下:
<style>
.spanMargin{
background: #e1e1e1
}
</style>
<div>
<span class="spanMargin">span1</span>
<span class="spanMargin">span2</span>
<span class="spanMargin">span3</span>
</div>
原因分析
首先这里是非常容易被忽视的一个细节,因为往往设计这类 Tag 标签肯定会设计边距所以这样细小的边距就容易被忽视
出现这种问题原因是span
标签换行带来的空格占位导致边距
解决方案两种如下:
<style>
.spanMargin{
background: #e1e1e1
}
</style>
<div>
<span class="spanMargin">span1</span><span class="spanMargin">span2</span><span class="spanMargin">span3</span>
</div>
<style>
.spanMargin{
background: #e1e1e1
}
</style>
<div style="font-size:0px">
<span class="spanMargin" style="font-size:16px">span1</span>
<span class="spanMargin" style="font-size:16px">span2</span>
<span class="spanMargin" style="font-size:16px">span3</span>
</div>
直接上代码,感兴趣的可以查一下相关样式兼容性,这里我觉得更有趣的是可以使用 hue-rotate
来实现渐变颜色过渡动画
<style>
.gradientText{
color: rgba(233, 30, 99, 0.5); /* 兼容兜底 */
background-image: linear-gradient(45deg, rgba(233, 30, 99, 0.5) 0%, #3F51B5 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: hue 5s infinite linear;
}
@keyframes hue {
from {
filter: hue-rotate(0deg);
}
to {
filter: hue-rotate(360deg);
}
}
</style>
<h1 class="gradientText">渐变色文字</h1>
em 其实和 rem 类似,他们的大小都是相对于别人来定的
举个例子如果HTML标签字体大小100px时候
html {
font-size: 100px;
}
1rem 就是等于 100px,0.12rem 就是等于 12px,以此类推,em
也是类似原理不过它是相对于父标签的字体大小
TIP
这样做的好处只要修改部分字体就能全局或者局部的修改整体尺寸,这里有个提示就是如果希望在不同size下边距尺寸固定的话,那么边距尺寸用px即可
这是 20px 文本
这是 1em 文本(父标签字体20px)
这是 1em 文本(父标签字体12px)
HTML <textarea>
标签能够记录下换行,但是前台展示的时候直接放入标签的时候只会展示空格且不会换行,如果我们想要不使用 <br>
标签就实现换行的话,可以使用 <pre>
标签,但是同样会引来其他样式问题,其实CSS3有个 white-space
属性能够优雅的解决这个问题,在刚看到这个标签的时候大多并不陌生,多用于不换行省略号展示标题,例如
<div
style = "
width: 300px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
这是一段很长很长文字。这是一段很长很长文字。这是一段很长很长文字。
</div>
这里主要介绍它其他三个属性值 pre
、 pre-wrap
、 pre-line
pre
和 pre-wrap
<div style = "white-space: pre;">
锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦
</div>
<div style = "white-space: pre-wrap;">
锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦
</div>
TIP
pre
:空白会被浏览器保留。其行为方式类似 HTML 中的 <pre>
标签
pre-wrap
:保留空白符序列,但是正常地进行换行
虽然文档对 pre
、 pre-wrap
有着不同的解释,但是我确实看不出他们两个有什么太大区别
pre-line
作用合并空白符序列,但是保留换行符。上面两个区别搞不清我觉得问题不大,因为就算要用通常也用这个属性效果如下
<div style = "white-space: pre-line;">
锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦
</div>
在前端开发的时候经常会遇到一个问题,当一段文字设置 height: 30px;line-height: 30px;
的时候按理说我们预期它应该垂直居中的,但是实际上却不是而且各个浏览器的表现还不太一致,如下左边是一个垂直居中的红点,如果是 chrome
浏览器很明显可以感觉到文字实际上是偏下的导致和左边的点对不齐
<style>
.dot-normal {
border: 1px solid #eee;
font-size: 45px;
height: 50px;
line-height: 50px;
padding-left: 20px;
position: relative;
}
.dot-normal::before {
background: red;
border-radius: 50%;
content: '';
display: inline-block;
height: 10px;
left: 10px;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 10px;
}
</style>
<div class="dot-normal">齉齉齉</div>
vertical-align: middle
能够稍微修正这个问题,但是个人觉得往往是矫正过多
<style>
.dot {
border: 1px solid #eee;
font-size: 45px;
height: 50px;
line-height: 50px;
padding-left: 10px;
}
.dot::before {
background: red;
border-radius: 50%;
content: '';
display: inline-block;
height: 10px;
vertical-align: middle;
width: 10px;
}
</style>
<div class="dot">齉齉齉</div>
很明显可以看的出来左边的小圆点是跟着文字向下偏移了但是明显过多了,至于用哪种实现类似需求还是看个人了
font-weight
属性设置文本的粗细,定义由粗到细的字符。400 等同于 normal,而 700 等同于 bold
TIP
通常情况下,在前端开发中 font-weight
设置为
0 - 345 展示为 lighter
效果
346 - 549 展示为 normal
效果
550 - 1000 展示为 bold
效果
1001 - +∞ 会 Invalid property value
,展示为 normal
效果
由于700字重实在太粗了,在我们开发中经常会遇到UX提出 500字重的需求,安卓 IOS 可能会比较好实现,但是前端想要实现可能需要加载额外字体,引入字体确实能够解决问题,但是那样一个字体文件起码也要 10M
以上显然不合适,其实只要我们把字体设置为如下字体,就能实现大部分终端500字重(仅限英文)的需求了
body {
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
移动端基本兼容
自适应撑满,这个虽然弹性布局 flex:1
也能实现
<!-- -webkit-fill-available -->
<style>
.flex {
display: flex;
}
.border {
border: 1px solid;
}
</style>
<div class="flex">
<div class="border">
test
</div>
<div class="border" style="width: -webkit-fill-available;">
-webkit-fill-available
</div>
<div class="border">
test
</div>
</div>
自适应缩放到最小,和 inline-block
效果类似
<!-- fit-content -->
<style>
.border {
border: 1px solid;
}
</style>
<div class="border" style="width: fit-content;">
content
</div>
<!-- min-content -->
<style>
.border {
border: 1px solid;
}
.inline-block {
display: inline-block;
}
.min-content {
width: -webkit-min-content;
width: -moz-min-content;
width: min-content;
}
</style>
<b>display:inline-block;</b>
<div class="border inline-block">
<img src="https://dummyimage.com/320x180/0388e3&text=320x180">
<p>display:inline-block具有收缩特性,但这里宽度随文字。而width:min-content随图片。</p>
</div>
<b>width: min-content;</b>
<div class="border min-content">
<img src="https://dummyimage.com/320x180/0388e3&text=320x180">
<p>display:inline-block具有收缩特性,但这里宽度随文字。而width:min-content随图片。</p>
</div>
display:inline-block;
display:inline-block具有收缩特性,但这里宽度随文字。而width:min-content随图片。
width: min-content;
display:inline-block具有收缩特性,但这里宽度随文字。而width:min-content随图片。
<!-- max-content -->
<style>
.border {
border: 1px solid;
}
.inline-block {
display: inline-block;
}
.max-content {
width: -webkit- max-content;
width: -moz- max-content;
width: max-content;
}
</style>
<div style="width: 400px;background: #f1f1f1;">
<b>display: inline-block;</b>
<div class="border inline-block">
<img src="https://dummyimage.com/320x180/0388e3&text=320x180">
<p>
display:inline-block描述文字超过一行显示会换行,不会让自身的宽度超过父级容器的可用空间的,width:max-content表现得好像设置了white-space:nowrap一样
</p>
</div>
<b>width: max-content;</b>
<div class="border max-content">
<img src="https://dummyimage.com/320x180/0388e3&text=320x180">
<p>
display:inline-block描述文字超过一行显示会换行,不会让自身的宽度超过父级容器的可用空间的,width:max-content表现得好像设置了white-space:nowrap一样
</p>
</div>
</div>
display: inline-block;
display:inline-block描述文字超过一行显示会换行,不会让自身的宽度超过父级容器的可用空间的,width:max-content表现得好像设置了white-space:nowrap一样
width: max-content;
display:inline-block描述文字超过一行显示会换行,不会让自身的宽度超过父级容器的可用空间的,width:max-content表现得好像设置了white-space:nowrap一样
未完待续...
← HTML Javascript →