动态检测浏览器是否支持 position:sticky 属性

7

有没有一种方法可以使用Javascript或jQuery检测浏览器是否支持position:sticky

我知道大多数现代浏览器都支持,但一些旧的浏览器和一些移动浏览器不支持。

我不想使用polyfill。如果position:sticky有效,则只执行某些操作,否则保持原样。

2个回答

14

检查CSS功能是否可用的一种强大方法是使用CSS.supports JavaScript函数:

if (CSS && CSS.supports && CSS.supports("position", "sticky")) {
  // awesome: position:sticky is supported on this browser!
} else {
  // fallback: I cannot rely on position:sticky!
}

我希望这回答了您的问题,但我认为值得一提的是,如果您想使用 CSS.supports(),您应该至少考虑仅仅使用 CSS 来响应缺少的特性。虽然 JavaScript 是使页面动态变化的好方法,但通常并不需要它来使您的页面响应缺少的特性。特别是对于像 sticky 这样的 CSS 特性。
例如:
/* 
  ...
  Basic styles for old browsers that don't support sticky go here.
  ... 
 */

@supports (position:sticky) { 
  /* Overrides to the above styles for modern "sticky" browsers go here */
}

即使如此,你通常甚至不需要这么高级。例如,假设你有一个导航栏,希望它尽可能地使用position:sticky,但如果不行,就使用position:absolute。即使有些浏览器不理解sticky,你也可以这样说:

.my-nav-bar {
  
  /* The fallback goes first */
  position: absolute; 

  /* This 'enhancement' is ignored if not understood, */
  /* but overrides the previous value if the browser supports it. */
  position: sticky; 

  top: 50px;
  /* ... etc ... */
}

3
如果不支持CSS和CSS.supports,但支持position:sticky呢? - clami219
<html> <head> </head> <body> </body> <script> alert("ok"); if(CSS.supports("position:sticky")) { document.body.style.backgroundColor = "red"; } </script> </html> - LDS
1
@clami219 关于支持的问题,非常好的提问!根据 caniuse.com 的数据,目前 CSS.supports 有大约95%的支持率,而 position:sticky 则有大约92%的支持率。除了 Safari(包括 iOS)之外,所有浏览器中 sticky 的引入都是在 supports 之后,因此我通常不会犹豫使用这种技术。 - aaaidan
1
我发现在被接受的答案错误地报告支持的情况下,这种方法可以正常工作。我赞成将其作为被接受的答案。 - Jimbo Jonny

2

来自 modernizr:

/*!
{
  "name": "CSS position: sticky",
  "property": "csspositionsticky",
  "tags": ["css"],
  "builderAliases": ["css_positionsticky"],
  "notes": [{
    "name": "Chrome bug report",
    "href":"https://bugs.chromium.org/p/chromium/issues/detail?id=322972"
  }],
  "warnings": ["using position:sticky on anything but top aligned elements is buggy in Chrome < 37 and iOS <=7+"]
}
!*/
define(['Modernizr', 'createElement', 'prefixes'], function(Modernizr, createElement, prefixes) {
  // Sticky positioning - constrains an element to be positioned inside the
  // intersection of its container box, and the viewport.
  Modernizr.addTest('csspositionsticky', function() {
    var prop = 'position:';
    var value = 'sticky';
    var el = createElement('a');
    var mStyle = el.style;

    mStyle.cssText = prop + prefixes.join(value + ';' + prop).slice(0, -prop.length);

    return mStyle.position.indexOf(value) !== -1;
  });
});

来源:https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/positionsticky.js

使用:

prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');

来源:https://github.com/Modernizr/Modernizr/blob/master/src/prefixes.js

工作示例(不需要Modernizr依赖):

function browserSupportsPositionSticky() {
  var prop = 'position:';
  var value = 'sticky';
  var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');

  var el = document.createElement('a');
  var mStyle = el.style;
  mStyle.cssText = prop + prefixes.join(value + ';' + prop).slice(0, - prop.length);
  
  return mStyle.position.indexOf(value) !== -1;
};

console.log(browserSupportsPositionSticky());


解决方案很有趣!原则是好的,但它现在不能直接使用...显然这是一个Modernizr的一部分。将其作为独立的JS函数会是理想的。 - clami219
只需从.addTest()调用中提取测试用例 o.O - Andreas
我尝试过了。不清楚前缀对象从哪里来。 - clami219
https://github.com/Modernizr/Modernizr/blob/master/src/prefixes.js - Andreas
我刚在一台版本为iPad Safari的设备上测试了"browserSupportsPositionSticky",其中检查器不适用于position: sticky(无论是否有前缀),并且在开发工具中将其称为位置的无效值,但是这个函数返回它被支持。这是我测试过的唯一一个不支持sticky的浏览器,因此我怀疑它不是唯一一个无法检测到缺乏sticky支持的浏览器。 - Jimbo Jonny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接