文章经过 Coco 授权转载
写本文的起因是,一天在群里有同学说误打误撞下,使用负的 outline - offset 实现了加号 。嗯?好奇的我马上也动手尝试了下,到底是如何使用负的 outline-offset 实现加号呢?
使用负值 outline-offset 实现加号
假设我们有这样一个简单的结构:
< div > </ div >
div {
width : 200px ; height : 200px ;
outline : 20px solid #000 ;
outline - offset : 10px ;
}
修改 outline - offset 到一个合适的负值 ,那么在恰当的时候,outline 边框就会向内缩进为一个加号。
经过一番尝试,修改上述 div 的 outline - offset 为 -118px。
div {
width : 200px ; height : 200px ;
outline : 20px solid #000 ;
outline - offset : - 118px ;
}
加个动画效果,大概是这样:
CodePen: https://codepen.io/Chokcoco/pen/PrrLaP
很有意思,我尝试了很多不同的情况,最后总结了一个简单的规律,要使用负的 outline-offset 生成一个加号有一些简单的限制:
在这个例子后,我又想,CSS 属性可以取负值的地方有很多。大家最为熟知的就是负margin ,使用负的 marign,可以用来实现类似多列等高布局、垂直居中等等。那还有没有其他一些有意思的负值使用技巧呢?
下文就再介绍一些 CSS 负值有意思的使用场景。
单侧投影
先说单侧投影,关于 box - shadow ,大部分时候,我们使用它都是用来生成一个两侧的投影,或者一个四侧的投影。如下:
OK,那如果要生成一个单侧的投影呢?
我们来看看 box-shadow 的用法定义:
{
box - shadow : none | [ inset ? && [ < offset - x > < offset - y > < blur - radius >? < spread - radius >? <color> ? ] ]#
}
以 box - shadow : 1px 2px 3px 4px #333 为例,4 个数值的含义分别是,x 方向偏移值、y 方向偏移值 、模糊半径、扩张半径。
这里有一个小技巧,扩张半径可以为负值 。
继续,如果阴影的模糊半径,与负的 扩张半径一致,那么我们将看不到任何阴影,因为生成的阴影将被包含在原来的元素之下,除非给它设定一个方向的偏移量。所以这个时候,我们给定一个方向的偏移值,即可实现单侧投影:
CodePen: https://codepen.io/Chokcoco/pen/pergRb
使用 scale(-1) 实现翻转
通常,我们要实现一个元素的 180° 翻转,我们会使用 transform : rotate ( 180deg ) ,这里有个小技巧,使用 transform : scale (- 1 ) 可以达到同样的效果。看个 Demo:
< p class = "scale" > CSS Nagative Scale(-1) </ p >
. scale {
transform : scale ( 1 );
animation : scale 10s infinite linear ;
}
@ keyframes scale {
50 % {
transform : scale (- 1 );
}
100 % {
transform : scale (- 1 );
}
}
看看效果:
(GIF 中第一行是使用了 transform : rotate ( 180deg ) 的效果 )
CodePen: https://codepen.io/Chokcoco/pen/VoQXVq
使用负 letter-spacing 倒序排列文字
与上面 scale(-1) 有异曲同工之妙的是负的 letter - spacing 。
letter - spacing 属性明确了文字的间距行为,通常而言,除了关键字 normal ,我们还可以指定一个大小,表示文字的间距。像这样:
< p class = "letter_spacing" > 倒序排列文字 </ p >
. letter_spacing {
font - size : 36px ;
letter - spacing : 0px ;
animation : move 10s infinite ;
}
@ keyframes move {
40 % {
letter - spacing : 36px ;
}
80 % {
letter - spacing : - 72px ;
}
100 % {
letter - spacing : - 72px ;
}
}
我们设置文字的 letter - spacing 从 0 -> 36px -> -72px,观察不同的变化:
CodePen: https://codepen.io/Chokcoco/pen/QeQXpW
然而,受到中英文混排或者不同字体的影响,以及倒序后的排列方式,不建议使用这种方式来倒序排列文字。
transition-delay 及 animation-delay 的负值使用,立刻开始动画
我们知道,CSS 动画及过渡提供了一个 delay 属性,可以延迟动画的进行。
考虑下面这个动画:
简单的代码大概是这样:
< div class = "g-container" >
< div class = "item" > </ div >
< div class = "item" > </ div >
< div class = "item" > </ div >
</ div >
. item {
transform : rotate ( 0 ) translate (- 80px , 0 ) ;
}
. item : nth - child ( 1 ) {
animation : rotate 3s infinite linear ;
}
. item : nth - child ( 2 ) {
animation : rotate 3s infinite 1s linear ;
}
. item : nth - child ( 3 ) {
animation : rotate 3s infinite 2s linear ;
}
@ keyframes rotate {
100 % {
transform : rotate ( 360deg ) translate (- 80px , 0 ) ;
}
}
如果,我们想去掉这个延迟,希望在一进入页面的时候,3 个球就是同时运动的。这个时候,只需要把正向的 animation-delay 改成负向的即可。
. item : nth - child ( 1 ) {
animation : rotate 3s infinite linear ;
}
. item : nth - child ( 2 ) {
animation : rotate 3s infinite - 1s linear ;
}
. item : nth - child ( 3 ) {
animation : rotate 3s infinite - 2s linear ;
}
这里,有个小技巧,被设置了 animation - dealy 为负值的动画会立刻执行,开始的位置是其动画阶段中的一个阶段 。所以,动画在一开始的时刻就是下面这样:
以上述动画为例,一个被定义执行 3s 的动画,如果 animation - delay 为 -1s,起点相当于正常执行时,第2s(3-1)时的位置。
CodePen: https://codepen.io/Chokcoco/pen/QeQXpW
负值 margin
负值 margin 在 CSS 中算是运用的比较多的,元素的外边距可以设置为负值。
在 flexbox 布局规范还没流行之前,实现多行等高布局还是需要下一番功夫的。其中一种方法便是使用正 padding 负 margin 相消的方法。
有如下一个布局:
左右两栏的内容都是不确定的,也就是高度未知。但是希望无论左侧内容较多还是右侧内容较多,两栏的高度始终保持一致。
OK,其中一种 Hack 办法便是使用一个很大的正 padding 和相同的负 margin 相消的方法填充左右两栏:
. g - left {
...
padding - bottom : 9999px ;
margin - bottom : - 9999px ;
}
. g - right {
...
padding - bottom : 9999px ;
margin - bottom : - 9999px ;
}
可以做到无论左右两栏高度如何变化,高度较低的那一栏都会随着另外一栏变化。
具体的代码可以看看这里:https://codepen.io/Chokcoco/pen/ZgrmVy
总结一下
另外,还有一些大家熟知的没有单独列出来的,譬如:
最后
欢迎关注「前端瓶子君」,回复「 交流 」加入前端交流群!
欢迎关注「前端瓶子君」,回复「 算法 」自动加入,从0到1构建完整的数据结构与算法体系!