《CSS揭秘》 |形状

本章示例:https://codepen.io/sanhuamao1/pen/XWpPgeL?editors=1100

引入:border-radius

border-radius可以单独指定水平和垂直半径,只要用一个斜杠(/)分隔这两个值即可。这个特性允许我们在拐角处创建椭圆圆角:

border-radius: 100px / 75px;

cjW0u8.png

两组值会展开为四个值的:

border-radius: 10px / 5px 20px;
/*相当于*/
border-radius: 10px 10px 10px 10px / 5px 20px 5px 20px

1 自适应的椭圆

根据其内容自动调整并适应。如果它的宽高相等,就显示为一个圆;如果宽高不等,就显示为一个椭圆:

border-radius: 50%;

2 半椭圆

上半椭圆

border-radius: 50% / 100% 100% 0 0;

左半椭圆

border-radius: 100% 0 0 100% / 50%;

3 四分之一椭圆

其中一个角的水平和垂直半径值都需要是100%,而其他三个角都不能设为圆角:

border-radius: 100% 0 0 0;

border-radius优秀示例:https://simurai.com/archive/buttons/#flexibility

4 平行四边形

说到四边形,我们可能会想到用下面的办法创建:

transform: skewX(-45deg);

然而上面的写法会导致它的内容也发生了斜向变形。下面有几种方法让内容不倾斜:

方法一:嵌套元素

对内容再应用一次反向的 skew() 变形,从而抵消容器的变形效果:

<div class="example">
  <div>平行四边形</div>
</div>
.example{
  transform: skewX(-45deg);
}
.example>div{
  transform: skewX(45deg);
}

方法二:伪元素

另一种思路是把所有样式(背景、边框等)应用到伪元素上,然后再对伪元素进行变形。

给宿主元素应用 position: relative 样式,并为伪元素设置 position:
absolute,然后再把所有偏移量设置为零,以便让它在水平和垂直方向上都
被拉伸至宿主元素的尺寸。此时,用伪元素生成的方块是重叠在内容之上的,可设置z-index: -1 样式避免覆盖:

.example{
  position: relative;
}
.example::before{
 content: '';
 position: absolute;
 top: 0; right: 0; bottom: 0; left: 0;
 z-index: -1;
 background: orange;
 transform: skew(-45deg);
}

5 菱形图片

方法一:基本变形

cjWq81.png

<div class="example">
  <img src="https://z3.ax1x.com/2021/04/19/cTN9C8.jpg"/>
</div>
.example{
  width: 400px;
  transform: rotate(45deg); //容器旋转
  overflow: hidden;
}

.example > img {
  max-width: 100%;
  transform: rotate(-45deg) scale(2.2); //图片旋转 适当放大填补空白
}

方法二:截取路径

使用 clip-path 属性。它最大的缺陷在于其浏览器支持程度还很有限。这个例子使用 polygon()(多边形)函数来指定一个菱形,直接给image元素添加该样式即可:

clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);

这个属性甚至可以参与动画,只要我们的动画是在同一种形状函数(比如这里是 polygon())之间进行的,而且点的数量是相同的。下面的动画效果是,图片在鼠标悬停时平滑地
扩展为完整的面积:

.example{
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  transition: 1s clip-path;
}
.example:hover {
 clip-path: polygon(0 0, 100% 0,
 100% 100%, 0 100%);
}

clip-path属性文档:https://developer.mozilla.org/zh-CN/docs/Web/CSS/clip-path

6 切角效果

方法一:渐变

需要把一个透明色标放在切角处,然后在相同位置设置另一个色标,并且把它的颜色设置为我们想要的背景色:

background:linear-gradient(-45deg, transparent 15px, orange 0);

如果要设置两个切角呢?

background:
linear-gradient(-45deg, transparent 15px, orange 0),
linear-gradient(45deg, transparent 15px, orange 0);
/*上面的情况,这两层渐变会默认填满整个元素,因此它们会相互覆盖。

使用 background-size 让每层渐变分别只占据整个元素一半的面积:*/
background:
linear-gradient(-45deg, transparent 15px, #58a 0) right,
linear-gradient(45deg, transparent 15px, #655 0) left;
background-size: 50% 100%;
background-repeat: no-repeat;

四个切角

background:
linear-gradient(135deg, transparent 15px, orange 0) top left,
linear-gradient(-135deg, transparent 15px, orange 0) top right,
linear-gradient(-45deg, transparent 15px,orange 0) bottom right,
linear-gradient(45deg, transparent 15px, orange 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;

linear-gradient属性文档:https://developer.mozilla.org/zh-CN/docs/Web/CSS/linear-gradient()


弧形切角

与上方切角的区别是:这里是用径向渐变来替代上述线性渐变:

background:
 radial-gradient(circle at top left,transparent 15px, orange 0) top left,
 radial-gradient(circle at top right,transparent 15px, orange 0) top right,
 radial-gradient(circle at bottom right,transparent 15px, orange 0) bottom right,
 radial-gradient(circle at bottom left,transparent 15px, orange 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;

方法二:内联 SVG 与 border-image

通过渐变实现时,代码会比较冗长,且更改属性时需要更改多处。

border: 17px solid transparent;
border-image: 1 url('data:image/svg+xml,\
 <svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="orange">\
 <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
 </svg>');
  background:orange;
  background-clip: padding-box;
  • 使用的切片尺寸是 1,这并不表示 1 像素,它所对应的是SVG 文件的坐标系统(因此不需要单位)
  • fill关键词添加背景色,
  • 由于边框已设置成透明色,所以加上background-clip让背景不去绘制边框(border)

方法三:裁切路径

方法二有个局限:只能指定某个实色的背景或一个边缘接近某个实色的背景图案。如果我们想设置其他类型的背景呢(比如纹理、平铺图案或一道线性渐变)

background: orange;
clip-path: polygon(
20px 0, calc(100% - 20px) 0, 100% 20px,
100% calc(100% - 20px), calc(100% - 20px) 100%,
20px 100%, 0 calc(100% - 20px), 0 20px
);
  • 好处:可以使用任意类型的背景,甚至可以对替换元素(比如图片)进行裁切。
  • 坏处:如果要改动切角的尺寸,我们需要修改八处;当内边距不够宽时,它会裁切掉文本。

未来

CSS 背景与边框(第四版)(http://dev.w3.org/csswg/css-backgrounds-4/)将引入一个全新的属性 corner-shape,可以彻底解决这个痛点。这个属性需要跟 border-radius 配合使用,从而产生各种不同形状的切角效果,而切角的尺寸正是 border-radius 的值。举例来说,为容器的四个角指定 15px 的斜面切角就是如此简单:

border-radius: 15px;
corner-shape: bevel;

7 梯形标签页

通过3D旋转模拟

.example17{
  background: orange;
  transform:perspective(.5em) rotateX(2deg)
}

由于单纯给一个元素加上3D效果,文字也会出现扭曲。那么就通过加伪元素来解决:

.example17{
  position:relative;
  display:block;
}
.example17::before{
  content:"";
  position:absolute;
  top:0;right:0;bottom:0;left:0;
  z-index:-1;
  background: orange;
  transform:perspective(.5em) rotateX(2deg) scaleY(1.3);
  transform-origin:bottom;
}

变形是以它自身的中心线为轴进行旋转的,所以要加上transform-origin:bottom方便控制;而scaleY(1.3)可以伸长高度,保持它原有的高度。(示例中有圆角与倾斜的示例)

posted @ 2021-04-24 13:43  sanhuamao  阅读(102)  评论(0编辑  收藏  举报