编写CSS样式时,其实有不少技巧能够节省HTML
元素和让CSS更加的DRY
,在这跟你们分享下。css
文章将分红上、中、下三篇,难度也会从简单到难,因此建议同窗们按顺序阅读起。html
文章将大量举各类示例,让同窗们能更加清楚CSS的魅力所在。前端
文章将持续输出,增长一些新奇的或者惟美的示例。。。浏览器
半透明边框相信不少前端小伙伴都常常遇到过,UI设计师
也常常性设计出这类样式。而若是对CSS
不太熟悉的前端小伙伴人员来讲,看似简单的东西,其实有一个小坑在里面。例:bash
...
<main class="wrapper">
<div class="border">我是边框</div>
</main>
...
.wrapper {
background: black;
...
}
.border {
width: 100px;
height: 100px;
background: white;
border: 10px solid hsla(0, 0%, 100%, 0.3);
}
复制代码
border
设置了0.3
的透明度,那是否是咱们要的半透明?让咱们看看结果。app
很显然不是的,background-clip
属性的初始值为border-box
,意味着背景默认状况下,会侵入边框的所在的范围,当属性值设置为padding-box
。svg
.border {
background-clip: padding-box
}
复制代码
box-shadow
咱们大多数人已经用过,不太为人所知的是,它还接受第四个参数,经过设置正直或负值,可让投影面积加大或者减少。函数
.border {
box-shadow: 0 0 0 10px red;
...
}
复制代码
使用box-shadow
的好处在于,它接受逗号分隔语法,能够建立任意数量的投影布局
.border {
box-shadow: 0 0 0 10px red, 0 0 0 20px yellow;
...
}
复制代码
box-shadow
是层层叠加的,前者会叠加在后者之上,上例中若是
yellow
须要宽度为
10px
,那么须要设置为
20px
。
多重投影在大多数场合均可以很好的应用,但有一些注意事项。测试
投影行为跟边框不彻底一致,由于它不会影响布局,并且也不会受
box-sizing
属性的影响。投影部分并不会影响鼠标事件。
若是咱们只须要两层边框的话,outline
(全部浏览器都支持 outline 属性)是一个不错的选择,它不会像box-shadow
只能模拟实现边框。
.border {
border: 10px solid #655;
outline: 5px dashed deeppink;
...
}
复制代码
outline-offset
属性来控制它跟元素边缘之间的间距,这个属性甚至能够接受负值。这对于某些效果来讲很是有用。举个例子
.border {
outline: 5px solid deeppink;
outline-offset: -79px;
}
复制代码
使用
outline
也有一些须要注意的地方。
outline
并不能接受用逗号分隔的多个值。边框不必定会贴合
border-radius
属性产生的圆角,所以若是元素是圆角的,它的描边可能仍是直角的。
背景图片指定在容器某个区域,也是很常见。
.border {
background: url('https://cdn.renqilai.com/2019_10_16/15_35_42.jpg') no-repeat white;
background-size: 30px 30px;
background-position: 60px 60px;
}
复制代码
background-position
扩展语法的浏览器上,背景图片会紧贴在左上角,看起来很奇怪,并且它会干扰到文字的可读性。提供一个回退方案也很简单,就是把老套的
bottom right 定位值写进 background
的简写属性中:
.border {
background: url(code-pirate.svg) no-repeat bottom right #58a;
background-position: 60px 60px;
}
复制代码
在给背景图片设置距离某个角的偏移量时,有一种状况极其常见:偏移量与容器的内边距一致。若是采用上面提到的 background-position
的扩展语法方案,代码看起来会是这样的:
padding: 10px;
background: url(code-pirate.svg) no-repeat #58a;
background-position: 80px 80px; // 分别增长20px
复制代码
咱们常用background-position:top left
,你是否有过疑惑,这个top left究竟是哪一个左上角?默认状况下,默认是以padding box
。而咱们使用background-origin
默认状况下是padding-box
。若是把它的 值改为 content-box
(参见下面的代码),咱们在 background-position
属 性中使用的边角关键字将会之内容区的边缘做为基准
background: url("code-pirate.svg") no-repeat #58a bottom right;
background-position: 70px 70px;
background-origin: content-box;
复制代码
不管咱们怎样更改padding
值,都不会去影响图片的定位了。
从上述两例得知,咱们无非是想获得图片距离白色右边框10px
,距离白色下边框10
px。使用calc
,它能够完美地在background-position
属性中使用:
background-origin: padding-box;
background-position: calc(100% - 20px) calc(100% - 10px);
复制代码
请不要忘记在 calc() 函数内部的 - 和 + 运算符的两侧各加一个空白符,不然会产生解析错误!这个规则如此怪异,是为了向前兼容:将来,在 calc() 内部可能会容许使用关键字,而这些关键字可能会包含连字符(即减号)
不管咱们怎样更改padding
值,都不会去影响图片的布局了。
若是咱们要实现内侧有圆角,外侧边框依旧保持着直角状态,如图:
咱们通常会使用两个元素实现,若是咱们须要一个元素,有没有方法实现?
在前面咱们提到过outline
描边,它并不会随border-radius
改变边框,依旧保持着直角状态。
outline: 5px solid deeppink;
border-radius: 10px;
box-shadow: 0 0 0 5px deeppink;
复制代码
这里box-shadow
第四个参数值为5px
,那这个值是如何获得的?是在某个浏览器测试的结果?事实上,指定一个等于描边宽度的扩张值在某些浏览器中可能会获得渲染异常,所以推荐一个稍小些的值。这里直接给出一个公式( 根号2 - 1)r
,其中r
为border-radis
的10px
,另外有一个限制,为了让这个效果得以达成,扩张半径须要比描边的宽度值小,但它同时又要比 (根号2 - 1)r
大。
线性渐变相信不少人都挺熟悉的,如何实现下图这种效果?
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
复制代码
若是我想将黄色部分的宽度减小,我须要去修改两个值,这种也不够DRY。
background: linear-gradient(#fb3 50%, #58a 0);
background-size: 100% 30px;
复制代码
将后者修改成0
,那它的位置就老是会被浏览器调整为前一个色标的位置值,便可显示出相同的效果。
在完成了水平以后,咱们来尝试下倾斜渐变的效果。
background: linear-gradient(45deg,#fb3 50%, #58a 0);
background-size: 30px 30px;
复制代码
贴片
内部渐变旋转45度,而不是把整个重复的背景都旋转了。实际上,若是想让整个背景看起来都旋转了45度,须要单个贴片包含了四条条纹,而不是两条,只有这样才有可能作到无缝拼接。
background: linear-gradient(45deg,#fb3 25%, #58a 0,
#58a 50%,#fb3 0, #fb3 75%, #58a 0);
background-size: 30px 30px;
复制代码
background: linear-gradient(60deg,#fb3 50%, #58a 0);
复制代码
repeating-linear-gradient()
(
radial-gradient()
也有),色标是无限循环重复的,直到填满整个背景。
background: repeating-linear-gradient(60deg,#fb3, #fb3 15px, #58a 0, #58a 30px);
// background-size: 30px 30px;
复制代码
逗号分隔
,其实这种也是能够简化的,如:
background: white repeating-linear-gradient(60deg,
blue 0 15px,
hsla(0, 0%, 0%) 0 30px,
red 0 45px);
复制代码
若是咱们将第一个参数不为0
会是怎样的状态?
background: white repeating-linear-gradient(60deg,
blue 10px 15px,
black 20px 30px,
red 0 45px);
复制代码
咱们将blue
第一个参数值为10px
,black
第一个参数值为20px
,red
保持不变。
咱们注意到,左下角再也不是以蓝色开头,而是红色开头。为何?缘由在于blue
色标起始位置为10px
,因此在左下角开始到10px
会被重复的渐变叠加到。
而色标blue
与black
之间有一层渐变的过程,由于blue
结束为15px
,而black
开始为20px
,他们之间存在着5px
的渐变过程。
大多数状况下,若是咱们想要的条纹图案色差不是差别极大的状况下,只是明度有着轻微的差别。举个例子,咱们来看看这个条纹图案:
background: repeating-linear-gradient(30deg,
#79b, #79b 15px, #58a 0, #58a 30px);
复制代码
幸运的是,还有一种更好的方法:再也不为每种条纹单独指定颜色,而是 把最深的颜色指定为背景色,同时把半透明白色的条纹叠加在背景色之上来 获得浅色条纹:
background: #58a;
background-image: repeating-linear-gradient(30deg,hsla(0,0%,100%,.1),
hsla(0,0%,100%,.1) 15px,transparent 0, transparent 30px);
复制代码
前面咱们举了各类简单的例子,接下来咱们尝试下稍微复杂点的状况。
background-image:linear-gradient(white 1px, transparent 0),
linear-gradient(90deg, white 1px, transparent 0);
background-size: 30px 30px;
复制代码
background-image: linear-gradient(white 2px, transparent 0),
linear-gradient(90deg, white 2px, transparent 0),
linear-gradient(hsla(0,0%,100%,.3) 1px,transparent 0),
linear-gradient(90deg, hsla(0,0%,100%,.3) 1px,transparent 0);
background-size: 75px 75px, 75px 75px,15px 15px, 15px 15px;
复制代码
background: #655;
background-image: radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
复制代码
background: #655;
background-image: radial-gradient(tan 30%, transparent 0),
radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
复制代码
background-image: linear-gradient(45deg,rgba(0,0,0,.25) 25%, transparent 0,transparent 75%, rgba(0,0,0,.25) 0),
linear-gradient(45deg,rgba(0,0,0,.25) 25%, transparent 0,transparent 75%, rgba(0,0,0,.25) 0);
background-position: 0 0, 15px 15px;
background-size: 30px 30px;
复制代码
background-position
来偏移第二个渐变,使用交差的方式,实现。
天然界中,由于没有规律而美,而平时咱们使用渐变老是能查到必定的规律,那如何增长随机性?
background-image:
linear-gradient(90deg, #fb3 11px, transparent 0),
linear-gradient(90deg, #ab4 23px, transparent 0),
linear-gradient(90deg, #655 41px, transparent 0);
background-size: 41px 100%, 61px 100%, 83px 100%;
复制代码
background-size
分别为
41
,
61
,
83
若是细心的同窗可能会注意到它们都为
质数
,由于咱们须要随机性更加真实,咱们得把贴片的尺寸最大化,
为了让最小公倍数最大化,这些数字最好是“相对质数” 平铺贴片的尺寸如今是 41×61×83=207 583 像素,比任何咱们所 能想像出的屏幕分辨率都要大!
请注意这个方法不只适用于背景,还能够用于其余涉及有规律重复的状况。
在照片图库中,为每幅图片应用细微的伪随机旋转效果时,可使用多个 :nth-child(a) 选择符,且让 a 是质数。
若是要生成一个动画,并且想让它看起来不是按照明显的规律在循环时,咱们能够应用多个时长为质数的动画。
有时咱们想把一幅图案或图片应用为边框,而不是背景。可能会有人说使用border-image
,它的原理基本上就是九宫格伸缩法:把图片切割成九块,而后把它们应用到 元素边框相应的边和角。可是咱们但愿出如今拐角出的图片区域是随着元素宽高和边框厚度的变化而变化的。用border-image
是不可能作到的。
在前面,咱们使用了不少的渐变背景,那咱们能不能使用渐变来解决这个难题?
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white) padding-box, // 注意点
repeating-linear-gradient(-45deg, red 0, red 12.5%,
transparent 0, transparent 25%,
#58a 0, #58a 37.5%,
transparent 0, transparent 50%) 0 / 5em 5em;
复制代码
background
第一个白色背景的
background-clip
是在
padding-box
上的,这样防止白色背景覆盖边框和第二个背景。
蚂蚁行军,当鼠标点击某个元素时,咱们能看到边框能"行走",这是如何实现的?
@keyframes ants { to { background-position: 100% } }
...
padding: 1em;
border: 1px solid transparent;
background:
linear-gradient(white, white) padding-box,
repeating-linear-gradient(-45deg,
black 0, black 25%, white 0, white 50%
) 0 / .6em .6em;
animation: ants 12s linear infinite;
复制代码
.voucher {
width: 150px;
height: 80px;
line-height: 5;
background: radial-gradient(circle at 100% 50%, transparent 9px, #fff 0) 0 0 / 100% 100% no-repeat;
filter: drop-shadow(3px 3px 2px rgba(0,0,0,.2));
}
复制代码
...
width: 0;
height: 0;
border-width: 0 25px 40px 25px;
border-style: solid;
border-color: transparent transparent rgb(245, 129, 127) transparent;
复制代码
这是利用什么原理实现?
盒子有
margin
、border
、padding
、content
,下左下右边框交界处出呈现平滑的斜线。咱们能够利用这个特色, 经过设置不一样的上下左右边框宽度或者颜色能够获得小三角等。
调整宽度大小能够调节三角形形状。
利用这个特色,咱们来看看其余的形状
height:20px;
width:20px;
border-color: red blue yellow orange;
border-style:solid;
border-width:20px;
复制代码
感兴趣的同窗,能够利用这个特色,去捣鼓其余的形状,这里就再也不举例啦。
场景:当咱们要实现一个根据内容区的大小,自动适应的椭圆。如:
当内容区宽高相等,则为圆形。
当内容区宽度大于高度,则为椭圆。
border-radius
能够帮咱们实现这一点,可是若是咱们使用px
单位的话,并不能达到咱们想要的效果。而它能够接受另外一个单位值,
%
百分比值。
border-radius
,有一个不为人知的真相:它能够单独指定水平和垂直半径,只要用一个斜杠( / )分隔这两个值便可。
<main class="wrapper">
<div class="voucher">我是一个形状</div>
</main>
.voucher {
border-radius: 50% / 50%;
padding: 10px;
background: orange;
}
复制代码
因为斜杠先后的两个值如今是一致的,因此能够简化为:
...
border-radius: 50%;
复制代码
到这里你们能发现,border-radius
实际上是一个简写属性,在水平方向上,它能够接受4
个值,垂直也是。这四个值分别从左上角开始以顺时针顺序应用到元素的拐角。说到这,咱们直接举两个例子来看看效果吧。
半椭圆
...
border-radius: 50% / 100% 100% 0 0;
background: orange;
复制代码
...
border-radius: 100% 0 0 / 100% 0 0;
复制代码
平时四边形形状,相信也是很经常使用的UI设计。而如何只用一个元素实现?可能咱们脑子立马会想到一个skew()
变形,这个想法是对的。可是,若是你不作一些处理的话,内容也会跟着倾斜。那如何使内容不变化呢?
.voucher {
position: relative;
padding: 10px;
z-index: 0;
}
.voucher::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
background: orange;
transform: skew(-45deg);
}
复制代码
菱形图片的制做,咱们大概能想出,使用两个元素,而后旋转剪切啥的来实现。而咱们是利用clip-path
来实现咱们的功能。
注意 cli-path
有兼容性问题,若是项目考虑到兼容低版本的,须要注意。
<main class="wrapper">
<img src="https://cdn.renqilai.com/2020_05_27/11_58_26.png" alt="我失败了">
</main>
img {
width: 100px;
height: 100px;
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
transition: 1s clip-path;
}
img:hover {
clip-path: polygon(0 0, 100% 0,100% 100%, 0 100%);
}
复制代码
咱们不只作出了棱形,顺带还让它动起来,使得不会那么枯燥。
clip-path
能够绘制各类各样的形状,不过绘制点比较麻烦,快捷绘制出形状点我。顺带的也给出一位牛人使用
clip-path
作出的各种好玩的东西点我。
(文章将持续中。。。)
亲,分享不易额,喜欢的话必定别忘了点💖!!!
只关注不点💖的都是耍流氓,只收藏也不点💖的也同样是耍流氓。