现代 CSS

应用于下一代Web的样式

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

2019年对于CSSer来说是幸运的一年。年中的时候业界出了一份CSS状态报告,而且在年末的时候Web图鉴也对CSS做出相应的分析。这些数据对于一位Web的从业者来说是非常有利的,这些重要的数据告诉CSSer们CSS目前的一种状态,以及应该去掌握哪些CSS特性等。今天要和大家聊的既可以说是新特性(因为很多同学觉得这些东西离实际使用还很远),但也是旧的东西(因为对于时刻关注CSS发展的同学来说是旧的)。前段时间刚结束的2019年Chrome Dev Summit(CDS)大会上,@Adam Argyle@Una Kravets一起分享了一个非常有趣的话题,这个话题就是有关于CSS特性的东东。也被称为是应用于下一代Web的样式

简介

时到今日,Web发展变化非常地大,相应的最近几年CSS的发展也可以说是神速,更值得的庆幸的是,现代Web浏览器对这些新的CSS特性支持度也非常的高。正如@Adam Argyle@Una Kravets一起分享的话题《Next-generation web styling》:

随着新的CSS特性在浏览器中出现,以及CSS Houdini的出现,Web样式变得比以往更加强大。

如果你对这个话题感兴趣,或者觉得有必要继续往下阅读的话,我更建议你先花一点时间观看@Adam Argyle@Una KravetsCDS大会上分享的视频

事实上,你不必担心视频中介绍到的CSS特性不被浏览器支持,因为在一些项目中可以看到这些特性的身影,比如滚动捕捉(Scroll Snap)、粘贴定位(Sticky)、毛玻璃效果(backdrop-filter)、逻辑属性和CSS Houdini等。另外视频中提到的相关特性的Demo在CSS@CDS页面中都可以找到。而且我们接下来的内容中运用到的示例也会采取这里提供的案例。

滚动捕捉(Scroll Snap)

CSS Scroll Snap常被译文滚动捕捉,它是CSS的一个独立功能模块(CSS Scroll Snap Module Level 1)。该特性可以让一个容器滚动停止的时候,自动平滑定位到指定元素的指定位置。其实在去年分享的《改变用户体验的滚动新特性》文章中以及今年在CSS Conf分享的主题中都有介绍到该特性。该特性主要包含了scroll-*以及scroll-snap-*等属性。其中有些属性是作用于滚动容器上,有些属性作用于滚动定位的子元素上:

作用在滚动容器上的属性 作用在定位的子元素上的属性
scroll-snap-type scroll-snap-align
scroll-snap-stop scroll-margin
scroll-padding  

滚动捕捉提供了原生滚动惯性和减速,并且支持触摸

我们来看一个简单的示例,在<section>元素(滚动容器)中设置水平滚动,并且对齐子元素<picture>左侧(对齐点):

section {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
}

section > picture {
    scroll-snap-align: start;
}

就上面的代码来说。在<section>元素上使用了下面这几个有关于滚动条的属性:

overflow-x是大家熟悉的一个CSS属性,让容器水平滚动(当<section>的内容总宽度大于容器宽度时会出现水平滚动条)。

overscroll-behavior-x属性(overscroll-behavior属性是的一个,它还有另一个属性overscroll-behavior-y)也是运用于滚动上的新特性,可以控制一个容器滚动时发生的默认行为。该属性有autocontainnone三个属性值,当该属性取值为contain时,可以阻止容器的滚动行为不会传播给其祖先元素,但会影响其子元素内的局部显示。

scroll-snap-type属性用来确定容器滚动的定位是水平滚动定位,还是垂直滚动定位。该属性接受两个属性值:

第一个属性值 描述
x 捕捉水平定位点
y 捕捉垂直定位点
block 捕捉和块状元素排列一个滚动方向的定位点。默认文档流下指的就是垂直轴
inline 捕捉和内联元素排列一个滚动方向的定位点。默认文档流下指的就是水平轴
both 横轴和纵轴都捕捉
第二个属性值 描述
none 默认值,表示滚动时忽略捕捉点,也就是我们平时使用的滚动效果
mandatory 表示“强制”,强制定位,无论是添加删除元素或者滚动窗口较小,不足以放下子元素。该值是一个可选值
proximity 表示“大约”,可能会定位。该值是一个可选值

另外,我们在<section>的子元素<picture>上使用了scroll-snap-align属性。该属性主要用于捕捉点是上边缘,下边缘还是中间位置。常见的值主要有:

  • none:默认值。不定义位置
  • start:起始位置对齐,例如,垂直滚动,子元素和容器同上边缘对齐
  • end:结束位置对齐,例如,垂直滚动,子元素和容器同下边缘对齐
  • center:居中对齐。元素中心和滚动容器中心一致

同样的,该属性也支持两个属性值,比如scroll-snap-align: start end,这个时候,第一个属性值表示块元素排列方向(通常是垂直方向),第二个属性值表示内联元素排列方向(通常是水平方向)。在上面的代码示例中,scroll-snap-align设置的值为start,它设置<picture>和容器的左侧边缘对齐。

注意:滚动捕捉的特性也会受dirdirection的影响,如果你想了解更多有关于这方面的知识,可以阅读《Web中向左向右》一文

来看看运用了滚动捕捉的效果。

水平滚动捕捉

垂直滚动捕捉

双向滚动捕捉(水平和垂直)

使用了滚动捕捉之后在滚动效果,对于用户的体验会更好,不知道你有没有发现,不管是水平还是垂直方向,只要子元素滚动到一定位置时,哪怕用户停止滚动,子元素也会自动到相应的位置。如下面的录屏效果所示:

有关于这方面更多的介绍,还可以阅读:

逻辑属性

上图来自@Estefany Aguilar的手绘图

CSS逻辑属性的全称是CSS逻辑属性和值CSS Logical Properties and Values Level 1),该规范和CSS Properties and Values API Level 1是完全不同的两个规范。CSS逻辑属性给CSS带来一个全新的概念,并且在布局上有着显著的变化。

众所周知,在CSS中有着很多概念,而且这些概念直接影响了CSS的使用。如果想更好的理解CSS逻辑属性,就必须了解这些概念,比如在 CSS盒模型视觉格式化模型display属性CSS定位和层叠控制等。在以往我们的认识中,所涉及到的属性都可以说是物理属性,这些物理属性和逻辑属性有着一一对应的关系。接下来,咱们简单的来看看。

坐标系统

Web中有着多种不同的坐标系统,比如Canvas、CSS、SVG中的坐标系统还是有一定的差异性的。不过我们这里只看大家熟悉的CSS中的坐标系统。CSS的坐标系统的原点是在屏幕的左上角,它有两个坐标轴,即x轴(水平轴)和y轴(垂直轴):

这看上去和笛卡坐标有点不一样。没有显式的x轴负值和y轴负值。其实在CSS的坐标系统中一样可以使用负坐标,只不过有可能会跑到屏幕(或容器)外面,让人看不到。

事实上,除了大家熟悉的平面画布中的x轴和y轴,还有控制第三维度的z轴:

在CSS中要确定沿着z轴排列元素,表示的是用户与屏幕的这条看不见的垂直线:

另外,CSS中还有一个文档流的概念。形象一点说,流就好比我们生活中的水流,在不同的器皿中将会有不同的形状。这是因为不同的盒子使用的是不同的格式化上下文(Formatting Context)来布局,每个格式化上下文都拥有自己不同的渲染规则,而这些规则是用来决定其子元素如何定位,以及和其他元素的关系。好比水倒进不同的器皿中,会有不同的形态:

但在CSS逻辑属性中,虽然也有着坐标系统的概念,但不再以x轴和y来区分,而是以inlineblock的概念来区分(z轴的概念并没有变化)。这样做是可以很好的和书写模式(writing-mode)相结合。如果你阅读了《Web中向左向右》一文的话,应该多少了解这样做的重要性。

我们来看看个示例:

对应关系如下:

物理属性 逻辑属性(horizontal-tab) 逻辑属性(vertical-lr) 逻辑属性(vertical-rl)
x(水平轴) inline block block
y(垂直轴) block inline inline

注意:CSS的书写模式writing-modedirection和HTML的dir属性对CSS逻辑属性有着直接的影响。

盒模型

可以说CSS盒模型中的属性决定了元素的尺寸大小边框风格元素与元素之间的间距位置等。CSS逻辑属性对于盒模型的变化是非常的大。在物理属性中我们习惯用方向(*-top*-right*-bottom*-left,即可TRBL原则)来区别不同方向的样式、位置和间距等;但在CSS逻辑属性中不再有方向的概念,用*-start*-end来区别。如下图所示:

@Adrian Roselli在Codepen写了一个Demo,你可以切换物理属性和逻辑属性,看出他们之间的差异:

有关于逻辑属性对盒模型产生的变化,还可以阅读早前整理的《CSS的逻辑属性对盒模型带来的变化》一文。

来看一个简单的示例:

对应关系如下表所示:

物理属性 逻辑属性(horizontal-tab) 逻辑属性(vertical-lr) 逻辑属性(vertical-rl)
width inline-size block-size block-size
height block-size inline-size inline-size
min-width min-inline-size min-block-size min-block-size
min-height min-block-size min-inline-size min-inline-size
max-width max-inline-size max-block-size max-block-size
max-height max-block-size max-inline-size max-inline-size
border-top border-block-start border-inline-start border-inline-start
border-right border-inline-end border-block-end border-block-start
border-bottom border-block-end border-inline-end border-inline-end
border-left border-inline-start border-block-start border-block-end
padding-top padding-block-start padding-inline-start padding-inline-start
padding-right padding-inline-end padding-block-end padding-block-start
padding-bottom padding-block-end padding-inline-end padding-inline-end
padding-left padding-inline-start padding-block-start padding-block-end
margin-top margin-block-start margin-inline-start margin-inline-start
margin-right margin-inline-end margin-block-end margin-block-start
margin-bottom margin-block-end margin-inline-end margin-inline-end
margin-left margin-inline-start margin-block-start margin-block-end

定位

物理属性中的toprightbottomleft在逻辑属性中也有着较大的变化。有关于这部的介绍可以阅读@Hui Jing的《Understanding positioning in CSS》一文。

来看一个示例:

对应关系如下:

物理属性 逻辑属性(horizontal-tab) 逻辑属性(vertical-lr) 逻辑属性(vertical-rl)
top inset-block-start inset-inline-start inset-inline-start
right inset-inline-end inset-block-end inset-block-start
bottom inset-block-end inset-inline-end inset-inline-end
left inset-inline-start inset-block-start inset-block-end

在CSS中还有一些物理属性在逻辑属性中会有所变化。比如floattext-align等。另外需要特别声明的是,CSS逻辑属性会受书写模式writing-modedirection以及HTML的dir属性影响。上面给大家展示的只是CSS逻辑属性和writing-mode的结合效果。如果把dirwriting-mode和逻辑属性结合起来的话,事情会变得更为复杂。这里暂且不表,后面我们会花一个章节来详细和大家聊这方面的内容。

CSS选择器

CSS选择器已经有多个版本的变化了,早期的CSS 2.1规范中的选择器、后面规范将选择器成为单独的一个功能模块,按版本分,现在有Level 3Level 4

可以说CSS选择器在CSS中是一个重要的,复杂的体系,如果要彻底的说清楚CSS选择器,都可以写成一本书了。在2019年@张鑫旭 老师的新书就是有关于CSS选择器的——《CSS选择器世界》:

小站上有关于CSS选择器方面的介绍也是比较全面:

@Adam Argyle@Una Kravets分享的话题中主要介绍两个选择器::focus-within:is()

:focus-within

对于CSSer来说,可能更为熟悉的是:focus选择器,对于可聚集的元素来说,都具备聚焦状态,在CSS中可以通过:focus状态选择器来给可聚焦元素在聚焦状态设置样式。最简单的就是:

a:focus {
    outline: none 0;
    box-shadow: 0 0 3px rgba(0,0,0,.5);
}

但对于:focus-within伪类选择器来说,可能有很多同学都不太了解,甚至是从未接触过。因为该选择器是CSS选择器(Level 4)中的一个选择器。该伪类选择器能非常方便的处理获取焦点状态,而且有了:focus-within之后,有一些常见的交互行为就变得非常的简单,甚至是以前一些需要依赖JavaScript来实现的交互行为,我们都可以使用:focus-within来实现。

另外:focus-within还可以解决一个长期存在的可访问性问题:“在很多情况下,当聚焦一个子元素时,应该让其父元素得到聚焦(焦点样式),以便辅助技术可以访问到该UI”。例如,如果你有一个包含多个项目的下拉菜单,当其中任何一个项目得到焦点时,菜单应该保持可见。否则,键盘用户的菜单将消失。

尝试着使用键盘的Tab键来操作导航菜单,效果如下:

:focus-within告诉浏览器在焦点位于指定元素的任何子元素时应用样式。比如下面的代码,当.menu元素设置了:focus-within样式时可以确保它保持可见:

.menu:focus-within {
    display: block;
    opacity: 1;
    visibility: visible;
}

:focus-within:focus其中最大的并异是::focus只能让获得焦点元素自身有样式,而:focus-within除了可以让获得焦点元素自身有样式,还可以让其父元素有样式。用张图来描述他们之间的差别:

再来看一个示例:

有关于该伪类选择器更多的介绍,还可以阅读:

:is()

CSS选择器的Level 4版本中新增了很多伪类选择器,早期在《初探CSS 选择器Level 4》一文中和大家简单的探讨过其中的一些选择器。可以说很多伪类选择器你是从未见过的,比如可以用于实际项目中的:not()选择器以及接下来我们要聊的:is()选择器。

:is()选择器并不是现在才出现的,它实际上有十多年的历史了,而且它的发展是曲折的,因为它几经变更。其中有一段时间规范中把该选择器删除,用:matches()来替代,现在又用回:is():is()选择器可以很好的选择目标元素,而且其最大的优势是可以帮助我们节约很多代码,还提高了CSS代码的可读性。

上图的意思是:

button:is(.focus, :focus) {
    // …
}

article > :is(h1,h2,h3,h4,h5,h6) {
    // …
}

等同于:

button.focus,
button:focus {
    // …
}

article > h1,
article > h2,
article > h3,
article > h4,
article > h5,
article > h6 {
    // …
}

来看一个更为复杂的示例:

article h1, 
article h2, 
article h3, 
article h4, 
article h5, 
article h6,
section h1, 
section h2, 
section h3, 
section h4, 
section h5, 
section h6,
aside h1, 
aside h2, 
aside h3, 
aside h4, 
aside h5, 
aside h6, {
    font-weight: 900;
}

如果我们使用:is()伪类选择器的话,上面的一坨代码就可以像下面这样简洁:

:is(article, section, aside) :is(h1, h2, h3, h4, h5, h6) {
    font-weight: 900;
}

是不是觉得很酸爽。

在CSS的选择器中还有一个与:is()伪类选择器风格恰恰相反的伪类选择器,即:not():not()是非的意思,来看一个简单的示例:

li:not(:last-child){
    margin-bottom: 20px;
}

上面代码的意思就是除了最后一个li之外的所有limargin-bottom值为20px

我们还可以将:is():not()混合起来使用。比如前面的示例:

:is(article, section, aside) :is(h1, h2, h3, h4, h5, h6) {
    font-weight: 900;
}

表示articlesectionaside的后代元素h1~h6font-weight: 900。如果将上面的代码换成:

:not(article, section, aside) :is(h1, h2, h3, h4, h5, h6) {
    font-weight: 400;
}

而上面的代码表示的是除了articlesectionaside元素的后代标题元素(h1~h6)的所有标题元素。听起来有点拗口,还是用代码来表示吧:

:not(article h1), :not(section h1), :not(aside h1),
:not(article h2), :not(section h2), :not(aside h2),
:not(article h3), :not(section h3), :not(aside h3),
:not(article h4), :not(section h4), :not(aside h4),
:not(article h5), :not(section h5), :not(aside h5),
:not(article h6), :not(section h6), :not(aside h6) {
    font-weight: 400;
}

正如上面的示例所示,将:is():not()结合起来使用会更具有良好的语法意义,使组合更具逻辑性和直接性。这也是为什么在新的规范中使用:is()重新替代:any():matches()的主要原因。

有关于:is()更多的介绍还可以阅读:

粘性定位(position: sticky

前面提到过了,定位和叠层也是CSS中的重要概念之一,也是一个独立的模块,即CSS Positioned Layout Module Level 3

在开始之前先说个题外话,有时候面试的时候,问面试者知道position有哪些属性值,有不少同学只能说出staticrelativeabsolutefixed,会选择性的忽略(或不知道)sticky

如果元素的position设置了非static之外的值时,该元素就会被称为定位元素:

而其中sticky是后面被加入的一个属性值,我常把它称为“粘性定位”。接下来我们就来简单地说说这个粘性定位。

粘性定位是一个很有意思的定位,从表面效果上来看,它是相对定位固定定位的混合效果。元素在跨越特定阈值前是相对定位的效果,之后是固定定位的效果。

也就是说,具有position: sticky的元素会一直停留在文档流中,直到它开始离开屏幕,它才会固定在屏幕的某个位置;但是当用户回滚时,元素会返回原来的文档流中的位置(文档流会给粘性元素保留空间)。粘性定位可以帮助我们创建很多以前需要借助JavaScript才能实现的效果。在视频中演示了几种粘性定位的常见效果:

粘性的堆栈

在这个Demo中,所有粘性元素共享同一个容器。这意味着,当用户向下滚动时,每个粘性元素都会在前一个元素上滑动。粘性元素也会共享相同的固定位置。具体效果如下:

粘性的幻灯片(Slide)

在这个Demo中,粘性元素是表兄弟(他们的父元素是兄弟元素)。当一个粘性元素碰到它的容器的下边界时,它会随着容器向上移动,从而造成一种假象,即较低的粘性元素向上推动了较高的粘性元素。换句话说,他们似乎是在争夺被卡住的位置。

如果将上面的粘性元素样式换换,那么还可以得到下面这个示例的效果:

有关于粘性定位更多的介绍还可以阅读:

媒体查询

CSS媒体查询(Media Queries)其实不是新东西,他一直都存在于CSS中,只不过早期的CSS媒体查询功能没有那么的强大:

<link rel="stylesheet" type="text/css" media="screen" href="sans-serif.css">

@media screen {
    * { font-family: sans-serif }
}

随着CSS的发展,CSS媒体查询也纳入条件CSS(Conditional CCSS)的系列中,成为条件CSS属性之一。加上Web响应式设计的出现以及众多不同终端设备的流行,CSS媒体查询变得越来越强,支持的特性也越来越多:

开发者可以通过媒体查询的规则,为不同的平台提供不同的样式规则:

媒体查询包含一个可选的媒体类型和媒体特性表达式(零个或多个):

媒体查询中的特性表达式最终会被解析为true(符合条件规则)或false(不符合条件规则)。如果媒体查询中指定的媒体类型匹配展示文档所使用的设备类型,并且所有的表达式的值都是true,那么该媒体查询的结果为true

CSS媒体查询在这几年发展特别神速,目前最新的规范版本已经到了Level 4。而且Level 5(还在草案阶段)为我们提供了更多强大的方法,可以根据用户的设备偏好调整应用程序的用户体验:

以下是可能是开发人员比较感兴趣的一些新的媒体查询特性:

  • prefers-reduced-motion:用于检测用户是否请求系统将其使用的动画或运动的数量减少到最小
  • prefers-color-scheme:用于检测用户是否请求系统使用浅颜色或深颜色主题
  • prefers-contrast:用于检测用户是否请求系统增加或减少相邻颜色之间的对比度
  • prefers-reduced-transparency:用于检测用户是否请求系统使用的最小化透明或半透明层效果
  • forced-colors:用于检测用户代理是否启用了强制颜色模式,该模式强制在页面上使用用户选择的有限颜色调色板
  • inverted-colors:可以用来测试用户代理或底层操作系统是否反转颜色
  • light-level:用于查询设备所使用的环境光级,允许作者相应地调整文档的样式

可能上面的列表中有很多个查询特性大家都会感到陌生。这里拿两个我最为熟悉或者有实际接触过的特性来举例。

使用prefers-color-scheme来切换暗黑模式

macOS系统和iOS13系统提出了darklight两种视觉模式,即暗色(dark高亮(light两种皮肤,而且这两种皮肤是系统级别的,我们可以通过系统上的切换,让整个电脑上只要支持dark/light模式的应用都可以轻易切换。

在以往,我们是无法获知用户是否开启了自己的偏好设置。那么现在我们就可以通过prefers-color-scheme: dark来做判断,如果用户开启了dark模式就会采用暗色系,如果开启的是light模式,就会采用亮色系。对于我们Web开发者而言,我们就可以像下面这样提供两套皮肤:

:root {
    --duration: 0.5s;
    --timing: ease;

    --bg-color-primary: #f0f0f0;
    --bg-color-secondary: #fff;
    --bg-color-tbleve3: #fafafa;
    --text-color-primary: #111;
    --text-color-secondary: #666;
    --text-auxiliary-color-primary: #999;
    --text-auxiliary-color-secondary: #ddd;
    --icon-filter_hover: invert(60%);

    color-scheme: dark light;
    supported-color-schemes: dark light;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg-color-primary: #111;
        --bg-color-secondary: #222;
        --bg-color-tbleve3: #333;
        --text-color-primary: #ddd;
        --text-color-secondary: #aaa;
        --text-auxiliary-color-primary: #888;
        --text-auxiliary-color-secondary: #777;
        --icon-filter: invert(100%);
        --icon-filter_hover: invert(60%);
        --image-filter: grayscale(50%);
    }

    img[src*='.svg'] {
        filter: var(--icon-filter);
    }

    img:not([src*='.svg']) {
        filter: var(--image-filter);
    }
}

body {
    transition: color var(--duration) var(--timing), background-color var(--duration) var(--timing);
    background-color: var(--bg-color-primary);
    color: var(--text-color-primary);
}

比如下面这样的一个示例:

如果你对如何实现暗黑模式的相关技术感兴趣的话,还可以花点时间阅读:

使用prefers-reduced-motion来让动画或动画数量减少

前面时间在学习A11Y相关知识的时候了解到。我们的用户可能会有这么一样的群体“认知障碍”。意思是认知障碍一般指的是有晕动症(指与晕动症和感官超载相关,比如癫痫病患者)、有学习障碍和阅读困难等用户群体。面对这些群体,我们应该尽量让页面上不能有动效,因为动效会诱导类似患有癫痫病患者发病(这可能是件极其危险的事)。作为开发者,我们就有必要注意这方面。

不要以已知会导致癫痫发作的方式设计内容。

Web中的很多动效会导致癫痫发作,比如每秒钟闪灯次数不应该超过三次。或者,闪光应该低于一般闪光和红色闪光阈值。如果您不确定,可以使用光敏癫痫分析工具Flash测试来测试你的站点或应用。

一般患有癫痫病的用户都有可能会通过下面的方式开启减少运动(Reduce Motion):

为此,为了避免这种现象出现,媒体特性中提供了prefers-reduced-motion条件来做判断:

@media (prefers-reduced-motion: reduce) { 
    * { animation: none; } 
}

比如下面这个示例:

切换效果会像下图这样:

gap

在Web布局时间避免不了处理元素与元素之间的间距,以往一般都是采用margin(或你已开始使用逻辑属性margin-inlinemargin-block等属性),但总是不够灵活。特别是在CSS Grid布局中,通过指定容器元素的内部间距而不是子元素周围的间距,那么margin这样的属性就不够灵活了。

庆幸的是,现在在CSS Box Alignment Module Level 3中定义了gap,这部分主要定义了用于column(多列)布局的row-gapcolumn-gap,在Grid中定义了gap属性(是grid-row-gapgrid-column-gapgrid-gap统称)。

用一张图来描述,gapmargin的差异:

gap可以帮助我们解决很多常见的布局问题。例如,使用gap,您不必担心子元素上的空白会在容器元素的边缘造成不必要的空白。比如下面这个示例:

在未来Flexbox布局中也可能会有gap的引入。现在Firefox已经实现了Flexbox中gap的效果,如下图所示:

下面视频向大家演示了修改视窗大小的效果:

上面提到了CSS Grid,这里有必要和大家说一下subgrid。在CSS Grid Layout Module Level 2提出了subgrid,取代grid的嵌套:

比如下面这样的一个示例:

有关于subgrid更多的介绍,可以阅读下面这些文章:

毛玻璃效果

在iOS系统上常常能看到高斯模糊(Gaussian Blur)效果:

早期一般都是使用CSS的filter来模拟这种毛玻璃(磨砂)效果:

上面的示例就是使用CSS的filter来实现的一个效果。虽然filter实现的效果看上去有点类似毛玻璃的效果,但效果还是有点差强人意。后面CSS的backdrop-filter可以让我们实现这样的效果变得更为轻松:

backdrop-filter又被称为高级filter,但backdrop-filterfilter有一个极大的差异:“filter会影响其后代元素,但backdrop-filter不会影响后代元素,会将效果应用于元素后面的区域”。比如:

h1 {
    backdrop-filter: blur(10px);
}

有关于这方面的相关的介绍还可以阅读下面这些文章:

CSS自定义属性(变量)

除了CSS语言之外的其他计算机语言都有变量的概念,但随着CSS预处理器语言的出现,开始引入了变量的概念,随之CSS也引入了变量的概念,但CSS中原生中的变量概念有两种说法:自定义属性变量

使用--前缀声明的属性被称之为CSS的自定义属性,通过var()函数引用的自定义属性又被称之为CSS的变量!

简而言之,在CSS的世界中,通过--前缀声明的属性既是自定义属性也是变量。

  • 自定义属性:使用--**代表任意声明的名称)声明的特殊格式作为名称,该名称被称为自定义属性,同时可以给自定义属性赋予任何值。比如--color: #fff
  • 变量:CSS的var()函数引用的自定义属性被称为变量。var()会返回自定义属性所对应的值,同时可以被运用于相应的CSS属性。对应的即是CSS规则中的属性值

用张图来描述他们之间的关系:

到今天为止,CSS自定义属性可以说是很成熟了,在很多地方都可以看到其身影。这里不做过多阐述,感兴趣的话可以阅读下面这方面的内容:

变量字体(VARIABLE FONTS)

在Web开发中,能够在Web中使用安全字体。这也成为了一个设计限制,很多艺术字体用不了。还好,我们可以通过@font-face来自定义字体,并将其运用于Web中。CSS Fonts Module Level 4中新增了一个变量字体(Variable Fonts)的概念,将自定义字体提升到一个全新的级别。我们不需要再为每个宽度,粗细或样式准备单独的字体文件,而是将一个字体的许多不同变体合并到一个文件中。比如:

@font-face {
    font-family:'Decovar Regular24'; 
    src:url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/209981/Decovar-VF.ttf');
}

h1 {
    font-family: "Decovar Regular24"; 
    font-variation-settings: 'SSTR' 1000;
}

在CSS中可以通过font-variant-*属性来控制大多数OpenType特性。而且还可以在@keyframes会让效果变得更好:

有关于字体变量更多的介绍,还可以阅读:

CSS Houdini

Houdini是一组底层API,它们公开了CSS引擎的各个部分,从而使开发人员能够通过加入浏览器渲染引擎的样式和布局过程来扩展CSS。 Houdini是一组API,它们使开发人员可以直接访问CSS对象模型(CSSOM),使开发人员可以编写浏览器可以解析为CSS的代码,从而创建新的CSS功能,而无需等待它们在浏览器中本地实现。

这组API,只有两个限制条件:你的想象力浏览器对Houdini支持性

Houdini可以让你告诉浏览器如何解释定制的CSS。也就是说,它允许你使用JavaScript访问CSSOM来扩展CSS。

如果你想了解Houdini,强烈建议你看看@Vincent De Oliveira的CSS Houdini Experiments。另外也可以观看@Una Kravets在JSConf上分享的视频:

@malyw分享的PPT

更多Houdini的内容还可以阅读:

其他

在CSS中还有很多其他的东西值得我们深入去探讨。其中有些功能你可能听说过,也有些从未听说过。由于时间有限,我们不在这篇文章中做深入的阐述:

  • size:允许同时设置widthheight的属性
  • aspect-ratio:元素宽高比(纵横比),早前在《Web中如何实现纵横比》和 《CSS实现长宽比的几种方案》模拟aspect-ratio属性的特性
  • min()max()clamp()CSS函数允许你设置任何CSS属性的数值约束,而不仅仅是宽度和高度
  • list-style-type:是一个现有的属性,但它将很快支持更广泛的值,包括emoji和SVG。而且CSS的::marker会让这方面更强大
  • display:很快display属性就能接受两个属性值,这将允许你显式地指定它的外部和内部布局,比如display: flexdisplay: block flex

小结

正如前面大家所看到的,这些年CSS发展是非常快速的,而且都是一些强大的特性,可以实实在在解决我们实际需求的特性。当然,这些属性并不是一触而就,也是经过不断革新一演进的。最后,希望文章中所提到的东西能够帮助你,让你在当前的项目中使用这些现代的CSS特性。如果你有这方面使用的经验或者更好的建议,欢迎在下面的评论中与我们一起分享。

扩展阅读

返回顶部