秋月何时了,CSS3 border-radius知多少?

这篇文章发布于 2015年11月1日,星期日,22:14,归类于 CSS相关。 阅读 96378 次, 今日 1 次 34 条评论

 

补充于2020-04-04

5年后再回首,发现当年写的这篇文章可真是shit,文中有非常多的理解错误的地方,例如border-radius半径设置很大时候的渲染机制,这篇文章直接就在瞎几把扯淡,大家忽略之。

——–

今天10月末,过了今天,秋天也算是走到头了,但是,对于前端的学习,路还漫长,今天就说说CSS3 border-radius更深入的一些tips. 本文属于进阶知识点,所以,下面内容不会啰嗦一些基础知识,适合有一定是要经验的小伙伴。

一、border-radius私有前缀拜拜

还有个把月就2016年了,00后都已经登上历史舞台了,大家都懂我说的意思,浏览器个把年前就把私有前缀给去掉了,现在完全没必要还傻傻使用-webkit-border-radius, -moz-border-radius,至少我是早就不使用了,你随意~

二、border-radius百分比值

border-radius支持百分比值,例如border-radius:50%. 如果大家看早些年CSS3 border-radius的文档或者文章,会发现,根本就没有提过百分比值这一茬。究其原因,是因为百分比值的支持是后来才支持的,跟数值不是一起出来的。比方说某些老版本的Android机子,border-radius:50%它就不认识。

不过,事情已经过去很多年了,现在大家可以不用在意这些细节了。

OK,大家都知道这个百分比是相对单位,但是,不同属性的百分比值相对的内容是不一样的,对吧,比方说translate是自身,width/height是父级,background-position需要尺寸差计算等。那这里border-radius的百分比值相对的属性是?

我们炒个板栗知道了:

.radius-test1 { width: 100px; height: 100px; border: 50px solid #cd0000; border-radius: 50%; }
<div class="radius-test1></div>

哦哦哦哦,我知道了,是相对于元素占据尺寸的百分比(类似jQuery outerWidth()/outerHeight()方法代表尺寸),也就是包含边框,padding后的尺寸。而不是单纯地相对于width/height值。

于是乎,我们要实现一个正方形元素的圆角效果(例如网站头像),一个50%就可以搞定,而无需去计算。

万圣节-扮鬼

border-radius还有一个大值特性,也就是值很大的时候,只会使用能够渲染的圆角大小渲染。因此,要实现一个正方形元素的圆角效果(例如网站头像),我们还可以使用一个很大的圆角值,同样是不需要计算的。例如,下面240*240像素图片,我设置圆角大小300px,跟上面效果一样。
万圣节-扮鬼

咦?貌似大数值border-radius值好像和50%没什么区别啊?因为上面的图片是正方形,实际上两者区别不小,我们把上面红圈圈例子的height改成200px看看两者对应效果:

.radius-test2 { width: 100px; height: 200px; border: 50px solid #cd0000; border-radius: 50%; }
.radius-test3 { width: 100px; height: 200px; border: 50px solid #cd0000; border-radius: 300px; }
<div class="radius-test2></div>
<div class="radius-test3></div>

此时,差别就很明显了。上面的长得像马桶盖子, 而后面长得像操场跑道。

疑问

为什么呢?50%成为“马桶盖子”还好理解,宽度和高度分别50%圆角化;但是后面明明圆角300像素,比占据高度需要的圆角大小值要高出不少,为什么还是直的呢?哈哈,实际上就是因为太大了,所以才会变成的“操场跑道”。

没错,因为值大了,要弄清此问题,有必要深入下。不行了,上年纪了,困了,去洗澡睡觉了明天继续。

三、border-radius单值表现深入

由于我们平时使用border-radius绝大多数情况是都单值,例如border-radius: 300px,于是,久而久之可那会忽略这样一个事实,那就是border-radius单值实际上是一种简写。就跟padding:300px, border-width:300px是一样的,是各个方位等值时候的一种简化书写形式。但是,和一般的可简写CSS属性相比,border-radius要比看上去的复杂的多,表面上是琅琊山伯爵,实际上是当年大梁的贵族少年。

我们将border-radius: 300px还原成其整容前的模样,结果是:

border-radius: 300px 300px 300px 300px/300px 300px 300px 300px;

我勒个擦,一副把七大姑八大婆都跳出来的即视感,这么这个多~~

长得好像一样

虽然看上去都是300px, 长得好像一样,实际上,表示的含义各不相同,翻译成普通话就是:

border-radius: 左上角水平圆角半径大小 右上角水平圆角半径大小 右下角水平圆角半径大小 左下角水平圆角半径大小/左上角垂直圆角半径大小 右上角垂直圆角半径大小 右下角垂直圆角半径大小 左下角垂直圆角半径大小;

也就是斜杠前的是水平方向,斜杠后面的是垂直方向。

虽然border-radiusborder-width/border-color等都是border打头的,但是,两者缩写与方位的表示确实不一样的。传统的边框属性border四个值分别表示上边框,右边框,下边框,左边框。但是,border-radius指的则是角落,所以,我们眼睛的关注点,需要移动下,从边框到角落(如下图所示)(每个方位都如此逆时针移动)。

实现的转移

都是最多4个值,1~3个缩写的规则也是一样的(一个是边,一个是角),不赘述。

那上面提到的“水平/垂直”又是什么鬼呢?

对于正圆,我们基本上很少提“水平半径”和“垂直半径”,因为,半径都是一样长。但是,对于标准椭圆,那就不一样了,因为存在最长半径和最小半径。在web中,圆角的水平半径指的就是椭圆的水平半径,垂直半径就是椭圆下图所示的垂直半径:
椭圆垂直水平半径示意

一个水平半径和一个垂直半径所夹起的那1/4段圆弧就是我们平时看的的圆角呈现,如下变色显示:

高亮的圆弧显示

demo
一例胜千图,为了方便大家感受下八大婆的具体行为,我特意紧承上面的例子,制作了个可操作的实时圆角和代码的例子。

您可以狠狠地点击这里:CSS3 border-radius圆角各个属性值作用demo

demo各个区域作用图解

OK, 为了演示水平垂直半径,我们现在先重置0,然后让水平1和垂直1都是300像素,如下图所示:
左上角均是300像素的效果

大家会看到,左上角出现了圆弧,那这个圆弧是怎么来的呢?我们画个圈圈辅助下~

圆弧大小

前方高能

大家发现没,原本设置的是300像素*300像素,结果最后显示的却是200像素*200像素半径下的圆弧效果,这显然不符合认知啊!!

实际上是这样的,CSS3圆角除了大值特性,还有一个等比例特性,就是水平半径和垂直半径的比例是恒定不变的。

回到上面例子,由于我们的元素占据宽度200像素,高度300像素。所以,根据大值特性,水平方向的300像素只能按照200像素半径渲染;再根据等比例特性,虽然垂直方向理论上的最大半径是300像素,但是受制于当初设定的300px*300px1:1比例,垂直方向最终渲染的半径大小也是200像素。于是,我们最后得到的只是一个200像素*200像素的圆弧。

第三节末尾所提到的“反而因为值设大了”就是指的这个。

可能有人会疑问,那该如何设置才能实现等同于border-radius:50%的效果呢。哈哈,如果你理解了上面的内容,其实就很简单了,最关键的一点就是比例关系。我们的元素占据的尺寸是200像素*300像素。所以,只要让水平半径和垂直半径保持2:3的比例就可以了,然后,可以利用“大值特性”设一个你认为安全的值就可以了。

比方说2倍尺寸border-radius: 400px/600px, 如下代码和效果:

.radius-test4 { width: 100px; height: 200px; border: 50px solid #cd0000; border-radius: 400px/600px; }
<div class="radius-test4></div>

是不是搞明白原理之后,之前晕头转向的表现是不是分分钟就理解了哈!

四、border-radius与图形构建

border-radius支持的可变值足有八个(在本文戏称为八大婆,简称八婆),基本上,每一个值的变化,都会呈现不同的图形,例如,下面这样,我东拖拖,西拖拖,拖出了个英文字母D:

圆角生成的字母D

或者我们可以只留一个方向或2侧的边框,可以拉出一些惊喜的效果,如下gif截图:
一侧边框的小尾巴效果gif截图

诸如很多的,就看你的脑洞和技术了。

本身CSS的border属性就可以构建三角,梯形等等,现在,再配合多变的border-radius,我们可以发挥的空间就更大了。但是,要想用得得心应手,还是需要深入理解border-radius的各个表现。

a.singlediv.com上就有些图标就是利用了border-radius实现的,大家有兴趣可以瞅瞅,看看人家怎么巧妙使用border-radius的,目的在于学习理解border-radius,倒不是效果本身。知其根本自然上层信手拈来。

border-radius与不规则头像案例

之前在“蝉原则”这篇文章中有介绍过border-radius实现不规则头像。

您可以狠狠地点击这里:随机不规则圆角头像demo

效果如下截图:

demo随机圆角截图示意

我们还可以内外角同时设置不同的百分比圆角,实现更加不规则的圆角效果,下面是一些案例截图:

更多不规则圆角示意

下面展示一个实际案例,配合CSS3动画,展示更多不规则圆角的可能性。

相关代码如下,CSS:

.spin-container {
  width: 200px; height: 200px;
  animation: spin 12s linear infinite;
  margin: auto;
}
.shape {
  height: 100%;
  border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
  animation: morph 8s ease-in-out infinite both alternate;
  overflow: hidden;
}
.avatar {
  height: 120%; width: 120%;
  margin: -10% 0 0 -10%;
  background: url(./avatar.jpg) no-repeat center;
  background-size: 100%;
  animation: spin 12s linear infinite reverse;
}
@keyframes morph {
  0% {border-radius: 40% 60% 60% 40% / 60% 30% 70% 40%;} 
  100% {border-radius: 40% 60%;} 
}
@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

HTML结构为:

<div class="spin-container">
  <div class="shape">
    <div class="avatar"></div>
  </div>
</div>

六、补充内容

插一下
对了,写摘要是突然想起来。有时候我们想使用透明边框优雅增加元素的点击区域,此时的圆角大小值需要把透明边框的宽度也计算在内。例如,希望圆角2像素,结果外面扩展了2像素的透明边框;此时,实际设置的border-radius值应该是4px.

插一下 × 2
哦,还有……妹的,忘记说了,本来是个独立段落,算了,简单说下吧。就是我们可以单独指定border-radius某个角落的圆角大小,如border-top-left-radius: 40px这个不少同学都知道。但是,大家不一定知道:

  1. 支持最多两个值,必须使用空格分隔。分别表示水平半径和垂直半径。而border-radius那种斜杠/分隔的写法这里是不支持的,只能是空格。
  2. 中间两个方位关键字,如top/left的前后顺序不能改变,否则会被认为是不合法(可参见下面的测试)。top/bottom表示垂直方向的在前面, left/right表示水平方向的在右边。全部写法示意:
    .radius {
      border-top-left-radius: 200px 100px;
      border-top-right-radius: 200px 100px;
      border-bottom-left-radius: 200px 100px;
      border-bottom-right-radius: 200px 100px;
    }

上面2点一综合,就可以得到如下的记忆公式:border-垂直-水平-radius: 水平 垂直

没错!前面的方位关键字和后面的半径方位不匹配!不匹配!不匹配!正好反的!

另外,偶们都不是天才,时间久了会记不得到底是垂直在前,还是水平在前。告诉大家一个一定不会记错的方法,罗永浩不是有个锤子手机吗?

锤子手机

垂直在前 → 锤子在前。

OK,下面我们来测试下前面提到的不能修改方位关键字的顺序,也就是不能border-left-top-radius

.radius-test5 { width: 100px; height: 100px; border: 50px solid #cd0000; border-top-left-radius: 200px 100px; }
.radius-test6 { width: 100px; height: 100px; border: 50px solid #cd0000; border-left-top-radius: 200px 100px; }
<div class="radius-test5></div>
<div class="radius-test6></div>

显然,上面还是方方正正,直接嗝屁了。所以,记住,「锤子在前」!

七、秋月何时了

这两个月产出有点少,为什么呢?大家都学过「产出守恒定律」,文章产少了,是因为产了其他很屌的东西:
大哥-屌

早就知道女朋友是技术学习的第一阻碍力,现在发现小朋友才是技术学习的Boss级阻碍力。

对了,今天是万圣节,我有必要扮鬼让大家开心一下:
万圣节-扮鬼

告诉大家一个秘密,我每天早上就是这么帅醒的。

不过在我们国家,万圣节显得冷冷清清凄凄惨惨戚戚,但是,第11区的人民就热闹多了:
11区的万圣节

不知道大家的万圣节是怎么过的,尤其今年恰逢周末。想想我年轻的时候,这样的节日不是加班,就是宅在家里。如果你也是这样,别桑心,没人给你扮鬼,咱们可以自己扮鬼开心下嘛。比如说:单身鬼,穷鬼等等。哟,你突然发现自己……根本就不用扮,直接本色出演就可以了!那……真是太恭喜你了,原来你每天都在过万圣节! 那更应该开心啦!

(本篇完)

分享到:


发表评论(目前34 条评论)

  1. 浪迹理工说道:

    audios标签的border-radius设置无效,不知道咋回事

  2. 阿强说道:

    ,上面少了个”

  3. 阳光Angel说道:

    border-radius里面这样的表达方式还是没太理解,截取的圆角吗? border-radius: 37% 37% 34% 34%/70% 70% 33% 33%;

  4. 阳光Angel说道:

    写的太有创意了,border-radius和box-shadow竟然还有这么多好玩的UI展示,研究好透彻啊,厉害大神

  5. ky说道:

    那老师还准备重写吗?

  6. zhaoyp说道:

    受益匪浅,三年多了,果真大神。

  7. huoshen说道:

    设置border-radius:200px/400px,代码相同,效果根本不一样,变成了水平操场。不是椭圆

  8. wmui说道:

    张老师你好,请教下你用的什么画图工具,还有截取gif图用的什么工具,感谢。

  9. xx说道:

    张老师,设置border-radius ,背景图像会不会让它失效?

  10. 雷通达说道:

    border-radius: 84px 292px 222px 112px/146px 272px 194px 300px; 写一个border-color: red transparent transparent transparent;,,,,拖动第一个七大姑八大姨的时候 出现了一个神奇的特效。。。。。。。。。。。。。。。

  11. hwaphon说道:

    很喜欢张老师的博客和慕课网视屏,内容深刻,文笔诙谐,力顶!

  12. 总裁说道:

    夫人知道你的图片素材,估计会揍你吧

  13. Hello World说道:

    大值特性,我怎么理解应该叫做“小值特性”呢?矩形画圆角的时候,是基于短边的

    又看了几遍 是我自己的理解问题
    怎么删评论…

  14. 说道说道:

    靠,赞

  15. Maku说道:

    之前有用过border加粗版的三角形啥的..但是border-radius的这些用法如果没有看这篇文章,估计是真的从来不会想到这点吧。
    但是对于兼容IE7,8来说,就没法随意的使用border-radius来画三角行了….吧……
    =。=哎

  16. 李彦龙说道:

    博主在 花式虐狗

  17. 蒋弋说道:

    为什么我做不出来那个所谓的”惊喜的图形”? 就是第一个”D”下面那个图形
    “我们可以只留一个方向或2侧的边框,可以拉出一些惊喜的效果”就是这一段。

  18. csscss说道:

    nice 已收藏

  19. 茗小铭说道:

    学习了~

  20. 234人说道:

    真佩服你的雅兴和时间,,,,

  21. light说道:

    之前是从慕课网上看到你的。感觉很腻害。后来发现你有自己的网站。果断保存。并时常浏览分享。

  22. allen说道:

    太啰嗦

  23. emi说道:

    非常佩服你对细节的认真,还有你如此的幽默!

  24. 文哥讨厌IE说道:

    恭喜恭喜,学弟我关注学长你很久了,每次来你的博客都感觉醍醐灌顶,很多以前似懂非懂的东西一下子就明白了,真是很感谢!

  25. Roger说道:

    bilibli

  26. 鱼一说道:

    深入浅出,赞

  27. 沃日说道:

    2016还有2个月,怎么能叫还有个把月?你过晕了吧

  28. teaism说道:

    非常感谢分享,真是婚姻事业双丰收哇,赞赞!!

  29. 渐归未来说道:

    还是在虐狗啊

  30. qq说道:

    镜鲤好吃吗

  31. Jimmy说道:

    小崽崽眼神儿很犀利的像他爹啊

  32. 不二很纯洁说道:

    通俗易懂,膜拜大神!