CSS3 gradient介绍

今天出去吃饭,饭后搞活动送了个小礼品。礼品本身不值一提,重要的的是渐变。本篇就介绍并实际做一下这个渐变效果。

渐变gradient分为linear-gradient(线性渐变)和radial-gradient(径向渐变)。

线性渐变

W3C标准语法:linear-gradient(angle, color… color);。第一个参数指明渐变方向,0deg表示渐变从下往上,90deg表示渐变从左往右,180deg表示渐变从上往下,270deg表示渐变从右往左。其实就是顺时针走一圈。你也可以用to + 关键字,例如to top等于0deg,to right等于90deg,to bottom等于180deg,to left等于270deg。第二参数是起始颜色,中间可以指定多个颜色,依次渐变,最后一个参数是终止颜色。权威请参照W3C

先看简单的,就2个颜色,从白到黑渐变。图1代码linear-gradient(0deg, #fff, #000);linear-gradient(to top, #fff, #000);,代码根据表题依次类推,一图胜千言

新版浏览器用W3C的标准语法没问题,但低版本可能尚不支持W3C的标准语法,此时你需要使用各浏览器私有的语法。当然如果你的页面不准备继续支持这些低版本的浏览器的话,此段可以略过。

Webkit引擎(Chrome和Safari),Genko引擎(Firefox),Presto引擎(Opera),Trident引擎(IE)的私有语法和和W3C的标准语法非常像。区别如下:

  1. 需要加上前缀,分别是-webkit-,-moz-,-ms-
  2. -webkit-,-ms-的第一个参数的关键字表示起始位置,因此不需要加to。例如-webkit-linear-gradient(top, #fff, #000);等价于W3C标准语法的linear-gradient(to bottom, #fff, #000);
  3. -moz-的第一个参数的关键字可以可不加to。不加to表示起始位置,加to表示终止位置。例如-moz-linear-gradient(top, #fff, #000);等价于-moz-linear-gradient(to bottom, #fff, #000);
  4. IE10以下是不支持渐变的…因此没有私有语法
  5. Opera从37开始支持,试了下并没有私有语法,加上-o-前缀反而不认…

另外Webkit引擎(Chrome和Safari)的旧版本还支持一种更旧的私有语法,即旧版本的Webkit引擎的浏览器有两种私有语法。旧语法:-webkit-gradient(type, point, point, color, color)。第一个参数type指明linear线性渐变或radial径向渐变。第二三参数分别是渐变的起点坐标和终点坐标。第四五参数是color-stop函数来表示起始和终止颜色。color-stop()支持两个参数,第一个是点的位置,第二个是颜色,例如color-stop(0.5, #fff)表示在渐变范围的中心处有个黑色的过渡色。具体你可以参照这里

为缩减篇幅,下面仍以介绍W3C标准语法为主。

上面的例子是2个颜色渐变,现在试试指定多个颜色间依次渐变。例如linear-gradient(to bottom, yellow, #9C117A, #EF137A, #f00);

上面指定了4个颜色,等比例依次渐变,但有时我们需要自己控制渐变的比例,可以在色彩后面追加%百分比。例如linear-gradient(to bottom, yellow 0%, #9C117A 20%, #EF137A 80%, #f00 100%);。第一个颜色渐变范围0-20%,第二个颜色渐变范围20-80%,第三个颜色渐变范围80-100%,第四个颜色渐变范围100-100%渐变,等于第四个颜色没有渐变

不在位置范围内的颜色表示不渐变,会填充为实色。例如:


background-image:linear-gradient(to bottom, #fb3 20%, #58a 80%);

渐变区域只集中在中间20-80%区域。上部20%是#fb3的实色,下部20%是#58a的实色。即上下各20%的区域都是实色,不渐变。因此如果你将两个颜色的位置值均设为50%,就出现了完全没有渐变效果,全部实色的背景:


background-image:linear-gradient(to bottom, #fb3 50%, #58a 50%);

另外,标准规定:如果颜色的位置值比在它之前的所有颜色的位置值都小,那该颜色的位置值会被调整为它前面所有颜色位置值的最大值。因此上面代码可以把第二个色标位置值设为0:

background-image:linear-gradient(to bottom, #fb3 50%, #58a 50%);
//等价于
background-image:linear-gradient(to bottom, #fb3 50%, #58a 0);

用实色这个特点很容易实现常见的条纹状的背景效果:


background-image: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);

上面#fb3 25%表示从0-25%区域是实色。#58a 0, #58a 50%等价于#58a 25%, #58a 50%,表示从25-50%区域从#58a渐变至#58a,等于实色。#fb3 0, #fb3 75%等价于#fb3 50%, #fb3 75%,表示从50-75%区域为从#fb3渐变至#fb3,等于实色。最后#58a 0等价于#58a 75%,表示从75%开始全都是实色。

你也可以发挥想象力,将实色这个特点还可用于遮蔽,达到切角效果。这样就避免了多个标签,通过层叠覆盖来实现切角。用渐变简单方便。


.clip {
    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;
    padding: .5em .6em;
    color: white;
    font: 50px/64px "微软雅黑";
}

<span class="clip">禮</span>

你也可以将上面线性渐变改成下面介绍的径向渐变来实现弧形切角。

径向渐变

线性渐变是沿着一条直线渐变,而径向渐变是圆形或椭圆形渐变。相比之下稍微复杂一点。

W3C标准语法:radial-gradient(position, shape, size, color-stop);

第一个参数size at position。size指定水平半径和垂直半径。position指明圆心位置,默认值center表示元素中心为渐变的圆心。同样可以指定为top,right,bottom,left,也可以自定义px值或%百分比,对应关系如下。

size和position用at连接。例如20px 50px at center,表示以元素中心点为圆心,20px为水平半径,50px为垂直半径的椭圆型渐变。具体效果见下图的第一,二行。

第二个参数size shape。shape可设circle,ellipse。看名字就知道了,前者表示圆形渐变,后者表示椭圆形渐变。

如果shape设成circle,那size的px值就是圆形半径,但不能用%百分比。例如40px circle表示半径为40px的圆型渐变。

如果shape设成ellipse,那size的值分别为椭圆的水平半径和垂直半径。可以用%百分比。例如30% 80% ellipse表示水平半径30%(相对于元素的宽),垂直半径80%(相对于元素的高)的椭圆型渐变。具体效果见下图的第三行。

前两个参数可以合并成size shape at position。例如100px 60px ellipse at right表示圆心在右中位置,水平半径100px,垂直半径60px的椭圆渐变。效果见下图第9单元格。

上面的size除了设px值或%百分比外,还有预定义好的关键字closest-sideclosest-cornerfarthest-sidefarthest-corner(默认值)。看名字也能猜出意思,例如默认值farthest-corner表示渐变半径为从圆心到离圆心最远的角落。效果见下图第4行各单元格。

第四个参数color-stop()函数,在线性渐变里有介绍,不赘述。

效果图如下,表行就是radial-gradient的参数:


多色渐变

上面的渐变都只设了两个颜色,一个起始一个终止。其实可以设多个颜色达到多色渐变的效果。例如,左图线性渐变模拟日出效果,右图径向渐变模拟太阳。纯CSS实现,毫无PS痕迹。


//左图日出
background-image: linear-gradient(to bottom, #071B26 0%, #071B26 30%, #8A3B12 80%, #240E03 100%);
//右图太阳
background-image: radial-gradient(circle,red,orange,#071B26);

重复渐变

CSS3之前想要对background-image实现重复渐变需要配合background-repeat,但也仅限于重复线性渐变,无法重复径向渐变。CSS3提供了repeating-linear-gradientrepeating-radial-gradient便捷地实现重复渐变。例如

//重复线性渐变
background-image: repeating-linear-gradient(red,green 40px, orange 80px);
//重复径向渐变
background-image: repeating-radial-gradient(black 10px,black 20px,#2a2a2a 30px,#2a2a2a 40px);

上面介绍过条纹背景的实现,但现实中的条纹背景,25%的颗粒度实在太大,比如我们想实现每个条纹的宽度为15px,用重复渐变就可以轻松实现:


background-image: repeating-linear-gradient(45deg, #fb3, #fb3 15px, #58a 0, #58a 30px);

但通常条纹状背景色可能色差不是那么大,而且如果浏览器不支持repeating-linear-gradient就显示不出背景了。因此一种安全的重复渐变方案是,主色调作为背景,而辅助条纹用渐变:


background: #58a;
background-image: repeating-linear-gradient(30deg, hsla(0,0%,100%,.1), hsla(0,0%,100%,.1) 15px,
              transparent 0, transparent 30px);

顺着这个思路可以实现信封效果:(关于background两层背景的思路,可以参照这里

background: linear-gradient(white, white) padding-box,
            repeating-linear-gradient(-45deg, red 0, red 12.5%, transparent 0, transparent 25%, 
                  #58a 0, #58a 37.5%, transparent 0, transparent 50%) 0 / 6em 6em;

还有常见的剪裁的效果:


border: 1px solid transparent;
background: linear-gradient(white, white) padding-box,
            repeating-linear-gradient(-45deg, black 0, black 25%, transparent 0, transparent 50%) 0 / .6em .6em;
animation: ants 12s linear infinite;    //增加动画效果

@keyframes ants { 
    from { background-position: 0 0; }
    to { background-position: 100% 100%; } 
}

增加动画效果后虚线的边框会不停滑动(关于animation你可以点击这里),单纯将border设成dashed是无法实现滑动效果的。

兼容性

目前gradient在众多浏览器上表现不错,但有些低端浏览器上会出现一些兼容性的问题。我的建议是放弃它们吧,低端浏览器活不过今年。况且渐变毕竟属于渐进增强,即使没有渐变效果也不影响用户的实际使用。

但有时人在江湖身不由己,想象一下和河马们或客户们解释浏览器的占有率,解释渐进增强是件多么累人的事吧。况且你心里很清楚,懂的人不需要解释,不懂的人解释了也没用。所以你可以考虑以下方案模拟出gradient效果:

  1. 最简单的方式就是直接PS出一张图片,虽然多了一次HTTP请求,但你不说谁知道呢_
  2. 使用脚本,例如PIE脚本等。但会通过JS对HTML结构进行调整,尤其涉及定位时,bug调试起来真的比较麻烦。
  3. 对低端IE使用滤镜

总结

不忘初心方得始终,来模拟实先一下小礼品的图标(色彩可能做不到完全一致):


.priv_icon_coupon {
    width: 70px;
    height: 70px;
    border-radius: 0.3em;
    border:3px solid #fff;
    background-image: linear-gradient(to bottom, #EF137A, #9C117A);
    font: 50px/64px "微软雅黑";
    color: #fff;
    text-align: center;
    text-shadow: 0 1px rgba(0,0,0,.5);
}
<span class="priv_icon_coupon">禮</span>

网上也有很多牛人做的渐变效果,如Lea Verou

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容