css绘制多种形状

CSS上古时代连圆形都要靠切图,到了CSS3之后,我们已经可以使用各种方法绘制不同的形状了

圆形

通常我们都是依靠设置宽高相同的盒,再设置border-radius为50%来绘制圆形

.circle {
  width: 100px;
  height: 100px;
  border-radius: 50%;
}

现在,我们也可以用强大的clip-path的circle方法来绘制,circle( [<shape-radius>]? [at <position>] ),其中shape-radius是半径,当使用百分比半径的时候将会以sqrt(width^2+height^2)/sqrt(2)为100%来计算,position定义了圆心到盒上边与左边的距离,默认值为盒中心。

.circle {
  width: 100px;
  height: 100px;
  /* 所有参数示例 */
  clip-path: circle(40px at 50px 40px);
  /* 实现同border-radius一致效果的示例 */
  clip-path: circle();
}

椭圆形

clip-path绘制椭圆形,ellipse( [<shape-radius>{2}]? [at <position>] ),shape-radius为椭圆形x轴与y轴半径,默认为100%,position是椭圆中心点,默认为盒中心点。

.ellipse {
  width: 100px;
  height: 50px;
  clip-path: ellipse(50% 30% at 50% 35%);
}

三角形

使用border属性,我们可以绘制出三角形,与梯形,这种方法的缺点是只绘出了形状,并没有改变盒模型的边界

.triangle {
  width: 100px;
  height: 100px;
  /* 未设置顶部边框则宽为0,左右两侧边框宽度为div宽度的一半,透明色,底边框高度为div高度,使用背景色,三个边框形成的区域就是三角形 */
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid orange;
}
.trapezoid {
  width: 100%;
  height: 100px;
  /* 减小两侧边框宽度,使之形成梯形 */
  border-left: 30px solid transparent;
  border-right: 30px solid transparent;
  border-bottom: 100px solid orange;
}

平行四边形

绘制平行四边形,我们第一个想到的方法就是使用transform的skew,但是skew有一个很大的缺点就是连盒内部的文字也变形了,如何解决文字变形的问题呢?我们可以使用CSS的伪元素,在伪元素上使用skew变形,而不改变元素本身。

skew( ax [, ay] ),ax与ay是角的大小,ax指x轴(纵轴,不同与平面直接直角坐标系的x轴)在逆时针方向上扭曲的程度,ay指y轴在顺时针方向上扭曲的程度。角的大小可以用度deg,百分度grad,弧度rad,圈数turn来表示。

/* 设置z-index为1,防止伪元素遮挡 */
.parallelogram {
  width: 150px;
  height: 36px;
  position: relative;
  cursor: pointer;
  font-size: 20px;
  color: #fff;
  line-height: 36px;
  z-index: 1;
}
.parallelogram::before {
  /* 设置z-index为-1,不遮挡未设置z-index的元素 */
  content: "";
  width: 150px;
  height: 36px;
  position: absolute;
  top: 0;
  left: 0;
  background: #00699f;
  transform: skew(-45deg);
  z-index: -1;
}

梯形

梯形用到了透视与3D变换的x轴旋转,若是要得到一个直角梯形,则还要改变变换原点的属性。

一些变换的基础知识

scale( sx [, sy] ) 缩放函数,sx表示缩放向量横坐标,sy表示缩放向量纵坐标,若未设置sy,则默认值为sx,使得元素保持原有形状均等缩放。

perspective(length) 观察者与z=0平面的距离,用以产生透视效果,默认值为none。

rotateX(a) 绕x轴顺时针旋转大小,可以是角度、弧度、百分度、圈数。

transform-origin 变换原点,可以是一个值、两个值或三个值,第一个值代表水平偏移量,第二个值表示垂直偏移量

  • 一个值:
    • 必须是长度、百分比或left,center,right,top,bottom关键字中的一个。
  • 两个值:
    • 其中一个必须是长度,百分比或left,center,right关键字中的一个。
    • 另一个必须是长度,百分比或top,center,bottom关键字中的一个。
  • 三个值:
    • 前两个值同只有两个值的用法。
    • 第三个值必须是长度。它始终代表Z轴偏移量。

梯形与直角梯形

.trapezoid {
  width: 170px;
  height: 36px;
  position: relative;
  cursor: pointer;
  font-size: 20px;
  color: #fff;
  line-height: 36px;
  z-index: 1;
}
.trapezoid::before {
  content: "";
  width: 170px;
  height: 36px;
  position: absolute;
  top: 0;
  left: 0;
  background: #00699f;
  /* 通过沿x轴旋转并改变观察点与z平面距离形成梯形,通过缩放使变换后的梯形达到原来的高度 */
  transform: scale(1.1 1.79) perspective(100px) rotateX(45deg);
  /* 通过改变变换原点为右下方,使梯形成为直角梯形 */
  transform-origin: bottom right;
  z-index: -1;
}

多边形

使用clip-path属性的polygon方法,可以更容易地画出三角形,四边形等,任意多边形形状。

polygon( [<fill-rule>,]? [<shape-arg> <shage-arg>]# )

fill-rule决定了多边形内部的填充方式,可选值为nonzero和evenodd,默认为nonzero,后面的每对参数表示多边形以盒模型左上角顶点为原点的顶点坐标 x y。

.polygon {
  width: 100px;
  height: 100px;
  /* 三角形 */
  clip-path: polygon(nonzero, 50% 0, 0 100%, 100% 100%);
  /* 平行四边形 */
  clip-path: polygon(nonzero, 50% 0, 0 100%, 50% 100%, 100% 0);
  /* 梯形 */
  clip-path: polygon(nonzero, 20% 0, 0 100%, 100% 100%, 80% 0);
}

clip-path属性虽然很方便,但是兼容性不好,大家可以根据不同的需求选择不同的方法。

参考连接
MDN basic shape
MDN perspective
MDN scale()
MDN rotateX()
MDN transform-origin
张鑫旭-CSS实现平行四边形布局效果
使用CSS写出三角形、圆形、平行四边形、梯形
dabblet
不可思议的CSS之clip-path
张鑫旭-好吧,CSS3 3D transform变换,不过如此!