自适应的椭圆
border-radius 属性的基本用法
难题
给任何正方形元素设置一个足够大的border-radius
,就可以把它变成一个圆形。所用到的 CSS 代码如下所示:
1 | background: #fb3; |
不过,我们往往不愿意对一个元素指定固定的宽度和高度,因为我们希望它能根据其内容自动调整并适应,进而控制圆:如果它的宽高相等,就显示为一个圆;如果宽高不等,就显示为一个椭圆。
解决方案
border-radius
,有一个鲜为人知的真相:
- 可以单独指定水平和垂直半径,只要用一个斜杠(/)分隔这两个值即可。
- 可以接受百分比值。这个百分比值会基于元素的尺寸进行解析,即宽度用于水平半径的解析,而高度用于垂直半径的解析。这意味着相同的百分比可能会计算出不同的水平和垂直半径。
1 | border-radius:50%/50%; |
//沿横轴劈开的半椭圆
border-radius:50%/100% 100% 0 0;
//沿纵轴劈开的半椭圆
border-radius:100% 0 0 100%/50%;
1 | ![](http://img.aisss.top/17-12-14/78618757.jpg) |
border-radius:100% 0 0 0;
1 | ![](http://img.aisss.top/17-12-14/76410207.jpg) |
1 | **注意** :只对非行内元素有效。 |
.button{
position:relative;
}
.button::before{
content:’’;
position:absolute;
top:0;right:0;bottom:0;left:0;
background:#58a;
tansform:skew(45deg);
z-inde:-1;
}
1 | 这个技巧的关键在于: |
1 | 它并没有一步到位地直接达到我们期望的效果,而是裁成一个八角形。 |
1 |
|
background:#58a;
background:linear-gradient(-45deg,transparent 15px,#58a 0);
1 | ![](http://img.aisss.top/17-12-15/87165453.jpg) |
background: #58a;
background:
linear-gradient(-45deg, transparent 15px, #655 0)
right,
linear-gradient(45deg, transparent 15px, #58a 0)
left;
background-size: 50% 100%;
background-repeat: no-repeat; //如果不关闭,每层渐变图案各自平铺了两次。这导致我们的两层渐变背景仍然是相互覆盖的
1 | ![](http://img.aisss.top/17-12-18/72570681.jpg) |
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 left,
linear-gradient(-45deg,transparent 15px,#58a 0) bottom right;
background-size:50% 50%;
background-repeat:no-repeat;
1 | ![](http://img.aisss.top/17-12-18/67549746.jpg) |
@minin beveled-corners($bg,$tl:0,$tr:$tl,$bl:$tl,$br:$tr){
background:$bg;
backgrounnd:
linear-gradient(135deg,transparent $tl,$bg 0) top left,
linear-gradient(225deg,transparent $tr,$bg 0) top right,
linear-gradient(45deg,transparent $bl,$bg 0) bottom left,
linear-gradient(-45deg transparent $br,$bg 0) bottom right;
background-size:50% 50%;
background-repeat:no-repeat;
}
//传入2~5 个参数调用
@include beveled-corners(#58a,15px,5px);
1 |
|
background:#58a;
background:
radial-gradient(circle at top left,transparent 15px,#58a 0) top left,
radial-gradient(circle at top right,transparent 15px,#58a 0) top right,
radial-gradient(circle at bottom left,transparent 15px,#58a 0) bottom left,
radial-gradient(circle at bottom right,transparent 15px,#58a 0) bottom right;
background-size:50% 50%;
background-repeat:no-repeat;
1 | ![](http://img.aisss.top/17-12-18/57969223.jpg) |
transform:perspective(.5em) rotateX(5deg);
1 | ![](http://img.aisss.top/17-12-18/84181656.jpg) |
.tab {
position: relative;
display: inline-block;
padding: .5em 1em .35em;
color: white;
}
.tab::before {
content: ‘’; /* 用伪元素来生成一个矩形 */
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
z-index: -1;
background: #58a;
transform: perspective(.5em) rotateX(5deg);
}
1 | ![](http://img.aisss.top/17-12-18/97165838.jpg) |
transform: scaleY(1.3) perspective(.5em)
rotateX(5deg);
transform-origin: bottom;
1 | ![](http://img.aisss.top/17-12-18/71829833.jpg) |
nav > a{
position:relative;
display:inline-block;
padding: .3em 1em 0;
}
nav > a::before{
content:’’;
position:absoltue;
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 rgba(0,0,0,.4);
border-bottom:none;
border-radius: .5em .5em 0 0;
border-shodaw: 0 .15em white inset;
transform:perspective(.5em) rotateX(5deg);
transform-origin:bottom;
}
1 | ![](http://img.aisss.top/17-12-18/53850367.jpg) |
.pie {
width: 100px; height: 100px;
border-radius: 50%;
background: yellowgreen;
background-image: linear-gradient(right,transparent 50%,#655 0);
}
1 | ![](http://img.aisss.top/17-12-19/83074108.jpg) |
.pie::before{
content:’’;
display:block;
margin-left:50%;
height:100%;
}
1 | ![](http://img.aisss.top/17-12-19/45613434.jpg) |
.pie::before{
content:’’;
display:block;
margin-left:50%;
height:100%;
background-color:inherit;
transform-origin:left;
border-radius:0 100% 100% 0/50%;
}
1 | ![](http://img.aisss.top/17-12-19/77845116.jpg) |
.pie::before{
content:’’;
display:block;
margin-left:50%;
height:100%;
background:#655;
transform-origin:left;
border-radius:0 100% 100% 0/50%;
transform:rotate(.1turn);
}
1 | ![](http://img.aisss.top/17-12-19/709242.jpg) |
@keyframes spin{
to {transform:rotate(.5turn);}
}
@keyframes bg{
50% {background:#655;}
}
.pie::before{
content:’’;
display:block;
margin-left:50%;
height:100%;
background-color:inherit;
transform-origin:left;
border-radius:0 100% 100% 0/50%;
animation:spin 3s linear infinite,
bg 6s step-end infinite;
}
1 |
|
1 | 首先,我们需要探索如何用内联样式来实现这个需求; |
@keyframes spin {
to { transform: rotate(.5turn); }
}
@keyframes bg {
50% { background: #655; }
}
.pie::before {
/* [其余的样式代码保持原样] */
animation: spin 50s linear infinite,
bg 100s step-end infinite;
animation-play-state: paused;
animation-deplay:inherit;
1 | 此时,我们就可以再次优化结构,把饼图的比率写到元素的内容中,就像我们最开始所期望的那样;然后我们通过一段简单的脚本来把`animation-delay`写到内联样式中 |
$$(.pie).forEach(function(pie){
var p=parseFloat(pie.textContent);
pie.style.animationDelay=’-‘+p+’s’;
});
1 | 我们还可以进一步优化,把比率文字放置在饼图的中心处,从而方便用户选中它。为了实现这一点,我们需要进行以下步骤: |
.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{
position:absolute;
top:0;left:50%;right:0;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-status:paused;
animation-deplay:inherit;
}
```