supce's blog

CSS Secret 读书笔记之菱形图片&切角效果


菱形图片

有时候可能会遇到菱形图片的需求,可以用下面两种方式实现。

基于变形的方案

这种方式与之前平行四边形的解决方案类似,需要把图片用一个div包裹,然后div和img进行相反的变形。

<div class="diamond-a">
    <img src="cat.jpg">
</div>
.diamond-a{
    margin: 100px;
    width: 250px;
    height:250px;
    transform: rotate(45deg);
    overflow: hidden;
}
.diamond-a > img{
    max-width: 100%;
    transform: rotate(-45deg);
}


得到的结果是个八角形。原因就是max-width: 100%;会解析为外部容器的边长,如果图片的宽度与容器的菱形对角线长度相同,就会成为一个菱形。也就是设置宽度为外部容器边长的√2倍,即约为1.42倍。

.diamond-a > img{
    max-width: 100%;
    transform: rotate(-45deg) scale(1.42);
}

裁切路径方案

上面的方法首先破坏了原有的HTML结构,而且要求图片必须是正方形。
这里就可以用裁切的方法来实现。而且可以给图片添加动画,当鼠标悬停时,图片扩展为完整的面积。

<img class="diamond-b" src="cat.jpg" />
.diamond-b{
    width: 250px;
    -webkit-clip-path: polygon(50% 0,100% 50%,50% 100%,0 50%);
    clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
    transition: 1s;
}
.diamond-b:hover{
    -webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}


切角效果

之前的切角效果大多是使用背景图片来达到目的,比如使用三角形盖住元素的顶角来模拟切角效果(当网页背景是纯色时),或者使用一张或者多张已经切过角的图片来作为整个元素的背景。这些方法增加了额外的HTTP请求,而且也不够灵活,不易维护。
这时候可以根据场景用下面几种方式来实现。

渐变方案

在之前渐变已经帮助我们实现了好多特效比如条纹背景,复杂背景以及图像边框等。这次来帮助我们实现切角效果,后面也还有它大展神通的地方!
渐变方案很简单,把一个透明色放在切角处即可,以右下角为例:

<div class="rad-a">this is a test</div>
.rad-a{
    margin: 20px;
    max-width: 10em;
    min-height: 6em;
    font: 125%/6em sans-serif;
    text-align: center;
    color: white;
}
.rad-a{
    background: linear-gradient(-45deg,transparent 15px,#58a 15px);
}

假设需要裁剪底部两个角。最初的想法可能会是这样:

.rad-b{
    background: linear-gradient(-45deg,transparent 15px,#58a 15px),
                linear-gradient(45deg,transparent 15px,#fb3 15px);   
}

但会发现结果是这样的:

这是因为两层渐变互相覆盖的结果。
那可以对每层渐变进行位置和大小的修改来实现:

.rad-b{
    background: linear-gradient(-45deg,transparent 15px,#58a 15px) right,
                linear-gradient(45deg,transparent 15px,#fb3 15px) left;
    background-size: 50% 100%;
    background-repeat: no-repeat;
}

那么也可以做出切出四角的效果了:

.rad-c{
    background: linear-gradient(-45deg,transparent 15px,#58a 15px) bottom right,
                linear-gradient(45deg,transparent 15px,#58a 15px) bottom left,
                linear-gradient(135deg,transparent 15px,#58a 15px) top left,
                linear-gradient(-135deg,transparent 15px,#48a 15px) top right;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}

可以用SCSS预处理下,需要的时候直接调用

弧形切角

既然有了linear-gradient,那使用radial-gradient就可以创建出弧形切角

.rad-d{
    background: radial-gradient(circle at top left,transparent 15px,#58a 15px) top left,
                radial-gradient(circle at top right,transparent 15px,#58a 15px) top right,
                radial-gradient(circle at bottom left,transparent 15px,#58a 15px) bottom left,
                radial-gradient(circle at  bottom right,transparent 15px,#58a 15px) bottom right;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}

内联SVG与border-image方案

这个方式,是利用border-image的缩放,设置SVG为一个八角形,那么得出的效果就是我们需要的切角效果。

.rad-e{
    color: black;
    /*border:20px solid transparent;*/
    border:20px solid #58a;
    border-image: 1 url('data:image/svg+xml,\
                  <svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%2358a">\
                  <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2" />\
                  </svg>');
    /*background: #58a;*/
    background: radial-gradient(circle at center,hsla(0,0%,100%,.5),#58a);
    background-clip: padding-box;
}

注意,由于背景色会延伸到边框,所以一定要记着设置background-clip的值。为了平稳退化,防止浏览器不支持border-image,可以设置border的颜色与背景色相同

裁切路径方案

跟上面提到的菱形一样,也可以用裁切路径的方案

.rad-f{
    /*background: #58a;*/
    background: url(cat.jpg);
    background-size: 100% 100%;
    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);
    -webkit-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);
}

  • 使用这个方式的好处显而易见,就是可以使用任意类型的背景,就如上面的例子背景如果是图片也可以进行剪裁。而且想菱形那里设置hover动画效果等。
  • 但是,它有一个缺点,当内边距不够宽时,它会裁切掉文本。因为它只能对元素做出统一的裁切,并不能区分元素的部分。而在渐变方案中,允许字体溢出并超出切角区域(因为它只是背景图案),而border-image会起到普通边框的作用,使文字折行。

今天天津好冷