title: 形状
date: 2016-10-24
tags: CSS Secrets
0x00 border-radius
border-radius
有一个鲜为人知的属性,它可以单独指定水平和垂直半径,只要用斜杠(/) 分隔这两个值即可。此外,它不仅可以接受数值单位,还可以接受百分比值。而这个百分比会基于元素的尺寸进行解析。
所以,要创建一个自适应的椭圆,只需将两个方向(水平和垂直)的半径都设置为 50%
#box{
width:400px;
height:200px; border-radius: 50% / 50%;
}
// or 进一步简化
border-radius: 50%;
大值特性和等比例特性
此外,border-radius
还有两个特性:大值特性 和等比例特性
大值特性
也就是值很大的时候,只会使用能够渲染的圆角大小渲染。大值特性相对于元素自身的 width ,height而言。
#box {
width: 200px;
height: 200px;
background: deeppink;
border-radius: 50%;
/*border-radius:100%*/
/*border-radius: 100px*/
/*border-radius:200px;*/
/*border-radius: 400px*/
}
如下,上面的渲染结果都是一样的,即最大渲染半径只能是 50%,100px;
等比例特性
等比例特性:水平半径和垂直半径的比例是恒定不变的。等比例特性相对设置的 border-radius
参数的比例而言的
#box {
width: 200px;
height: 300px;
background: deeppink;
border-radius: 300px 0 0 0/300px 0 0 0;
}
元素占据宽度200像素,高度300像素。所以,根据大值特性,水平方向的300像素只能按照200像素半径渲染;再根据等比例特性,虽然垂直方向理论上的最大半径是300像素,但是受制于当初设定的300px300px的1:1比例,垂直方向最终渲染的半径大小也是200像素。于是,我们最后得到的只是一个200像素200像素的圆弧。
最后值得注意的是,
border-radius
属性中前面的方位关键字和后面的半径方位是不匹配.它们的关系是:border-垂直-水平-radius: 水平 垂直
OK,了解上面的东西以后我们可以开始使用 border-radius
来实现许多形状了,比如:
半椭圆
#box {
width: 200px;
height: 300px;
background: deeppink;
border-radius: 50% / 100% 100% 0 0 ;
}
四分之一椭圆
#box {
width: 200px;
height: 300px;
background: deeppink;
border-radius: 100% 0 0 0;
}
0x01 平行四边形
我们很容易想到对矩形使用 skew()
变形属性来达到我们想要的效果,但是,这样势必导致其元素中的内容也会跟着被拉伸,于是,我们想到使用伪元素。
#box {
width: 100px;
height: 40px;
margin: 100px auto;
margin-left:400px;
text-align: center;
line-height: 40px;
/*其它文字,颜色,内边距等样式...*/
position: relative;
/*设置宿主元素为相对定位*/
}
#box:before {
/*使用伪元素来生成一个矩形*/
content: '';
position: absolute;
/*设置伪元素为绝对定位*/
left:0;
top:0;
right:0;
bottom: 0;
/*设置伪元素所有偏移量为0,使其自动继承宿主元素尺寸*/
z-index: -1;
/*将伪元素堆叠层次至于宿主元素之后*/
background: deeppink;
transform:skewX(45deg);
/*使用skewX()变形*/
border:1px solid red;
}
这技巧的关键在于,利用伪元素及其定位属性产生了一个方块,然后对伪元素设置样式,并将其放置在宿主元素的下层。
0x02 菱形
.picture{
width: 200px;
height: 200px;
transform: rotate(45deg);
margin: 200px auto;
overflow: hidden;
}
.picture>img{
height: 100%;
max-width: 100%;
transform: rotate(-45deg) scale(1.42);
/*正方形的斜边使其对角线的1.42倍*/
}
是的,我们很容易想到使用 transform:rotate()
属性来对容器进行旋转,然后对其中的图片进行逆向旋转,但是我们可能不太容易想到使用 skew()
属性对其进行缩放。
其实,道理也蛮简单,当使用 max-width
时,100% 会被解析为容器的边长,但是我们想要的的是图片的宽度与容器的对角线相等,而不是边长,并且 skew()
是以元素本身的中心点进行缩放的,而 width
则只会以其左上角为原点进行缩放。基于此,我们使用 勾股定理结合skew实现了一个菱形的效果。
0x02 梯形
梯形可以使用 CSS 中3D旋转来模拟。但不同于 2D 对元素使用 3D 变形以后,其内部的变形效应是不可逆转的。所以,我们有想到了伪元素。
.tab{
position: relative;
display: inline-block;
padding: .5em 1em .35em;
color: white;
}
.tab:before{
content: "";
/*用伪元素来生成一个矩形*/
position:absolute;
left:0; right:0; top:0; bottom: 0;
z-index: -1;
background: #58a;
transform-origin: bottom;
/*使用 transform-origin 属性当在 3D 空间旋转时 将其底边固定住*/
transform: scaleY(1.3) perspective(.5em) rotateX(5deg);
/*使用 scaleY() 属性在 Y 轴上扩展以此抵消因为 3D 旋转在元素垂直方向上的高度落差*/
}
我们很好的模拟出来一个梯形,而且只需改变 transform-origin
的值为 left
,right
就可以得到左倾斜或者右倾斜的梯形标签页了。
.nav{
font-size: 0;
margin: 0 auto;
}
.nav>a{
position: relative;
display: inline-block;
padding: .5rem 1rem 0;
color: white;
font-size: 1rem;
}
.nav>a:before{
content: "";
/*用伪元素来生成一个矩形*/
position:absolute;
left:0; right:0; top:0; bottom: 0;
z-index: -1;
background: #333;
background-image: linear-gradient(hsla(0,0%,100%,.06) hsla(0,0%,100%,0))
border:1px solid rgba(0,0,0,0.4);
border-bottom: none;
border-radius: .5em .5em 0 0;
box-shadow: 0 .15em white inset;
transform-origin: left;
/*使用 transform-origin 属性当在 3D 空间旋转时 将其底边固定住*/
transform: scaleY(1.3) perspective(.5em) rotateX(5deg);
/*使用 scaleY() 属性在 Y 轴上扩展以此抵消因为 3D 旋转在元素垂直方向上的高度落差*/
}