使用其原CSS代码在一些浏览器解析,未经作者许

作者: 前端  发布:2019-11-05

在 CSS 中使用功能查询

2016/09/04 · CSS · 功能查询

原文出处: Jen Simmons   译文出处:Erichain_Zain   

在 CSS 里,有一个你可能没有听过的工具,但是它已经出现一段时间了,而且非常强大。也许,它会成为 CSS 中你最喜欢的东西之一。

那么,是什么呢?就是 @support,也就是功能查询。

通过 @support,你可以在 CSS 中使用一小段的测试来查看浏览器是否支持一个特定的 CSS 功能(这个功能可以是 CSS 的某种属性或者某个属性的某个值),然后,根据测试的结果来决定是否要应用某段样式。比如:

CSS

@supports ( display: grid ) { // 如果浏览器支持 Grid,这里面的代码才会执行 }

1
2
3
@supports ( display: grid ) {
    // 如果浏览器支持 Grid,这里面的代码才会执行
}

如果浏览器能够理解 display: grid,那么,大括号里的代码都会被应用,否则,这些样式就会被跳过。

现在,对于功能查询是什么,你也许还有一点疑惑。这并不是通过某种额外的验证来分析浏览器是否已经确切的实现了某个 CSS 属性。如果你需要查看额外的验证,可以查看 Test the Web Forward。

功能查询让浏览器自己就能够表现出是否支持某个 CSS 属性或者 CSS 属性值。然后通过这个结果来判断是否要应用某段 CSS。如果一个浏览器没有正确的(或者完全的)实现一个 CSS 属性,那么,@supports 就没有什么用了。它并不是一个能够让浏览器的 bug 消失的魔杖。

但是,我已经发现 @supports 是那么难以置信的有帮助。比起以前没有这个属性的时候,@supports 能够让我一再的使用新的 CSS 功能。

多年以来,开发者们都在使用 Modernizr 来实现功能查询,但是 Modernizr 需要 JavaScript。虽然这部分 JavaScript 很小,但是,CSS 结构中添加了 Modernizr 的话,在 CSS 被应用之前,就需要下载 JavaScript 然后等待执行完成。比起使用 CSS,加入了 JavaScript 总是会更慢。而且,要是 JavaScript 执行失败了呢?另外,Modernizr 还需要一层额外复杂的、很多项目都无法理解的东西。相比之下,功能查询更快,功能更强大,使用起来更简单。

你也许注意到了,@supports 的写法和媒体查询很类似,我觉得他们可能就是堂兄弟的关系。

CSS

@supports ( display: grid ) { main { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); } }

1
2
3
4
5
6
@supports ( display: grid ) {
    main {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    }
}

大多数时候,你其实不需要这样的测试。比如,你可以直接这样写:

CSS

aside { border: 1px solid black; border-radius: 1em; }

1
2
3
4
aside {
    border: 1px solid black;
    border-radius: 1em;
}

如果浏览器能够理解 border-radius,那么,在相应的容器上就会应用圆角样式。如果它不能理解这个属性,那么,就会直接跳过并继续执行下面的语句。容器的边缘也就保持直角了。完全没有必要使用功能查询或者测试,CSS 就是这样运作的。这是属于 CSS 中稳固设计,渐进增强的一个基本的原则。浏览器会直接跳过他们无法解析的语句,不会抛出任何错误。

图片 1

大多数浏览器都会应用 border-radius: 1em;,然后展示出右边的效果。但是,在 IE6,7,8 上你却不能看到圆角,你看到的将是左边的效果。可以看看这个例子:A Rounded Corner Box。

对于这个例子,没有必须要使用功能查询。

那么,什么时候才需要使用 @supports 呢?功能查询是将 CSS 声明绑定在一起的一个工具,以便于这些 CSS 规则能够在某种条件下以一个组合的方式运行。当你需要混合使用 CSS 的新规则和旧规则的时候,并且,仅当 CSS 新功能被支持的时候,就可以使用功能查询了。

译者注:以下例子中的 initial-letter 属性现在在所有现代浏览器中都不受支持,所以,以下例子中的代码可能都是无效的代码。如果下文中有提到此属性在某某浏览器中受支持的话,请忽略。需要了解 initial-letter 详细的说明,可以参考initial-letter | MDN。

来看一个关于使用 initial-letter 的例子。这个属性告诉浏览器要将特指的那个元素变得更大,就像一个段首大字一样。在这里,我们要做的就是让段落的第一个字母的大小为四行文字那么大。同时,我们再对它进行加粗,在它的右边设置一些 margin,还给它设置一个高亮的橘色。OK,很不错了。

CSS

p::first-letter { margin-right: 0.5em; color: #FE742F; font-weight: bold; -webkit-initial-letter: 4; initial-letter: 4; }

1
2
3
4
5
6
7
p::first-letter {
    margin-right: 0.5em;
    color: #FE742F;
    font-weight: bold;
    -webkit-initial-letter: 4;
    initial-letter: 4;
}

图片 2

这是在 Safari 上的效果

让我们看看在其他浏览器上的效果。

图片 3

好吧,简直没法接受。除了使用 initial-letter 来达到我们想要的效果之外,我们并不想要改变字体的 colormargin,和font-weight。所以,我们需要一个方法来测试浏览器是否支持 initial-letter 这个属性,然后在浏览器支持这个属性的时候再应用相关的样式。所以,使用功能查询:

CSS

@supports (initial-letter: 4) or (-webkit-initial-letter: 4) { p::first-letter { -webkit-initial-letter: 4; initial-letter: 4; color: #FE742F; font-weight: bold; margin-right: 0.5em; } }

1
2
3
4
5
6
7
8
9
@supports (initial-letter: 4) or (-webkit-initial-letter: 4) {
    p::first-letter {
        -webkit-initial-letter: 4;
        initial-letter: 4;
        color: #FE742F;
        font-weight: bold;
        margin-right: 0.5em;
    }
}

注意,测试的时候需要进行完全的测试,CSS 属性和值都得写上。一开始我也比较疑惑,为什么非得测试 initial-letter: 4呢?4 这个值很重要吗?如果我写成 17 呢?莫非是需要匹配我即将要应用的 CSS 中的样式吗?

原因是这样的:@supports 在测试的时候,需要提供属性和值,因为有时候测试的是属性,有时候测试的是值。对于 initial-letter ,你输入多少值并不重要。但是,如果是 @suports ( dislay: grid ) 就不一样了,所有浏览器都识别 display,但是,并不是所有浏览器都识别 display: grid

回到我们的例子,当前的 initial-letter 只在 Safari 9 上受支持,并且需要加前缀。所以,我加了前缀,同时,保持着不加前缀的规则,并且,我还写了测试来测试另外的属性。没错,在功能查询中,还可以使用 and, or, not 声明。

下面是新的结果。理解 initial-letter 的浏览器会显示一个巨大加粗高亮的段首大字。其他浏览器的行为就像是这个段首大字不存在一样。当然,如果更多的浏览器支持了这个属性,那么,他们的行为也将会是有一个段首大字。

图片 4

深入探讨 CSS 特性检测 @supports 与 Modernizr

2017/03/01 · CSS · Modernizr

本文作者: 伯乐在线 - chokcoco 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

什么是 CSS 特性检测?我们知道,前端技术日新月异的今天,各种新技术新属性层出不穷。在 CSS 层面亦不例外。

一些新属性能极大提升用户体验以及减少工程师的工作量,并且在当下的前端氛围下:

  • 很多实验性功能未成为标准却被大量使用;
  • 需要兼容多终端,多浏览器,而各浏览器对某一新功能的实现表现的天差地别;

所以有了优雅降级和渐进增强的说法,在这种背景下,又想使用新的技术给用户提供更好的体验,又想做好回退机制保证低版本终端用户的基本体验,CSS 特性检测就应运而生了。

CSS 特性检测就是针对不同浏览器终端,判断当前浏览器对某个特性是否支持。运用 CSS 特性检测,我们可以在支持当前特性的浏览器环境下使用新的技术,而不支持的则做出某些回退机制。

本文将主要介绍两种 CSS 特性检测的方式:

  1. @supports
  2. modernizr

检测浏览器对HTML5和CSS3支持度的方法,html5css3

这篇文章主要介绍了检测浏览器对HTML5和CSS3支持度的方法,使用Modernizr来检测浏览器对HTML5和CSS3代码的兼容程度,需要的朋友可以参考下

 HTML5, CSS3 以及其他相关技术例如 Canvas、WebSocket 等等将 Web 应用开发带到了一个新的高度。该技术通过组合 HTML、CSS 和 JavaScript 可以开发出桌面应用具有的效果。尽管 HTML5 承诺很多,但现实中对 HTML5 支持的浏览器以及 HTML5 标准本身的完善程度都还没有到一个很成熟的程度。现在完全不担心浏览器支持是不现实的,还需要时间,因此当我们决定要采用 HTML5 技术开发 Web 应用的时候,我们需要对浏览器所支持的特性进行检测。

而 Modernizr 就可以帮助你完成对浏览器所支持 HTML5 特性的检查。

下面代码检测浏览器是否支持 Canvas:  

代码如下:<script>
window.onload = function () {
if (canvasSupported()) {
alert('canvas supported');
}
};

function canvasSupported() {
var canvas = document.createElement('canvas');
return (canvas.getContext && canvas.getContext('2d'));
}
</script>

下面代码检测浏览器是否支持本地存储:
 
代码如下:
<script>
window.onload = function () {
if (localStorageSupported()) {
alert('local storage supported');
}
};

function localStorageSupported() {
try {
return ('localStorage' in window && window['localStorage'] != null);
}
catch(e) {}
return false;
}
</script>

上面的两个例子中我们可以很直观的对浏览器的特性进行检查以确保我们在对应的浏览器上应用的功能能否正常运作。

而使用 Modernizr 的好处还在于你不需要这样一项项去检查,还有更简单的方法,下面我们开始:

当我第一次听到 Moderizr 这个项目时,我以为这是一个让一些老的浏览器能支持 HTML5 的 JS 库,事实上不是,它主要是检测的功能。

Modernizr 可以通过网址 来访问,该网站同时还提供一个定制脚本的功能,你可以确定你需要检测什么特性,并依此来生成相应的 JS 文件,这样可以减少不必要的 JS 代码。 
图片 5

 一旦下载了 Modernizr 的 JS 文件后,就可以通过 <script> 标签引入到网页中。  

代码如下:<script src="Scripts/Modernizr.js" type="text/javascript"></script>

检测 HTML 元素

一旦我们在页面上引入了 Modernizr 后就可以立即使用,我们可以在 <html> 元素中声明不同的 CSS 类,这些类定义了所需要支持或者不支持的特性,不支持的特性其类名一般是 no-FeatureName,例如 no-flexbox。下面是一个在 chrome 上可运行的例子:

 
代码如下:
<html class=" js flexbox canvas canvastext webgl no-touch geolocation postmessage
websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla
multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity
cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d
csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers
applicationcache svg inlinesvg smil svgclippaths">

还可以这样来判断浏览器是否启用了 JavaScript 支持:  

代码如下:<html class="no-js">

你可以在 HTML5 Boilerplate () 或者是 Initializr () 看到一些入门的例子,根据上面的步骤,增加 no-js 类可以判断浏览器是否启用了 JavaScript 支持。
 
使用 HTML5 和 CSS3 特性

你为 <html> 标签增加的 CSS 属性,可以直接在 CSS 中定义所需要的样式,例如:
 
代码如下:
.boxshadow #MyContainer {
border: none;
-webkit-box-shadow: #666 1px 1px 1px;
-moz-box-shadow: #666 1px 1px 1px;
}

.no-boxshadow #MyContainer {
border: 2px solid black;
}

如果浏览器支持 box-shadows 的话,将会为 <html> 元素增加 boxshadow 这个 CSS 类,否则的话就使用 no-boxshadow 这个类。这样假设浏览器不支持 box-shadow 的话,我们可以使用其他的样式来进行定义。

另外我们也可以使用 Modernizr 的对象来操作这个行为,例如下面的代码用来检测浏览器是否支持 Canvas 和 本地存储:

 
代码如下:
$(document).ready(function () {

if (Modernizr.canvas) {
//Add canvas code
}

if (Modernizr.localstorage) {
//Add local storage code
}

});

全局的 Modernizr 对象同样可用于测试 CSS3 特性是否支持:
 
代码如下:
$(document).ready(function () {

if (Modernizr.borderradius) {
$('#MyDiv').addClass('borderRadiusStyle');
}

if (Modernizr.csstransforms) {
$('#MyDiv').addClass('transformsStyle');
}

});

使用Modernizr加载脚本

在出现了浏览器不支持某些功能的的情况下,你不仅可以提供一个不错的备用方案,还可以加载shim/polyfill脚本在适当情况下填补缺失的功能 (想了解更多关于shims/polyfills的信息,请查看 ). Modernizr拥有一个内置的脚本加载器,可以用来测试一个功能,并在功能无效的时候加载另一个脚本. 脚本加载器是内置在Modernizr中的,并且是有效的独立yepnope(. 脚本加载器非常容易上手,它根据特定浏览器功能的可用性,真的会简化加载脚本的过程.

你可以使用Modernizr的load()方法来动态加载脚本,该方法接受定义被测功能的属性(test属性), 如测试成功后要加载的脚本(yep属性), 如测试失败后要加载的脚本(nope属性), 和无论测试成功还是失败都要加载的脚本(both属性). 使用load()及其属性的示例如下:
 
代码如下:
Modernizr.load({
test: Modernizr.canvas,
yep: 'html5CanvasAvailable.js’,
nope: 'excanvas.js’,
both: 'myCustomScript.js'
});

在这个例子中Modernizr在加载脚本时还会测试是否支持canvas功能 . 如果目标浏览器支持HTML5 canvas就会加载html5CanvasAvailable.js脚本及 myCustomScript.js脚本 (在这个例子中使用yep属性有点牵强  – 这只是为了演示load()方法中的属性如何使用 ). 否则的话, 就会加载 excanvas.js这个 polyfill脚本来为IE9之前版本的浏览器添加功能支持 . 一旦excanvas.js被加载,myCustomScript.js也会接着被加载.

由于Modernizr会处理加载脚本, 所以你可以用它来做些别的事情. 比如, 在Google或微软提供的第三方CDN不管用的时候,你可以用Modernizr来加载本地的脚本. Modernizr文档中提供了在CDN挂掉后提供本地jQuery后备过程的示例:
代码会先尝试从Google CND加载jQuery. 一旦脚本下载完成(或者下载失败)就会调用某个方法. 这个方法会检查jQuery对象是否有效,如果无效就加载本地的jQuery脚本. 并在其后加载一个名为needs-jQuery.js的脚本.

最后想说的是,如果你打算开发基于 HTML5 和 CSS3 的 Web 应用的话,那 Modernizr 就是你必不可少的工具,除非,除非你确认你所有客户所使用的浏览器支持你所写的代码。

这篇文章主要介绍了检测浏览器对HTML5和CSS3支持度的方法,使用Modernizr来检测浏览器对HTML5和...

什么是 CSS hack

Hack是针对不同浏览器去写不同的CSS样式,从而让各浏览器能达到一致的渲染效果,那么针对不同的浏览器写不同的CSS CODE的过程就叫做CSS Hack。然后将Hack放在浏览器特定的CSS文件中,让符合条件的浏览器去解析这些代码,符合条件的就解析,不符合的就不解析,从而达到所需要的页面渲染效果。总的一句话来说就是使用CSS Hack将会使你的CSS代码部分失去作用,然后借助条件样式,使用其原CSS代码在一些浏览器解析,而CSS Hack代码在符合条件要求的浏览器中替代原CSS那部分代码。

组织你的代码

现在,也许你迫不及待的想要使用这个工具来将你的代码分为两个分支,使其变得干净一些。“Hey,浏览器,如果你识别 Viewport 单位,就执行这个,否则,执行另外的”。感觉很不错,有条理。

CSS

@supports ( height: 100vh ) { // 支持 viewport height 的样式 } @supports not ( height: 100vh ) { // 对于旧浏览器的替代样式 } // 我们希望是好的,但这是一段烂代码

1
2
3
4
5
6
7
@supports ( height: 100vh ) {
    // 支持 viewport height 的样式
}
@supports not ( height: 100vh ) {
    // 对于旧浏览器的替代样式
}
// 我们希望是好的,但这是一段烂代码

这段代码并不好,至少当前看来是这样的。发现问题了吗?

问题就是,并不是所有的浏览器都支持功能查询,不理解 @supports 的浏览器会直接跳过两段代码,这也许就太糟糕了。

意思就是,除非浏览器百分之百支持功能查询,否则我们就没法使用了吗?当然不是,我们完全可以使用功能查询,而且应该使用功能查询,只要不像上面那样写代码就行。

那么,怎么做才对呢?其实与使用媒体查询类似,我们在浏览器完全支持媒体查询之前就开始使用了不是吗?事实上,功能查询使用起来比媒体查询更简单,只要脑子放聪明一点就行了。

你想要让你的代码知道浏览器是否支持功能查询或者正在测试的某个功能,我来告诉你怎么做。

当然,在未来,浏览器 100% 支持功能查询的时候,我们可以大量使用 @supports not 来组织我们的代码。

CSS @supports

传统的 CSS 特性检测都是通过 javascript 实现的,但是未来,原生 CSS 即可实现。

CSS @supports 通过 CSS 语法来实现特性检测,并在内部 CSS 区块中写入如果特性检测通过希望实现的 CSS 语句。

谈一谈浏览器兼容的思路

主要从三个方面去考虑:
要不要去做?主要从产品的角度和成本的角度去考虑;产品的角度来说我们要考虑清楚产品的使用群体,以及受众的浏览器比例,从中分析我们需要效果优先还是功能优先。从成本的角度分析,就是我们做某个功能值不值得,有没有必要,付出和收获是否不成比例。
如果做,做到什么程度?具体到需要让那些浏览器支持哪些效果,在不同的浏览器侧重点也不同。例如:渐进增强和优雅处理。渐进增强是指针对低版本浏览器进行页面构建,保证最基本的功能,在这基础上补充一些高级浏览器的效果,功能,交互;优雅降级:针对高级浏览器,构建完整的功能,再针对低版本的浏览器去做一些兼容。
如何去做?根据兼容的需求选择不同的技术或框架(比如jQuery)Bootstrap;jQuery 1.~(>=ie6),jQuery 2.~(>=ie9);Vue(>=ie9)等
根据兼容需求选择兼容工具(html5shiv.js , respond.js , css.reset , normalize.css , Modernizr)postCSS条件注释 CSS Hack js能力检测做一些修补。

功能查询的支持情况

所以,@supports 现在支持度什么样了呢?

自从 2013 年中,@supports 就能够在 Firefox,Chrome 和 Opera 中使用了。在 Edge 的各个版本中也受支持。Safari 在 2015 年秋季才实现这个功能。具体的支持情况,请看下面这张图:

图片 6

你可能会觉得 IE 不支持此功能会是一个大问题,但是,其实不是这样的。待会儿就会告诉你原因。我相信,最大的一个障碍是 Safari 8,我们需要留意在这个浏览器上发生的事情。

让我们来看另外一个例子。假设我们有些布局代码,为了正常运行,需要使用 object-fit: cover;。对于不支持这个属性的浏览器,我们想要使用不同的样式。

图片 7

所以,我们可以这样写:

CSS

@supports (initial-letter: 4) or (-webkit-initial-letter: 4) { p::first-letter { -webkit-initial-letter: 4; initial-letter: 4; color: #FE742F; font-weight: bold; margin-right: 0.5em; } } div { width: 300px; background: yellow; } @supports (object-fit: cover) { img { object-fit: cover; } div { width: auto; background: green; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@supports (initial-letter: 4) or (-webkit-initial-letter: 4) {
    p::first-letter {
        -webkit-initial-letter: 4;
        initial-letter: 4;
        color: #FE742F;
        font-weight: bold;
        margin-right: 0.5em;
    }
}
 
div {
    width: 300px;
    background: yellow;
}
@supports (object-fit: cover) {
    img {
        object-fit: cover;
    }
    div {
        width: auto;
        background: green;
    }
}

会发生什么呢?@supports 有支持或者不支持的情况,object-fit 也有支持或者不支持的情况,所以,就有了四种可能性:

功能查询支持情况 属性(或者值)支持情况 会发生什么 是否我们想要的
支持 不支持 CSS 将会被应用
支持 不支持 CSS 不会被应用
不支持 支持 CSS 不会被应用
不支持 不支持 CSS 不会被应用

语法:

CSS

@supports <supports_condition> { /* specific rules */ }

1
2
3
@supports <supports_condition> {
    /* specific rules */
}

举个例子:

Sass

{ position: fixed; } @supports (position:sticky) { div { position:sticky; } }

1
2
3
4
5
6
7
8
9
{
    position: fixed;
}
@supports (position:sticky) {
    div {
        position:sticky;
    }
}

上面的例子中,position: sticky 是 position 的一个新属性,用于实现黏性布局,可以轻松实现一些以往需要 javascript 才能实现的布局(戳我了解详情),但是目前只有在 -webkit- 内核下才得到支持。

上面的写法,首先定义了 div 的 position: fixed ,紧接着下面一句 @supports (position:sticky) 则是特性检测括号内的内容,如果当前浏览器支持 @supports 语法,并且支持 position:sticky 语法,那么 div 的 则会被设置为 position:sticky 。

我们可以看到,@supports 语法的核心就在于这一句:@supports (...) { } ,括号内是一个 CSS 表达式,如果浏览器判断括号内的表达式合法,那么接下来就会去渲染括号内的 CSS 表达式。除了这种最常规的用法,还可以配合其他几个关键字:

列举5种以上浏览器兼容的写法

条件注释:

<!--[if IE 6]> <p>You are using Internet Explorer 6.</p> <![endif]-->
<!--[if !IE]><!--> <script>alert(1);</script> <!--<![endif]-->
 <!--[if IE 8]> <link href="ie8only.css" rel="stylesheet"> <![endif]-->

! [if !IE] 非IE

lt [if lt IE 5.5] 小于IE 5.5

lte [if lte IE 6]小于等于IE6

gt [if gt IE 5]大于 IE5

gte [if gte IE 7]大于等于IE7

| [if (IE 6)|(IE 7)]IE6或者IE7

最佳实践

所以,我们应该怎么写功能查询的代码呢?像下面这样:

CSS

// fallback code for older browsers @supports ( display: grid ) { // code for newer browsers // including overrides of the code above, if needed }

1
2
3
4
5
6
// fallback code for older browsers
 
@supports ( display: grid ) {
    // code for newer browsers
    // including overrides of the code above, if needed
}

译者注:本文的主要内容是介绍功能查询和 @supports 的使用方法,所以,某些代码可能是无法运行的,希望读者们注意。同时,由于原文中的一些内容显得比较冗余,所以部分内容并没有翻译。如果需要了解详细内容,请查看原文。

1 赞 1 收藏 评论

图片 8

@supports not && @supports and && @supports or

CSS Hack

CSS Hack大致有3种表现形式,CSS属性前缀法、选择器前缀法以及IE条件注释法(即HTML头部引用if IE)Hack,实际项目中CSS Hack大部分是针对IE浏览器不同版本之间的表现差异而引入的。常见的Hack写法:

.box{
//属性前缀法 
color: red; _color: blue; /*ie6*/ *color: pink; /*ie67*/ color: yellow9; /*ie/edge 6-8*/}

//选择器前缀法
.ie7 .clearfix{ zoom: 1;}

//IE条件注释法
<!–-[if IE 7]><link rel="stylesheet" href="ie7.css" type="text/css" /><![endif]–->

<!DOCTYPE html>
<!--[if IEMobile 7 ]> <html dir="ltr" lang="en-US"class="no-js iem7"> <![endif]-->
<!--[if lt IE 7 ]> <html dir="ltr" lang="en-US" class="no-js ie6 oldie"> <![endif]-->
<!--[if IE 7 ]> <html dir="ltr" lang="en-US" class="no-js ie7 oldie"> <![endif]-->
<!--[if IE 8 ]> <html dir="ltr" lang="en-US" class="no-js ie8 oldie"> <![endif]-->
<!--[if (gte IE 9)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html dir="ltr" lang="en-US" class="no-js"><!--<![endif]-->

@supports not — 非

not 操作符可以放在任何表达式的前面来产生一个新的表达式,新的表达式为原表达式的值的否定。看个例子:

Sass

@supports not (background: linear-gradient(90deg, red, yellow)) { div { background: red; } }

1
2
3
4
5
@supports not (background: linear-gradient(90deg, red, yellow)) {
    div {
        background: red;
    }
}

因为添加了 not 关键字,所以与上面第一个例子相反,这里如果检测到浏览器不支持线性渐变 background: linear-gradient(90deg, red, yellow) 的语法,则将 div 的颜色设置为红色 background: red 。

h3>@supports and — 与

这个也好理解,多重判断,类似 javascript 的 && 运算符符。用 and 操作符连接两个原始的表达式。只有两个原始表达式的值都为真,生成的表达式才为真,反之为假。

当然,and 可以连接任意多个表达式看个例子:

Sass

p { overflow: hidden; text-overflow: ellipsis; } @supports (display:-webkit-box) and (-webkit-line-clamp:2) and (-webkit-box-orient:vertical) { p { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } }

1
2
3
4
5
6
7
8
9
10
11
p {
    overflow: hidden;
    text-overflow: ellipsis;
}
@supports (display:-webkit-box) and (-webkit-line-clamp:2) and (-webkit-box-orient:vertical) {
    p {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
    }
}

上面同时,检测 @supports (display:-webkit-box) and (-webkit-line-clamp:2) and (-webkit-box-orient:vertical) 了三个语法,如果同时支持,则设定三个 CSS 规则。这三个语法必须同时得到浏览器的支持,如果表达式为真,则可以用于实现多行省略效果:

Demo戳我

See the Pen @supportAnd by Chokcoco (@Chokcoco) on CodePen.

属性兼容问题

常见的属性兼容情况如下:
inline-block: >=ie8
min-width/min-height: >=ie8
:before,:after: >=ie8
div:hover: >=ie7
inline-block: >=ie8
background-size: >=ie9
圆角: >= ie9
阴影: >= ie9
动画/渐变: >= ie10
常见处理范例如下:
.clearfix:after{content: '';display: block;clear: both;}.clearfix{zoom: 1; / 仅对ie67有效 /}
.target{display: inline-block;
display: inline;*zoom: 1;}

@supports or — 或

理解了 @supports and,就很好理解 @supports or 了,与 javascript 的 || 运算符类似,表达式中只要有一个为真,则生成表达式表达式为真。看例子:

Sass

@supports (background:-webkit-linear-gradient(0deg, yellow, red)) or (background:linear-gradient(90deg, yellow, red)){ div { background:-webkit-linear-gradient(0deg, yellow, red); background:linear-gradient(90deg, yellow, red) } }

1
2
3
4
5
6
@supports (background:-webkit-linear-gradient(0deg, yellow, red)) or (background:linear-gradient(90deg, yellow, red)){
    div {
        background:-webkit-linear-gradient(0deg, yellow, red);
        background:linear-gradient(90deg, yellow, red)
    }
}

上面的例子中,只有检测到浏览器支持 background:-webkit-linear-gradient(0deg, yellow, red) 或者(or) background:linear-gradient(90deg, yellow, red) 其中一个,则给 div 元素添加渐变。

Demo戳我

See the Pen @supports or by Chokcoco (@Chokcoco) on CodePen.

当然,关键字 not 还可以和 and 或者 or 混合使用。感兴趣的可以尝试一下。

以下工具/名词是做什么的

Can i use?

兼容性来看,先看看 Can i use 吧:

图片 9

这仍是一个实验中的功能,虽然大部分浏览器都已经支持了,但是目前看来,即是在移动端想要全部兼容仍需要等待一段时间。

但是我们已经可以开始使用起来了,使用 @supports 实现渐进增强的效果。

渐进增强(progressive enhancement):针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验:

条件注释

条件注释 (conditional comment) 是于HTML源码中被IE有条件解释的语句。条件注释可被用来向IE提供及隐藏代码。(IE10不再支持条件注释)。

CSS.supports()

谈到了 @supports,就有必要再说说 CSS.supports() 。

它是作为 @supports 的另一种形式出现的,我们可以使用 javascript 的方式来获得 CSS 属性的支持情况。

可以打开控制台,输入 CSS.supports 试试:

图片 10

如果没有自己实现 CSS.supports 这个方法,输出上述信息,表示浏览器是支持 @supports 语法的,使用如下:

JavaScript

CSS.supports('display', 'flex') // true CSS.supports('position', 'sticky') // true

1
2
CSS.supports('display', 'flex')  // true
CSS.supports('position', 'sticky')  // true

图片 11

那它有什么用呢?如果你的页面需要动态添加一些你不确定哪些浏览器支持的新的属性,那它也许会派上用场。以及,它可以配合我们下文即将要讲的 modernizr 。

IE Hack

专门准对IE浏览器不同版本间的兼容性问题的处理,使之能够渲染出想要的效果。

modernizr

上面介绍了 CSS 方式的特性检测,在以前,通常是使用 javascript 来进行特性检测的,其中 modernizr 就是其中最为出色的佼佼者。

modernizr(戳我查看 Github )是一个开源的 javascript 库。有着将近 2W 的 star ,其优秀程度可见一斑。

简单看看使用方法,假设页面已经引用了 modernizr ,语法如下:

JavaScript

// Listen to a test, give it a callback Modernizr.on('testname', function( result ) { if (result) { console.log('The test passed!'); } else { console.log('The test failed!'); } }); // 或者是类似 CSS.supports() Modernizr.testAllProps('background', 'linear-gradient(90deg, #888, #ccc)'); // true

1
2
3
4
5
6
7
8
9
10
11
12
// Listen to a test, give it a callback
Modernizr.on('testname', function( result ) {
  if (result) {
    console.log('The test passed!');
  }
  else {
    console.log('The test failed!');
  }
});
// 或者是类似 CSS.supports()
Modernizr.testAllProps('background', 'linear-gradient(90deg, #888, #ccc)');  // true

举个实际的例子,假设我们希望对是否支持渐变这个样式浏览器下的一个 div 区别对待,有如下 CSS:

CSS

div { background: #aaa; } .linear-gradient div{ background: linear-gradient(90deg, #888, #ccc); }

1
2
3
4
5
6
7
div {
    background: #aaa;
}
.linear-gradient div{
    background: linear-gradient(90deg, #888, #ccc);
}

使用 Modernizr 进行判断,如果支持渐变,则在根元素添加一个 .linear-gradient 样式,方便示例,使用了 jquery 语法:

JavaScript

if (Modernizr.testAllProps('background', 'linear-gradient(90deg, #888, #ccc)')) { $('html').addClass('linear-gradient'); }

1
2
3
if (Modernizr.testAllProps('background', 'linear-gradient(90deg, #888, #ccc)')) {
    $('html').addClass('linear-gradient');
}

Demo戳我

See the Pen modernizr by Chokcoco (@Chokcoco) on CodePen.

当然,Modernizr 还有很多其他的功能,可以去翻翻它的 API 。

js 能力检测

是指js中兼容性问题的一些封装。通过js封装函数或对象来解决浏览器的兼容问题。

特性检测原理

如果嫌引入整一个 Modernizr 库太大,页面又不支持 @supports ,其实我们自己用简单的 javascript 实现也非常方便简单。

想要知道浏览器支持多少 CSS 属性,可以在调试窗口试试:

JavaScript

var root = document.documentElement; //HTML for(var key in root.style) { console.log(key); }

1
2
3
4
5
var root = document.documentElement; //HTML
for(var key in root.style) {
    console.log(key);
}

图片 12

上面图片截取的只是打印出来的一小部分。如果我们要检测某个属性样式是否被支持,在任意的 element.style 检测它是否存在即可,即上面代码示例的 root 可以替换成任意元素。

当然,元素可能有 background 属性,但是不支持具体的 linear-gradinet() 属性值。这个时候该如何检测呢?只需要将具体的值赋值给某一元素,再查询这个属性值能否被读取。

JavaScript

var root = document.documentElement; root.style.backgroundImage = 'linear-gradient(90deg, #888, #ccc)'; if(root.style.backgroundImage) { // 支持 } else { // 不支持 }

1
2
3
4
5
6
7
8
9
var root = document.documentElement;
root.style.backgroundImage = 'linear-gradient(90deg, #888, #ccc)';
if(root.style.backgroundImage) {
  // 支持
} else {
  // 不支持
}

所以上面 Modernizr 的例子里,javascript 代码可以改成:

JavaScript

var root = document.documentElement; root.style.backgroundImage = 'linear-gradient(90deg, #888, #ccc)'; if(root.style.backgroundImage) { $('html').addClass('linear-gradient'); }

1
2
3
4
5
6
var root = document.documentElement;
root.style.backgroundImage = 'linear-gradient(90deg, #888, #ccc)';
if(root.style.backgroundImage) {
  $('html').addClass('linear-gradient');
}

当然,做这种特定属性值判断的时候由于有个 CSS 赋值操作,所以我们选取用于判断的元素应该是一个隐藏在页面上的元素。

html5shiv.js

用于解决IE9以下版本浏览器对HTML5新增标签不识别,并导致CSS不起作用的问题。使用Javascript来使不支持HTML5的浏览器支持HTML标签。利用脚本document.createElement(“”)创建对应的脚本,CSS选择器便可正确应用到该标签。

各种方式间的优劣

  • 原生的 @supports 的性能肯定是最好的,而且无需引入外部 javascript ,首推这个,但是无奈兼容问题,目前来看不是最好的选择。
  • Modernizr 功能强大,兼容性好,但是需要引入外部 javascript,多一个 http 请求,如果只是进行几个特性检测,有点杀鸡用牛刀的感觉。
  • 针对需要的特性检测,使用 javascript 实现一个简单的函数,再把上面用到的方法封装一下:

JavaScript

/** * 用于简单的 CSS 特性检测 * @param [String] property 需要检测的 CSS 属性名 * @param [String] value 样式的具体属性值 * @return [Boolean] 是否通过检查 */ function cssTest(property, value) { // 用于测试的元素,隐藏在页面上 var ele = document.getElementById('test-display-none'); // 只有一个参数的情况 if(arguments.length === 1) { if(property in ele.style) { return true; } // 两个参数的情况 }else if(arguments.length === 2){ ele.style[property] = value; if(ele.style[property]) { return true; } } return false; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 用于简单的 CSS 特性检测
* @param [String] property 需要检测的 CSS 属性名
* @param [String] value 样式的具体属性值
* @return [Boolean] 是否通过检查
*/
function cssTest(property, value) {
    // 用于测试的元素,隐藏在页面上
    var ele = document.getElementById('test-display-none');
    // 只有一个参数的情况
    if(arguments.length === 1) {
        if(property in ele.style) {
            return true;
        }
    // 两个参数的情况
    }else if(arguments.length === 2){
        ele.style[property] = value;
        if(ele.style[property]) {
            return true;
        }
    }
    return false;
}

简单测试一下:

图片 13

软件工程没有银弹,所以无论哪种方式,都有适合的场景,我们要做的就是掌握了解它们的原理,根据不同的场景灵活运用即可。

系列 CSS 文章汇总在我的 Github 。

到此本文结束,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

打赏支持我写出更多好文章,谢谢!

打赏作者

respond.js

Respond.js 是一个快速、轻量的 polyfill,用于为 IE6-8 以及其它不支持 CSS3 Media Queries 的浏览器提供媒体查询的 min-width 和 max-width 特性,实现响应式网页设计。(Responsive Web Design)

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

图片 14 图片 15

2 赞 收藏 评论

css reset

HTML标签在浏览器中都有默认的样式,例如p标签有上下边距,strong标签有字体加粗样式等。不同浏览器的默认样式之间存在差别,例如ul默认带有缩进样式,在IE下,它的缩进是由margin实现的,而在Firefox下却是由padding实现的。开发时浏览器的默认样式可能会给我们带来多浏览器兼容问题,影响开发效率。解决方法其中之一是开始就将浏览器的默认样式全部覆盖掉,这就是CSS reset。

关于作者:chokcoco

图片 16

经不住流年似水,逃不过此间少年。 个人主页 · 我的文章 · 63 ·    

图片 17

normalize.css

Normalize.css 是一个可以定制的CSS文件,它让不同的浏览器在渲染网页元素的时候形式更统一。它可以保留有用的默认值,不同于许多 CSS 的重置,其标准化的样式,适用范围广的元素。纠正错误和常见的浏览器的不一致性。一些细微的改进,提高了易用性。使用详细的注释来解释代码。

Modernizr

Modernizr是一个检测用户浏览器HTML5和CSS3能力的JavaScript库。Modernizr在页面加载时快速运行来检测功能;之后它会创建一个保存检测结果的JavaScript对象,然后为你页面中的html标签上添加一系列class属性来接通你的CSS。Modernizr支持大量的测试和可选地包括YepNope.js来视情况加载外部的js和css资源。

postCSS

PostCSS 是使用 JS 插件来转换 CSS 的工具,支持变量,混入,未来 CSS 语法,内联图像等等。PostCSS是CSS变成JavaScript的数据,使它变成可操作。PostCSS是基于JavaScript插件,然后执行代码操作。PostCSS自身并不会改变CSS,它只是一种插件,为执行任何的转变铺平道路。

一般在哪个网站查询属性兼容性?

http://caniuse.com/

本文由9159.com发布于前端,转载请注明出处:使用其原CSS代码在一些浏览器解析,未经作者许

关键词:

上一篇:没有了
下一篇:设计模式(Design