前言
在日常开发中,对于图像不同效果的处理,通常需要设计侧的专业知识和技能,同时开发侧也需要增加额外的图片资源的请求。为了避免引入多个图片资源且和增加一些额外的配置项去实现不同效果的处理,我们可以使用CSS的滤镜属性直接对元素进行效果处理,而不需要对每个元素的不同效果引入相关的图片文件,从而能提高更大的灵活性和可维护性。
在开发过程中我们总会碰到这样的场景:符合条件时按钮或图片高亮展示,不符合条件时按钮或图片置灰展示。
我们可能很自然地就去想这无非就是用两种样式:高亮的和非高亮的样式,两种样式对应的按钮颜色或者图片路径不同。那么要是每个按钮或图片都不一样,我们就需要对每一个高亮的场景都去做一个灰色场景的处理,即便是走配置化的数据,那么我们也都需要配置两份数据去做展示,这样不仅配置麻烦且工作效率较低。
如果我们只想要配置一套数据的话,其实可以使用filter滤镜去进行实现,我们可以利用其grayscale属性,将配置好高亮图片转换为灰度图像进行实现,参考效果如下图所示。
图1 奖励领取置灰效果图
filter滤镜就是css3新增的一个神奇功能,它可以对网页中的图片进行类似Photoshop图片处理的效果,但并不需要依赖于任何作图软件。同时,filter滤镜不仅可以对图片添加滤镜效果,还可以对网页元素甚至视频进行滤镜处理。
filter属性通过调整滤镜函数的参数,可以改变元素的颜色、透明度、亮度、对比度等视觉特性。
filter: <filter-function> [<filter-function>]* | none
filter: url(file.svg#filter-element-id)
blur(radius)函数将高斯模糊应用到图像。radius 定义了高斯函数的标准偏差值,或者屏幕上有多少像素相互融合,值越大模糊程度越高。若未设置值,默认为 0。
图2 blur滤镜效果对比图
brightness(amount)函数让图像更明亮或更暗淡。值为 0% 将创建全黑图像,值为 100% 会使输入保持不变,值大于 100% 提供更明亮的结果。若未设置值,默认为 1。
图3 brightness滤镜效果对比图
contrast(amount)函数可调整输入图像的对比度。值是 0% 图像会全黑,值为100% 图像不变,值可以超过 100%,意味着会运用更低的对比。若未设置值,默认是 1。
图4 contrast滤镜效果对比图
drop-shadow(offset-x offset-y blur-radius color) 可在图像后方应用投影。阴影可以设置模糊度,以特定颜色画出的遮罩图的偏移版本,最终合成在图像下面。
图5 drop-shadow滤镜效果对比图
grayscale(amount)函数可将图像转为灰度图。amount的值定义了转换的比例,值在 0% 到 100% 之间,值为 0% 图像无变化,值为 100%则完全转为灰度图像。若未设置值,默认是 0。
图6 grayscale滤镜效果对比图
hue-rotate(angle)函数可在图像应用色相旋转,angle的值设定图像会被调整的色环角度值。值为 0deg,则图像无变化,超过 360deg相当于又绕一圈。若未设置值,默认为 0deg。
图7 hue-rotate滤镜效果对比图
invert(amount)函数可反转图像颜色。amount的值定义转换的比例,值在 0% 和 100% 之间,值为 0% 则图像无变化,值为 100% 则图像完全反转。若未设置值,则默认为 0。
图8 invert滤镜效果对比图
opacity(amount) 函数可改变图像透明度。amount的值定义转换的比例,值在 0% 和 100% 之间,值为 0% 则是完全透明,值为 100% 则图像无变化。若未设置值,则默认为 1。该函数与css的opacity 属性很相似,不同之处在于通过 filter,一些浏览器为了提升性能会提供硬件加速。
图9 opacity滤镜效果对比图
saturate(amount)函数可转换图像饱和度。amount的值定义转换的比例,值为 0% 则是完全不饱和,值为 100% 则图像无变化,超过 100% 则有更高的饱和度。若未设置值,则默认为 1。
图10 saturate滤镜效果对比图
sepia(amount) 函数可将图像转换为深褐色。amount的值定义转换的比例,值在 0% 到 100% 之间,值为 0% 图像无变化,值为 100% 则完全是深褐色的。若未设置值,则默认为 0。
图11 sepia滤镜效果对比图
从filter函数的使用方式可以看出,滤镜效果是可以进行叠加的,比如,filter: contrast(50%) brightness(50%)。
图12 组合滤镜效果图
那么同一元素上定义多个滤镜的话,滤镜的先后顺序对最后效果有影响吗?我们调换滤镜顺序换成filter: brightness(50%) contrast(50%)来看看。
图13 组合滤镜顺序变换效果图
由上图可以看出,滤镜的先后顺序不同产生的效果也是不一样的。原因在于滤镜顺序不同,滤镜的色值处理算法对图片处理的先后顺序也就不一样,最终产生的效果就不一样。
其实CSS滤镜不仅可以组合使用实现很多视觉效果,也可以通过结合不同的滤镜效果和CSS动画,去实现一些奇妙的动画效果。
文字融合动画就是一种文字从融合到分开的效果,我们可以通过改变letter-spacing和blur的值去进行效果实现。
<div class="container">
<div class="text">Hello World</div>
</div>
.container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #000;
filter: contrast(30);
}
.text {
color: #fff;
font-size: 100px;
animation: show 3s linear forwards;
}
@keyframes show {
0% {
opacity: 0;
letter-spacing: -50px;
filter: blur(10px);
}
25% {
opacity: 1;
filter: blur(8px);
}
50% {
filter: blur(5px);
}
100% {
letter-spacing: 10px;
filter: blur(2px);
}
}
,时长00:03
该动画其实就是一种模拟安卓手机充电时的动画效果,主要就是通过contrast滤镜以及blur滤镜去实现很好的融合效果。
<div class="g-container">
<div class="g-number">90%</div>
<div class="g-contrast">
<div class="g-circle"></div>
<ul class="g-bubbles">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
.g-container {
position: relative;
width: 300px;
height: 400px;
margin: auto;
}
.g-number {
position: absolute;
top: 100px;
width: 100%;
color: #fff;
font-size: 30px;
text-align: center;
z-index: 10;
}
.g-contrast {
width: 100%;
height: 100%;
background-color: #000;
overflow: hidden;
filter: contrast(10) hue-rotate(0);
animation: hueRotate 10s infinite linear;
}
.g-circle {
position: relative;
width: 300px;
height: 300px;
box-sizing: border-box;
filter: blur(8px);
}
.g-circle::after {
content: "";
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%) rotate(0);
width: 200px;
height: 200px;
background-color: #00ff6f;
border-radius: 42% 38% 62% 49%/45%;
animation: rotate 10s infinite linear;
}
.g-circle::before {
content: "";
position: absolute;
width: 176px;
height: 176px;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
background-color: #000;
z-index: 10;
}
.g-bubbles {
position: absolute;
left: 50%;
bottom: 0;
width: 100px;
height: 40px;
transform: translate(-50%, 0);
border-radius: 100px 100px 0 0;
background-color: #00ff6f;
filter: blur(5px);
}
li {
position: absolute;
border-radius: 50%;
background: #00ff6f;
}
li:nth-child(0) {
left: 50px;
top: 50%;
transform: translate(-50%, -50%);
width: 16px;
height: 16px;
animation: move 4s ease-in-out -1.47s infinite;
}
li:nth-child(1) {
left: 55px;
top: 50%;
transform: translate(-50%, -50%);
width: 18px;
height: 18px;
animation: move 6s ease-in-out -2.23s infinite;
}
li:nth-child(2) {
left: 60px;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
animation: move 5s ease-in-out -3.89s infinite;
}
li:nth-child(3) {
left: 65px;
top: 50%;
transform: translate(-50%, -50%);
width: 22px;
height: 22px;
animation: move 7s ease-in-out -4.56s infinite;
}
li:nth-child(4) {
left: 70px;
top: 50%;
transform: translate(-50%, -50%);
width: 24px;
height: 24px;
animation: move 9s ease-in-out -2.12s infinite;
}
li:nth-child(5) {
left: 75px;
top: 50%;
transform: translate(-50%, -50%);
width: 26px;
height: 26px;
animation: move 9s ease-in-out -1.98s infinite;
}
li:nth-child(6) {
left: 80px;
top: 50%;
transform: translate(-50%, -50%);
width: 23px;
height: 23px;
animation: move 5s ease-in-out -3.35s infinite;
}
li:nth-child(7) {
left: 63px;
top: 50%;
transform: translate(-50%, -50%);
width: 19px;
height: 19px;
animation: move 7s ease-in-out -4.34s infinite;
}
li:nth-child(8) {
left: 67px;
top: 50%;
transform: translate(-50%, -50%);
width: 25px;
height: 25px;
animation: move 6s ease-in-out -2.87s infinite;
}
li:nth-child(9) {
left: 73px;
top: 50%;
transform: translate(-50%, -50%);
width: 28px;
height: 28px;
animation: move 8s ease-in-out -3.45s infinite;
}
li:nth-child(10) {
left: 56px;
top: 50%;
transform: translate(-50%, -50%);
width: 24px;
height: 24px;
animation: move 7s ease-in-out -1.83s infinite;
}
li:nth-child(11) {
left: 45px;
top: 50%;
transform: translate(-50%, -50%);
width: 25px;
height: 25px;
animation: move 5s ease-in-out -2.67s infinite;
}
li:nth-child(12) {
left: 68px;
top: 50%;
transform: translate(-50%, -50%);
width: 19px;
height: 19px;
animation: move 6s ease-in-out -3.12s infinite;
}
li:nth-child(13) {
left: 54px;
top: 50%;
transform: translate(-50%, -50%);
width: 29px;
height: 29px;
animation: move 9s ease-in-out -2.22s infinite;
}
li:nth-child(14) {
left: 41px;
top: 50%;
transform: translate(-50%, -50%);
width: 27px;
height: 27px;
animation: move 5s ease-in-out -1.11s infinite;
}
li:nth-child(15) {
left: 51px;
top: 50%;
transform: translate(-50%, -50%);
width: 24px;
height: 24px;
animation: move 7s ease-in-out -3.23s infinite;
}
@keyframes rotate {
50% {
border-radius: 45%/42% 38% 58% 49%;
}
100% {
transform: translate(-50%, -50%) rotate(720deg);
}
}
@keyframes move {
90% {
opacity: 1;
}
100% {
opacity: 0.1;
transform: translate(-50%, -180px);
}
}
@keyframes hueRotate {
100% {
filter: contrast(15) hue-rotate(360deg);
}
}
图14 手机充电动画效果图
电影谢幕动画其实就是图片逐渐消失而谢幕文案逐渐模糊显示的效果,我们可以使用filter属性中的blur和brightness滤镜来模拟该效果的实现。
<div class="main">
<div class="img"></div>
<div class="text">Thank you for watching!</div>
</div>
.main {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: #000;
}
.img {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: url("xxx.png");
background-size: cover;
animation: imgHide 3s linear forwards;
}
.text {
color: #fff;
font-size: 50px;
opacity: 0;
animation: textShow 2s linear forwards;
}
@keyframes imgHide {
0% {
filter: brightness(1);
}
100% {
filter: brightness(0);
}
}
@keyframes textShow {
0% {
opacity: 0;
filter: blur(8px) brightness(50%);
}
100% {
opacity: 1;
filter: blur(0) brightness(100%);
}
}
,时长00:03
彩虹文字动画其实就是一种动态变化文字颜色的效果。该动画效果的实现就是通过动态地改变hue-rotate的值,使文字颜色在一定范围内进行循环变化产生动态颜色。
<div>MAINTO MEMBER CENTER</div>
div {
font-size: 80px;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(to right, red, orange, yellow, green, cyan, blue, purple);
animation: huerotate 6s linear infinite;
}
@keyframes huerotate {
from { filter: hue-rotate(0deg); }
to { filter: hue-rotate(360deg); }
}
效果图片如下所示:
图15 彩虹文字动画效果图
同样我们也可以通过这种方式去实现一种动态背景颜色变换的效果。
div {
background: linear-gradient(45deg, #5fddcc, #ff004d);
animation: hueRotate 10s infinite alternate;
}
@keyframes hueRotate {
0 {
filter: hue-rotate(0);
}
100% {
filter: hue-rotate(360deg);
}
}
图16 动态背景颜色变换效果图
这些通过CSS动画或JavaScript控制去实时改变元素上的滤镜效果,从而在页面上产生动态变化的视觉效果又叫做动态滤镜效果,那与之相对应的不会发生改变或动态变化自然就是静态滤镜效果。静态滤镜效果在开发中经常被使用,下面我们就来聊聊在日常营销业务中的一些常见的静态滤镜的使用场景。
基于一些特殊时期或者特定重大事件的背景下,我们需要把网站页面变成黑白色或灰色,以表尊敬和纪念。实现网页的置灰效果并不需要将所有的图片和文字都手动换成灰色,这种方法十分繁琐且不现实。它的实现主要是通过filter的grayscale属性,由于滤镜filter会直接影响所有的后代元素,所以只需要给html添加一个统一的灰色滤镜就可以。
html {
filter: grayscale(.95);
}
图17 网页置灰效果图
我们在集卡活动中经常会看到,未点亮的卡片是暗色显示,只有获得了此卡才会高亮显示。这种明暗效果的实现并不用区分点亮和未点亮的卡片进行显示,这其实就可以使用filter的brightness属性进行实现,默认情况下降低亮度,只有点亮了的卡片才恢复亮度。
.unactive {
filter: brightness(0.5);
}
.active {
filter: brightness(1);
}
图18 集卡明暗效果图
大多数情况下设计提供给我们的图片都是直接使用,如果需要加上阴影的话会默认在图片上进行处理。那么如果是配置化的图片需要统一加上阴影效果呢,开发侧能不能进行统一处理?能的话又要怎么处理呢?
打个比方我们需要给下面的卡券图片再加个阴影效果:
图19 卡券图片
设置阴影的方式我们脑子里肯定首先就会想到box-shadow属性,我们先来看看它的的使用方式。
box-shadow: offset-x offset-y blur spread color inset;
从box-shadow接受的参数可以看出,drop-shadow可接受的参数和box-shadow属性基本是一样的,但不包含扩张半径spread和inset内阴影等关键字。那他们实现的阴影效果是不是一样的呢?我们先用box-shadow来实现看看。
box-shadow: 2px 4px 3px rgba(50, 50, 0, 0.5);
图20 卡券图片box-shadow效果图
如上图阴影是加了,但是好像哪里不太对,为什么直接给图片外围增加了一个阴影,并没有在卡券本身添加阴影呢?
这是因为在给透明图片添加阴影效果时无法穿透元素,只能添加到透明图片元素的盒模型上,所以最终呈现效果如上图所示。下面我们来使用filter的drop-shadow属性看看。
filter: drop-shadow(2px 4px 3px rgba(50, 50, 0, 0.5));
图21 卡券图片drop-shadow效果图
如上图才是我们期望的效果,阴影效果只作用到卡券本身,这说明drop-shadow的阴影效果是可以穿透透明元素的。除此之外,通过滤镜一些浏览器为了更好的性能会提供硬件加速。但是在使用drop-shadow的投影时,需要注意的是任何非透明的部分都会被打上投影,包括文本(如果背景是透明的)。
图22 drop-shadow效果对比图
毛玻璃效果是一种常见的视觉效果,它模拟了玻璃表面上由于光线折射而产生的模糊和透明感。我们经常需要使用毛玻璃效果处理内容模糊,以此达到一个信息保护的效果,或者进行背景模糊突出主要内容,引导用户进行操作,在日常开发中其实就是使用了filter的blur属性进行实现的。比如说我们需要给一些产品卡片设置毛玻璃效果:
图23 毛玻璃效果范围超出对比图
使用filter添加模糊后,实际看到的大小会超出我们设置的宽高,这是由于周围的毛边效果产生的,我们可以通过外层设置 overflow: hidden进行处理。不过其实使用filter实现的毛玻璃效果并不是唯一且最好的方式,我们也可以用backdrop-filter属性去实现漂亮的毛玻璃效果,我们来看看他们的实现效果有什么区别。
图24 毛玻璃效果对比图
从上图可以看出,filter明显是对图片本身进行了一个模糊处理,而dropback-filter却像是有一个模糊的遮罩层在上面,我们来看看具体的元素结构。
图25 毛玻璃效果元素结构对比图
由元素结构可以看出,使用backdrop-filter的效果确实比使用filter的效果多了一层置于图片上层的元素,blur效果也并不是作用于图片本身,而是作用于图片的上层元素。
没错,backdrop-filter并不是通过处理图片本身来实现毛玻璃的效果,而是通过在图片上面盖上一个模糊层从而达到毛玻璃的效果,因此要做模糊处理的图片必须置于使用backdrop-filter元素的下面。
那么这个backdrop-filter又是什么呢,与filter又有什么关系或者有区别呢?
backdrop-filter可以给元素后面区域添加图形效果(如模糊或颜色偏移),而filter属性是将模糊或颜色偏移等图形效果应用于元素。虽然backdrop-filter使用方式同filter属性一致,但它适用于元素背后的所有元素,不过为了看到效果,必须使元素或其背景至少部分透明。
既然backdrop-filter和filter的语法相同,那所支持的滤镜效果和呈现效果会不会也一样呢?
属性值 | filter | drop-filter | 说明 |
blur | 支持 | 支持 | 高斯模糊 |
brightness | 支持 | 支持 | 亮度 |
contrast | 支持 | 支持 | 对比度 |
drop-shadow | 支持 | 支持 | 阴影 |
grayscale | 支持 | 支持 | 灰度 |
hue-rotate | 支持 | 支持 | 色相 |
invert | 支持 | 支持 | 反相 |
opacity | 支持 | 支持 | 透明度 |
sepia | 支持 | 支持 | 饱和度 |
saturate | 支持 | 支持 | 褐色 |
url | 支持 | 支持 | SVG过滤器的URL |
由上可知,filter和backdrop-filter支持的滤镜是一模一样的。不过,与filter 不同的就是backdrop-filter是应用于元素后面的内容而不是元素本身,而filter却是作用于元素本身,所以呈现出来的滤镜效果当然是有些不同的。为了更好地看出作用元素的区别,我们再举个简单的例子,依然是模糊效果。
<div class="main">
<div class="child">none</div>
<div class="child filter">filter</div>
<div class="child backdrop-filter">backdrop-filter</div>
</div>
.main {
width:100vw;
height:100vh;
display: flex;
align-items: center;
justify-content: center;
background: url("xxx.png");
background-size: cover;
}
.child {
width: 400px;
height:300px;
color: #fff;
font-size: 20px;
text-align: center;
line-height: 300px;
background: rgba(0, 0, 0, .7);
margin-left: 20px;
}
.filter {
filter: blur(8px);
}
.backdrop-filter {
backdrop-filter: blur(8px);
}
图26 滤镜作用元素效果对比图
由上图我们可以看到filter属性确实只将作用元素本身进行了模糊处理,包括元素的背景和文本内容,而backdrop-filter作用的元素本身却没有任何效果,但是它背后的背景图片部分确实被进行了模糊处理,其实在出现backdrop-filter属性之前,是很难实现给元素背后特定的区域添加滤镜效果的。
那既然滤镜的这两个属性都这么厉害为什么还是不怎么常见,难道是因为兼容性不太好吗?
图27 filter兼容性说明图
filter属性在现代浏览器中有很好的支持,包括Chrome、Firefox、Safari、Edge等主流浏览器,部分版本仍需要添加前缀进行兼容性处理。
图28 dropback-filter兼容性说明图
dropback-filter属性的兼容性相对较低,仅在一些较新版本的浏览器中得到支持,且安卓移动端支持较弱。
由上可知,filter属性在大部分浏览器中具有良好的兼容性,但只能调整元素本身的效果;backdrop-filter属性适用于调整元素后面内容的效果,但兼容性相对较差。所以还是需要根据具体的需求和是否需要广泛支持的场景,选择适合的属性去进行对应滤镜效果的处理。
需要注意的是:作用了filter和backdrop-filter的元素会使内部的fixed定位失效,原因是filter值不为none的元素和backdrop-filter值不为none的元素,都会生成新的堆叠上下文。我们都知道css中position: fixed是相对于屏幕视口进行定位的,而作用了filter和backdrop-filter的元素会使得其内部的position: fixed元素不再相对于屏幕视口进行定位,而是相对这个父元素进行定位。
CSS滤镜技术是一个强大而有趣的工具,可以在不依赖图像编辑软件的情况下,在网页设计中应用不同的滤镜效果,也可以为元素增添生动、丰富的视觉效果。
在本文中,我们先介绍了各种滤镜函数的基础用法和显示效果,了解了它们如何改变元素的外观和视觉表现。随后,我们了解了如何通过灵活地应用不同的滤镜函数和组合,去创造出更复杂、个性化的滤镜效果,去实现图像处理和动画,为网页设计增添了更多创意和动感。我们还知道了通过使用filter属性,可以简单地应用模糊(blur)、对比度(contrast)和亮度(brightness)调整、颜色调整等效果,让网页元素瞬间焕发生机。而backdrop-filter属性则允许我们对元素背景内容进行处理,为网页带来更深度的视觉层次。
但是,在使用滤镜效果时我们也要考虑兼容性和性能问题,尽量避免过度使用滤镜造成页面加载缓慢。虽然大多数现代浏览器都支持CSS滤镜,但一些高级滤镜在较旧的浏览器或移动设备上可能会有兼容性问题。因此,我们在使用滤镜时需要进行兼容性测试,并在必要时提供备用方案,以确保在不同平台和设备上都能展现良好的效果。
本文作者
柯琦,来自缦图互联网中心前端团队。
来源-微信公众号:缦图coder
出处:https://mp.weixin.qq.com/s/x15DGBjOyL8EWtt78xJESg
度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。
灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
灰度发布常见一般有三种方式:
本文主要将讲解根据Cookie和来路IP这两种方式实现简单的灰度发布,Nginx+LUA这种方式涉及内容太多就不再本文展开了。
A/B测试流程
根据Cookie查询Cookie键为version的值,如果该Cookie值为V1则转发到hilinux_01,为V2则转发到hilinux_02。Cookie值都不匹配的情况下默认走hilinux_01所对应的服务器。
两台服务器分别定义为:
hilinux_01 192.168.1.100:8080
hilinux_02 192.168.1.200:8080
upstream hilinux_01 {
server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream hilinux_02 {
server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
}
upstream default {
server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
server {
listen 80;
server_name www.hi-linux.com;
access_log logs/www.hi-linux.com.log main;
#match cookie
set $group "default";
if ($http_cookie ~* "version=V1"){
set $group hilinux_01;
}
if ($http_cookie ~* "version=V2"){
set $group hilinux_02;
}
location / {
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
在Nginx里面配置一个映射,$COOKIE_version可以解析出Cookie里面的version字段。$group是一个变量,{}里面是映射规则。
如果一个version为V1的用户来访问,$group就等于hilinux_01。在server里面使用就会代理到http://hilinux_01上。version为V2的用户来访问,$group就等于hilinux_02。在server里面使用就会代理到http://hilinux_02上。Cookie值都不匹配的情况下默认走hilinux_01所对应的服务器。
upstream hilinux_01 {
server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream hilinux_02 {
server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
}
upstream default {
server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
map $COOKIE_version $group {
~*V1$ hilinux_01;
~*V2$ hilinux_02;
default default;
}
server {
listen 80;
server_name www.hi-linux.com;
access_log logs/www.hi-linux.com.log main;
location / {
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
如果是内部IP,则反向代理到hilinux_02(预发布环境);如果不是则反向代理到hilinux_01(生产环境)。
upstream hilinux_01 {
server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream hilinux_02 {
server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
}
upstream default {
server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
server {
listen 80;
server_name www.hi-linux.com;
access_log logs/www.hi-linux.com.log main;
set $group default;
if ($remote_addr ~ "211.118.119.11") {
set $group hilinux_02;
}
location / {
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
如果你只有单台服务器,可以根据不同的IP设置不同的网站根目录来达到相同的目的。
server {
listen 80;
server_name www.hi-linux.com;
access_log logs/www.hi-linux.com.log main;
set $rootdir "/var/www/html";
if ($remote_addr ~ "211.118.119.11") {
set $rootdir "/var/www/test";
}
location / {
root $rootdir;
}
}
到此最基本的实现灰度发布方法就讲解完了,如果要做更细粒度灰度发布可参考ABTestingGateway项目。
ABTestingGateway是新浪开源的一个动态路由系统。ABTestingGateway是一个可以动态设置分流策略的灰度发布系统,工作在7层,基于nginx和ngx-lua开发,使用redis作为分流策略数据库,可以实现动态调度功能。
ABTestingGateway:https://github.com/CNSRE/ABTestingGateway
SS是一个很独特的语言。看起来非常简单,但是某种特殊效果看似简单,实现起来就颇有难度。这篇文章主要是给在学习前端的童鞋分享一些新的CSS技巧,一些在前端教程和培训课堂中不会讲到的知识。第二就是让还在前端开发这条道路上的童鞋们,重新燃起对前端排版和特效的热爱和热情!
这种是一个非常常见的布局方式,但是对于新手来说是比较常见的难题。
这种布局方式在后台管理系统中比较常见,当我们内容不足浏览器窗口高度时,底部内容需要固定在底部。当内容超出了浏览器窗口高度,就会随着内容往后推。
在有CSS3之前,实现这个效果是颇有难度的。浏览器窗口高度是会根据不同用户打开浏览器的情况,屏幕大小的差异和浏览器的缩放比例而变。我们需要借助JavaScript来实时获取浏览器高度进行运算才能实现。虽然说标题是说“固定”底部,但是我们想要的效果不是position: fixed。使用固定定位,在内容高于窗口高度时,就会挡住我们的内容。
随着CSS3的来临,最完美的实现方式是使用Flexbox。实现的关键就是使用不太被关注的flex-grow属性,可以在我们的内容标签元素(比如div)中使用。在我们下面的例子里使用了main标签。
我来讲解一下实现原理吧。
flew-grow是用来控制一个flex元素相对它同等级flex元素的自身可扩充的空间。如果我们使用flex-grow: 0,那这个flex元素就完全不会扩展了。所以我们需要把头部和底部之间的内容标签元素设置为flex-grow: 1或者flex-grow: auto,这样内容部分就会自动填充满头部和底部之外的所有空间。
为了避免底部内容受内容部分扩充空间的影响,我们给footer底部元素flex-shrink: 0属性。flex-shrink的作用与flex-grow是恰恰相反,用来控制flex元素收缩的空间,这里我们给了flex-shrink: 0就是为了底部footer的大小不受影响。
我们直接上HTML和CSS代码看看是怎么实现的。
<div id="document">
<nav>
<h1>头部内容</h1>
</nav>
<main>
<p>可以添加更多内容看看底部的变化哦!</p>
</main>
<footer>
<h1>底部内容</h1>
</footer>
</div>
#document {
height: 100vh;
display: flex;
flex-direction: column;
background: #202020;
font-family: microsoft yahei,wenquanyi micro hei,sans-serif !important;
}
nav, footer {
background: #494949;
display: flex;
justify-content: center;
}
main {
color: #bdbdbd;
flex: auto;
}
footer {
flex-shrink: 0;
}
* {
margin: 0;
}
h1,
p {
padding: 15px;
}
nav > h1 {
color: #82FCFD;
text-shadow: 1px 1px 4px #00000080;
}
footer > h1 {
color: #82FCFD;
text-shadow: 1px 1px 4px #00000080;
}
知识点总结:
flex-grow --- 是用来控制一个flex元素相对它同等级flex元素的自身可扩充的空间 flex-shrink --- 作用与flex-grow是恰恰相反,用来控制flex元素收缩的空间
悬停放大图片是一个特别吸引眼球的特效,比较常用于可点击的图片。当用户悬停鼠标在图片上,图片会稍微的放大。
其实实现这个特效是非常简单的。首先我们需要一个div包裹这img标签,这个包裹层是用来遮挡住图片,当图片放大时不会出现图片超出我们规定的宽高以外。
首先我们来讲讲div包裹的属性,我们需要给它一个固定的width宽和height高。然后我们必须给予这个元素overflow: hidden属性。让图片放大的时候不会超出这个div元素的宽高。有了这个包裹层,我们就可以编写img的各种效果了。
我的例子里面用了transform: scale(1,1)作为悬停时的图片特效,这个transform是用于改变任何元素的属性的,然后scale是用于放大(整数就会放大)或者缩小(负数就会缩小)元素的。
上代码让大家看看:
<div class="img-wrapper">
<img src="https://img-blog.csdnimg.cn/2020032122230564.png"/>
</div>
.img-wrapper {
width: 400px;
height: 400px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}
.img-wrapper img {
height: 400px;
-webkit-transition: 0.3s linear;
transition: 0.3s linear;
}
.img-wrapper img:hover {
transform: scale(1.1);
}
.img-wrapper {
display: inline-block;
box-sizing: border-box;
border: 3px solid #000;
}
如果你们想让图片更加炫酷可以加上图片过滤属性filter,让图片变灰或者变深褐色,然后悬停时候出现更加炫酷的颜色变幻。灰化的属性是filter: grayscale(100%);,然后深褐色化的属性是filter: sepia(100%)。其实图片还有很多过滤属性的,大家有兴趣也可以去尝试一下哦!
加入特殊效果的代码如下:
<!-- 灰度过滤 -->
<div class="img-wrapper">
<img
class="grayscale-img"
src="https://img-blog.csdnimg.cn/2020032211021728.png"
/>
</div>
<!-- 深褐色过滤 -->
<div class="img-wrapper">
<img
class="sepia-img"
src="https://img-blog.csdnimg.cn/2020032122230564.png"
/>
</div>
/* ==============
* 灰度过滤
* ==============*/
.grayscale-img {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.grayscale-img:hover {
-webkit-filter: grayscale(0);
filter: grayscale(0);
}
/* ==============
* 深褐色过滤
* ==============*/
.sepia-img {
-webkit-filter: sepia(100%);
filter: sepia(100%);
}
.sepia-img:hover {
-webkit-filter: sepia(0);
filter: sepia(0);
}
知识总结
transform --- 用于改变元素 scale --- 对元素进行放大和缩小 filter --- 图片过滤器 grayscale --- 灰度过滤 sepia --- 深褐色过滤
最近微信也逃脱不了黑暗时代的到来,网页也很多都做了黑暗模式的兼容和主题。如果我们在做的一个网站想瞬间实现黑暗模式可以怎么实现呢?
其实有一个很快的方式,我们可以使用invert和hue-rotate两个CSS3过滤器来实现。
filter: invert() — 是从0到1的刻度,1是从白变黑。 filter: hue-rotate() — 用于改变你元素的颜色,同时或多或少保持原本相同的色系。这个属性的值可以从0deg到360deg。
在我们页面的body标签上添加这两个属性,我们就可以快速尝试把我们的网站变成"黑暗模式"。这里需要注意的是,如果body和html上没有设置background背景颜色,这个过滤就会不起效了哦。
CSS的代码如下:
html {
background: #fff;
}
body {
background: #fff;
filter: invert(1) hue-rotate(270deg);
}
实现效果
这里我们会发现图片的颜色会受影响,并不是很美观,使用css过滤器是无法完美切换黑暗模式的。不过使用JavaScript辅助就可以完美的切换黑暗模式。
最近出了一个JavaScript辅助插件叫Darkmode.js。
其实Darkmode.js运用的也是css里面的一个特性叫mix-blend-mode — “CSS 属性描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合“。加上Javascript的辅助判断哪些页面上的元素需要黑化的,哪些是不需要黑化的。就会想我们之前那种做法,导致其他不需要黑化的元素,比如图片,受到影响导致颜色出现问题。
使用Darkmode.js非常简单,只要在脚本里面添加以下代码就可以马上加入一个插件,
<script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.5/lib/darkmode-js.min.js"></script>
<script>
// 这些是这个插件的可配置项:
var options = {
bottom: "32px", // 定位底部距离 - 默认: '32px'
right: "32px", // 定位右边距离 - 默认: '32px'
left: "unset", // 定位左边距离 - 默认: 'unset'
time: "0.5s", // 默认动画时间: '0.3s'
mixColor: "#fff", // 需要改变的颜色 - 默认: '#fff'
backgroundColor: "#fff", // 背景颜色 - 默认: '#fff'
buttonColorDark: "#262728", // 黑暗模式下按钮颜色 - 默认: '#100f2c'
buttonColorLight: "#fff", // 日间模式下按钮颜色 - 默认: '#fff'
saveInCookies: true, // 是否在cookie保存当前模式 - 默认: true,
label: "", // 切换模式按钮图标 - 默认: ''
autoMatchOsTheme: true // 是否自动根据系统适应模式 - 默认: true
};
let darkmode = new Darkmode(options);
darkmode.showWidget();
</script>
如果你不希望用这个插件的默认按钮,你可以在你的JavaScript代码中自主控制。我们可以通过.toggle()方法来切换模式,同时可以使用.isActivated()来检测是否已经进入黑暗模式。
const darkmode = new Darkmode();
darkmode.toggle();
console.log(darkmode.isActivated()) // 如果已经进入黑暗模式会返回 true
知识总结
filter: invert() — 可以把页面从白变黑,也可以从黑变白。 filter: hue-rotate() — 用于改变你元素的颜色,同时或多或少保持原本相同的色系。 Darkmode.js — 瞬间实现黑暗模式。
ul,li的无序列表有默认的符号·,但是在很多情况下我们希望可以给这个符号加入自己的样式和颜色,甚至是换成自定义的符号。默认的符号我们是无法做任何的样式处理,而且默认的符号在CSS属性里面只有几个选择可以使用,很多情况下都是无法满足我们的设计。
其实自定义无序列表符号不难,我们只需要使用伪类::before加content属性就可以实现。
在我这个例子里面我做了两个任务列表,一个是待处理任务,一个是已完成任务,各自给了不一样的列表符号和颜色。
实现原理
一、首先我们禁用了ul的默认符号样式list-style: none
二、在li的:before伪类上给予content内容值,待处理任务使用,已完成任务li.completed:before使用✔
三、为了展示效果更加好看我分别给了li和li .completed两个不同的颜色
上代码看看是怎么实现的吧:
HTML
<div>
<h2>待处理</h2>
<ul>
<li>待办任务1</li>
<li>待办任务2</li>
<li>待办任务3</li>
<li>待办任务4</li>
<li>待办任务5</li>
</ul>
</div>
<div>
<h2>已完成</h2>
<ul>
<li class="completed">完成任务1</li>
<li class="completed">完成任务2</li>
<li class="completed">完成任务3</li>
</ul>
</div>
CSS
ul {
list-style: none;
color: #fff;
font-size: 20px;
border: 3px solid #000;
padding: 1rem 2rem;
min-height: 200px;
margin: 15px 2rem 0 0;
background: #323232;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
border-radius: 8px;
}
li {
padding: 0.3rem 0;
}
li::before {
content: " ";
color: aqua;
}
li.completed::before {
content: "✔ ";
text-decoration: none;
color: greenyellow;
}
li.completed {
text-decoration: line-through;
color: #bdbdbd;
}
::before和::after伪类加content属性可以用来做很多特殊的效果,也是当代前端排版比较常用的“魔法”。说到伪类的使用,我再给大家说一个比较常用的使用场景。
在管理后台或者是文章展示中,我们经常可以见到的“面包屑导航”也是用伪类来插入每个目录中间的符号的。
实现逻辑
一、这个导航含有3个a标签,首先给每个a标签加入一个伪类::after,然后在content属性插入/符号。
二、然后使用a:first-child,这个伪类会选择到第一个a标签,然后使用content属性加入»符号。
三、因为我们第一步在每个a标签的后面插入了/符号, 所以我们需要在最后一个a标签清除掉。这里我们使用:last-child选择到最后一个a标签,然后用content: " "属性把伪类的内容清楚掉。
HTML
<div class="breadcrumb">
<a>三钻</a>
<a>前端</a>
<a>教程</a>
</div>
CSS
.breadcrumb {
font-size: 1.6rem;
color: #fff;
}
.breadcrumb a:first-child {
color: #82fcfd;
}
.breadcrumb a:first-child::before {
content: " » ";
}
.breadcrumb a::after {
content: " /";
color: #ef6eae;
}
.breadcrumb a:last-child::after {
content: "";
}
知识总结
::before | ::after — 伪类用于向某些选择器添加特殊的效果。 content — CSS 属性用于在元素的 ::before 和 ::after 伪元素中插入内容。使用content 属性插入的内容都是匿名的可替换元素。 :first-child — CSS伪类表示在一组兄弟元素中的第一个元素。 :last-child — CSS伪类代表父元素的最后一个子元素。
这个超级炫酷的效果在官网中非常的受欢迎,这种效果可以给用户带来视觉冲击,也给我们的网站带来了活力。普通的网页图片会跟随着网页一起滑动,但是视觉差效果图就会固定在底部,只有图片所在的窗口上的元素会移动。
对你没有看错,这个效果只需要用到CSS就能轻易的实现!我们只要使用一个CSS背景图的属性background-attachment: fixed,这个特性会把背景相对于视口固定。即使一个元素拥有滚动机制,背景也不会随着元素的内容滚动。
实现理论:
一、在含有图片的元素中加入background: url()和background-size: cover(第二个属性适用于定义图片为封面,可以让图片大小自动适应,在很大的屏幕也会显示完整的图片)
二、然后附加固定背景图的属性background-attachment: fixed
三、最后给这个元素加入一个高度height: 100%或者任意的高度height: 400px
就那么简单哦!不用怀疑,马上上代码,大家都可以自己去试试哦!
HTML
<div class="wrapper">
<div class="parallax-img"></img>
<p>这里填写一堆文字就可以了,尽量多一点哦</p>
</div>
CSS
.wrapper {
height: 100wh;
}
.parallax-img {
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
height: 100%;
background-image: url("http://ppe.oss-cn-shenzhen.aliyuncs.com/collections/182/7/thumb.jpg");
}
p {
font-size: 20px;
padding: 1.5rem 3rem;
min-height: 1000px; // 当你的文字内容不够,也能撑出足够的高度来看到效果,当然如果你文字足够多,就不需要了
}
如果想做到我动图里面一样的效果,或者想看是怎么实现的,可以查看下面总结里面的“预览实际效果”或者看“GitHub源码”。
知识总结
background-attachment: fixed — 把背景相对于视口固定。即使一个元素拥有滚动机制,背景也不会随着元素的内容滚动。 background-size: cover — 可以让图片大小自动适应,在很大的屏幕也会显示完整的图片。
有些童鞋可能没有被这个震撼到或者还是觉得不够刺激。那我们再来一个高级例子,上面的例子在滑动的时候图片是固定死的。如果我们加上JavaScript的助力,我们可以让窗口的图片缓慢的跟随这个页面滑动,使得效果更有动力和更有冲击感。
实现理论 首先讲一下排版,因为我们需要在我们滑动页面的时候使用JavaScript偏移图片,所以我们需要给图片一个CSS属性让我们可以让图片可以根据一个速度来往上或者往下移动。这个例子里面我们让所有图片包裹在一个div里面,class名为block。这个div给予相对定位属性position: relative,这个时候我们就可以在里面加入图片,然后让图片绝对定位position: absolute在这个div盒子里面。
但是图片是可能很大的,我们需要把图片不超出我们定义个盒子,所以我们的div同时也给予了overflow: hidden和一个高度height: 100%。这样图片超出div盒子就会被隐藏。
布局代码如下:
<div class="block">
<img
src="https://unsplash.it/1920/1920/?image=1005"
data-speed="-1"
class="img-parallax"
/>
<h2>视差速度 -1</h2>
</div>
<div class="block">
<img
src="https://unsplash.it/1920/1920/?image=1067"
data-speed="1"
class="img-parallax"
/>
<h2>视差速度 1</h2>
</div>
html, body{
margin: 0;
padding: 0;
height: 100%;
width: 100%;
font-family: 'Amatic SC', cursive;
}
.block{
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
font-size: 16px;
}
.block h2{
position: relative;
display: block;
text-align: center;
margin: 0;
top: 50%;
transform: translateY(-50%);
font-size: 10vw;
color: white;
font-weight: 400;
}
.img-parallax {
width: 100vmax;
z-index: -1;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%,0);
pointer-events: none
}
实现这个布局,在你滑动的时候,图片是不会移动的。因为最后一步就是加入JavaScript的辅助,让图片活起来。
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
// 循环获取每一个图片元素
$(".img-parallax").each(function () {
var img = $(this);
var imgParent = $(this).parent();
function parallaxImg() {
var speed = img.data("speed"); // 获取每张图片设置了的偏移速度
var imgY = imgParent.offset().top; // 获取图片盒子所在的Y位置
var winY = $(this).scrollTop(); // 获取当前滑动到的位置
var winH = $(this).height(); // 获取浏览器窗口高度
var parentH = imgParent.innerHeight(); // 获取图片盒子的内高度
// 浏览器窗口底部的所在位置
var winBottom = winY + winH;
// 当前图片是否进入浏览器窗口
if (winBottom > imgY && winY < imgY + parentH) {
// 运算图片需要开始移动的位置
var imgBottom = (winBottom - imgY) * speed;
// 运算出图片需要停止移动的位置
var imgTop = winH + parentH;
// 获取从开始移动到结束移动的%(根据开始与结束像素 + 移动速度)
var imgPercent = (imgBottom / imgTop) * 100 + (50 - speed * 50);
}
img.css({
top: imgPercent + "%",
transform: "translate(-50%, -" + imgPercent + "%)",
});
}
$(document).on({
scroll: function () {
parallaxImg();
},
ready: function () {
parallaxImg();
},
});
});
</script>
知识总结
position: relative — 相对定位。 position: absolute — 绝对定位。 overflow: hidden — 如果需要,内容将被剪裁以适合填充框。 不提供滚动条。
在有CSS3之前裁剪图片实现也是颇有难度的。现在我们有了两个非常方便简单的CSS3属性可以实现裁剪,那就是object-fit和object-position, 这两个属性可以让我们改变图片的大小,但是不影响图片的长宽比。
当然我们可以使用图片处理工具或者使用JavaScript等插件来实现图片裁剪功能。但是因为有了CSS3的属性,我们不只可以裁剪,我们还可以用裁剪的属性来做图片的动态效果。
为了让我们的例子更加简单,我们这里使用了<input type="checkbox">复选框元素,这样我们就可以使用:checked的伪类来触发启动效果。所以在例子里面我们完全不需要JavaScript的协助。
实现原理:
一、首先给予图片一个宽高height: 1080px,width: 1920px。
二、然后用CSS选择器,锁定当input被选中后img标签的样式变化。当被选中时,给图片设定一个新的宽高,这里我们给宽高各自500像素:width: 500px,height: 500px。
三、然后我们加上了过渡效果和时间让图片改变宽高时有动画过渡效果:transition: width 2s, height 4s;。
四、最后加上object-fit: cover和object-position: left-top这两个属性来保持图片的宽高比例,这样就大功告成了!
我们来看看完成的代码:
勾选裁剪图片 <input type="checkbox" />
<br />
<img
src="https://img-blog.csdnimg.cn/2020032122230564.png"
alt="Random"
/>
input {
transform: scale(1.5); /* 只是用来放大复选框大小 */
margin: 10px 5px;
color: #fff;
}
img {
width: 1920px;
height: 1080px;
transition: 0s;
}
/* css选择器锁定复选框被选中时的状态 */
input:checked + br + img {
width: 500px;
height: 500px;
object-fit: cover;
object-position: left-top;
transition: width 2s, height 4s;
}
知识总结
object-fit — CSS 属性指定可替换元素的内容应该如何适应到其使用的高度和宽度确定的框。 object-position — 用来切换被替换元素的内容对象在元素框内的对齐方式。 transition — 过渡可以为一个元素在不同状态之间切换的时候定义不同的过渡效果。
如果有使用过Photoshop的同学对blend混合模式应该是非常熟悉了,我们都知道混合模式是非常强大,也是p图时非常常用的一个功能。但是你们有没有想象过可以在浏览器的CSS中直接使用呢?对我们不需要设计师给我们做图,我们前端也可以实现混合模式了。
在CSS中我们不只可以对background背景加入混合模式,我们可以对任何一个元素的自带背景加入混合模式,让你可以做出很多之前没有想过的效果和排版。
往一个元素加入混合模式,我们只需要使用到一个CSS属性mix-blend-mode即可。
简单实现原理:
首先我们只需要加一个h1标题标签
<h1>混合模式:颜色减淡</h1>
然后我们给h1标签加入mix-blend-mode中的颜色减弱模式color-dodge,但是要注意的是我们需要给body和html加入背景颜色background: white,要不你会发现这个效果会无效。因为h1我们没有给颜色,会自动往上级继承,并且混合模式是针对背景颜色的过滤,所以body和html需要有背景颜色才行。
h1 {
mix-blend-mode: color-dodge;
font-family: yahei;
font-size: 5rem;
text-align: center;
margin: 0;
padding: 20vh 200px;
color: #D1956C;
}
html,
body {
margin: 0;
background-color: white;
}
body {
background-image: url(https://images.unsplash.com/photo-1505567745926-ba89000d255a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3302&q=80);
background-repeat: no-repeat;
background-size: cover;
min-height: 100vh;
overflow: hidden;
}
换换背景图和h1标签的字体颜色就可以弄出各种不同的特效了。
知识总结
mix-blend-mode — CSS 属性描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。
CSS Grid和Flexbox让我们可以更简便,更容易和更快的实现各式各样的响应布局,并且让我们快捷方便的在布局中实现横向剧中和竖向剧中。但是回想一下以前是颇为困难的。
虽然这些新出的布局方式可以让我们解决很多以前的布局难题,但是像瀑布流布局这种,就无法用它们简单来实现了。因为瀑布流一般来说都是宽度一致,但是高度是根据图片自适应的。并且图片的位置也是根据在上方图片的位置而定的。
其实最好实现瀑布流布局的办法就是用CSS的列属性套件,这套属性大多数都是用于排版杂志中的文本列。但是用于布局瀑布流也是特别实用哦。因为以前需要实现瀑布流,就必须有JavaScript的辅助来计算图片高度然后决定每张图片的定位和位置,所以现在有了列属性就可以使用纯CSS实现了。
实现原理:
实现这个布局,首选我们需要把所有的内容先包裹在一个div元素里面,然后给这个元素column-width和column-gap属性。
然后,为了防止任何元素被分割到两个列之间,将column-break-inside: avoid添加到各个元素中。
神奇的效果就完美实现了,零JavaScript。
我们来看看代码:
<div class="columns">
<figure>
<img src="https://source.unsplash.com/random?city" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?night" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?developer" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?building" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?water" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?coding" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?stars" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?forest" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?girls" alt="" />
</figure>
<figure>
<img src="https://source.unsplash.com/random?working" alt="" />
</figure>
</div>
.columns {
column-width: 320px;
column-gap: 15px;
width: 90%;
max-width: 1100px;
margin: 50px auto;
}
.columns figure {
display: inline-block;
box-shadow: 0 1px 2px rgba(34, 25, 25, 0.4);
column-break-inside: avoid;
border-radius: 8px;
}
.columns figure img {
width: 100%;
height: auto;
margin-bottom: 15px;
border-radius: 8px;
}
知识总结
column-width — CSS属性建议一个最佳列宽。 列宽是在添加另一列之前列将成为最大宽度。 column-width — 该 CSS 属性用来设置元素列之间的间隔 (gutter) 大小。 column-break-inside — 设置或检索对象内部是否断。
我希望这8个前端小技巧和特效对大家有帮助,或多或少有吸收一点新的前端知识。这篇文章提到的内容,其实很多都是值得深挖和学习的。有一些例子我做的比较简单,但是其实是有无限的可能性。喜欢前端的童鞋们,让我们继续在前端领域中一起深挖,让我们的热爱无限的燃烧起来吧!
在最后我想给大家讲一下我对前端的热爱和态度。
回想前端这几年,发展真的是突飞猛进,从前端排版,HTML5+CSS3做H5页面,到前端组件化,各种UI框架满天飞。
一开始我随着热潮用起了UI框架,起初觉得特别方便,来一个新的项目就直接上一个UI框架,研发速度也非常快。但是久而久之就觉得前端开发变成了处理数据,对接接口,实现交互。
某天在阅览国外的一些前端设计和框架的时候,我突然发现国内多数的前端开发者都不再怎么使用CSS3做出一些很好玩的布局和特效了。现在市面上的系统和页面都是千篇一律,普遍都是用一些知名的UI框架搭建系统和APP,基本自己动手去排版已经少之又少。前端已不再是以前的前端,缺少了灵魂。
但是我们回想一下,我们刚刚开始学习前端的时候,让我们最有成就感,觉得前端特别有意思的那种感觉。就是那种让我们觉得神乎奇迹,不可思议的布局,特效和交互。那种感觉自己成功实现了很优美,很炫酷的页面和特效的感觉,让我们越做越来劲,越做越是兴奋。
但是在某些公司,研发部都是要求快速开发,UI设计部门也是受到时间的控制和限制,所以逐步走进了UI框架的限制之中。都是围绕这一些UI框架来设计和开发系统和应用。
作为一名热爱前端的开发者,我还是坚持在绝大多数的项目中,自己排版和实现页面交互特效。然后使用UI框架作为辅助,主要是用来减轻一些小组件和常用组建的快速实现。(可以说我是比较追求完美和外貌协会的程序员 )
作者:三钻
链接:https://juejin.im/post/5e8fc7826fb9a03c677e68d9
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*请认真填写需求信息,我们会在24小时内与您取得联系。