《css揭秘》学习笔记(二)

时间:2022-03-08 10:12:09
第三章形状
9、自适应的椭圆
圆形:给一个正方形设置一个大于边长长度一半的border-radius即可。
椭圆:
border-radius:50%;
半椭圆:
border-radius:100% 0 0 0;
四分之一椭圆:
border-radius:100% 0 0 0;
10、平行四边形
最简单的变形:形状和内容一起变形,不合要求(要求是形状变形,文字不变形)
transform:skewX(-45deg);
嵌套元素方案:使用一个嵌套的div,即两个div,在包含文字的div对其再变形一次,从而抵消容器的变形。
伪元素方案:把所有的样式应用到伪元素上,然后再对伪元素进行变形。
.button{
position: relative;
/*其他的文字颜色,内边距等样式*/
}
.button::before{/*在IE8中及较早版本中必须声明<!DOCTYPE>*/
content:'';
position:relative;
top:0; right: 0; bottom:0; left:0;
z-index: -1;
background:#58a;
transform:skew(45deg);
}

11、菱形图片
方法一:把图片用一个div包裹,然后对其应用相反的rotate()变形样式:
<div class="picture">
<img src="xxx.jpg" alt="..." />
</div>

.picture{
width:400px;
transform:rotate(45deg);
overflow:hidden;
}
.picture >img{
max-width:100%;
transform:rotate(-45deg) scale(1.42);/*图片的边长和容器对角线相等,scale默认是以它的中心点进行缩放,除非额外指定transform-origin样式*/
}

方法二:clip-path属性,从svg处借鉴

clip-path:polygon(50% 0, 100% 50%, 50% 100%, 0 50%);/*多边形函数,clip-path允许把元素剪裁成我们想要的任何形状*/

延伸:可以参与动画,只要我们的动画是在同一种形状函数之间进行的,而且点的数量是相同的。此外这个方法还可以很好地适应正方形的图片。

如果希望图片在鼠标悬停时平滑的扩展为完整的面积:

img{
clip-path: poly(50% 0, 100% 50%, 50% 100%, 0 50%);
transition:1s clip-path;
}
img:hover{
clip-path: poly(0 0, 100%0,100% 100%, 0100%);
}

12、切角效果

方案一:css渐变:只需要一个角被切掉,渐变可以接受一个角度(例如45deg)作为方向,而且色标的位置信息也可以是绝对的长度值,这一点丝毫不受容器尺寸的影响。

线性渐变:把一个透明色标放在切角处,在相同位置设置另一个色标,并且把他的颜色设置为我们想要的背景色。

background:#58a;
background:linear-gradient(-45deg, transparent 15px, #58a 0);

假设两个切角,需要两层渐变:

background:#58a;
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:#58a;
background:linear-gradient(135deg, transparent 15px, #58a 0) top left;
linear-gradient(-135deg, transparent 15px, #58a 0) top right ;
linear-gradient(-45deg, transparent 15px, #58a 0) bottom right;
linear-gradient(45deg, transparent 15px, #58a 0)bottom left ;
background-size: 50% 50%;
background-repeat: no-repeat;

如果用scss写:略

弧形切角----------内凹圆角

background:#58a;
background:radial-gradient(135deg, transparent 15px, #58a 0) top left;/*径向渐变*/
radial-gradient(-135deg, transparent 15px, #58a 0) top right ;
radial-gradient(-45deg, transparent 15px, #58a 0) bottom right;
radial-gradient(45deg, transparent 15px, #58a 0)bottom left ;
background-size: 50% 50%;
background-repeat: no-repeat;

内联svg与border-image方案

border: 15px solid transparent;
border-image: 1 url('data: image/svg+xml,\ /*1表示svg的坐标系统*/
<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-clip: padding-box;

裁切路径方案

background: #58a;
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
);

 最大的缺点在于:当内边距不够宽时,它会裁切掉文本,渐变方案允许文字溢出并超出切角区域;而border-image方案则会起到普通边框的作用,令文字折行。

13、梯形标签页

根据透视原理,在三维图形中旋转一个矩形,看到的图形就是梯形

transform: perspective(.5em) rotate(5deg);

但这样产生的文字也变形了,对元素使用了3D变形之后,其内部的变形效应是“不可逆转的”。如果使用3D变形的功能生成梯形,唯一可行的方案是将变形效果应用在为元素上,类似于生成平行四边形的方法。

.tab{
position: relative;
display: inline-block;
padding: .5rem 1rem .35rem;
color:white;
}
.table:before{
content:'';/*用伪元素生成一个矩形*/
position:absolute;
top:0;right:0;bottom:0;left:0;
z-index:-1;
background:#58a;
transform:perspective().5rem rotate(5deg);
}

由于以上虽然可以实现,但是元素投射到2D屏幕上的尺寸会发生很多变化:宽度增加、位置稍稍下移、高度稍许缩减等。

必须指定transform-origin:bottom;当它在3D空间中旋转时,可以把他的底边固定住。通过变形属性来改变尺寸。

transform:scaleY(1.3) perspective(.5rem) rotate(5deg);
transform-origin:bottom;

标签页的例子:

nav > a{
position: relative;
display: inline-block;
padding: .3rem 1rem 0;
}
nav > a{
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
z-index: -1;
background: #ccc;
background-image: linear-gradient(hsla(0, 0%,100%,.6)
hsla(0, 0%,100%,0));
border: 1px solid rgb(0, 0, 0, .4);
border-bottom: none;
border-radius: .5rem .5rem 0 0;
box-shadow: 0 .15rem white inset;
transform:perspective().5rem rotate(5deg);
transform-origin: bottom;
}

缺点:斜边的角度依赖与元素的宽度。

14、简单的饼图

炫酷的进度指示器:

@keyframes spin{
to {transform: rotate(.5turn);}
}
@keyframes bg{
50% { background: #655;}
}
.pie::before{
content: '';
display: block;
margin-left: 50%;
height: 100%;
border-radius: 0 100% 100% 0 / 50%;
background-color: inherit;
transform-origin: left;
animation: spin 3s linear infinite,
bg 6s step-end infinite;
}

多个不同比率的静态饼图:

<div class="pie" style="animation-delay: -20s"></div>
<div class="pie" style="animation-delay: -60s"></div>

@keyframes spin{
to {transform: rotate(.5turn);}
}
@keyframes bg{
50% { background: #655;}
}
.pie::before{
content: '';
display: block;
margin-left: 50%;
height: 100%;
border-radius: 0 100% 100% 0 / 50%;
background-color: inherit;
transform-origin: left;
animation: spin 50s linear infinite,
bg 100s step-end infinite;
animation-play-state: paused;
animation-delay: inherit;
}

把饼图的比率写到元素的内容中:

$$('.pie').foreach(function(pie){
var p = parseInt(pie.textContent);
pie.style.animationDelay = '-' + p + 's';
});

最终代码:

.pie{
position: relative;
width: 100px;
line-height: 100px;
border-radius:50%;
background: yellowgreen;
background-image: linear-gradient(to right, transparent 50%, #655 0);
color: transparent;
text-align: center;
}
@keyframes spin{
to {transform: rotate(.5turn);}
}
@keyframes bg{
50% { background: #655;}
}
.pie::before{
content: '';
display: block;
margin-left: 50%;
height: 100%;
border-radius: 0 100% 100% 0 / 50%;
background-color: inherit;
transform-origin: left;
animation: spin 50s linear infinite,
bg 100s step-end infinite;
animation-play-state: paused;
animation-delay: inherit;
}

svg解决方案:

<svg width="100" height="100">
<circle r="30" cx="50" cy="50"/>
</svg>
circle{
fill:yellowgreen;
stroke: #655;
stroke-width: 50;
stroke-dasharray: 60 158;/*为虚线描边准备*/
}
svg{
transform: rotate(-90deg);
background: yellowgreen;
border-radius: 50%;
}

优化后代码:

<svg viewbox="0 0 32 32">
<circle r="16" cx="16" cy="16"/>
</svg>
circle{
fill:yellowgreen;
stroke: #655;
stroke-width: 32;
stroke-dasharray: 38 100;
}


svg{
width: 100;height: 100;
transform: rotate(-90deg);
background: yellowgreen;
border-radius: 50%;
}
用js脚本实现css:略。