Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically detect if position:sticky is supported by the browser

Is there a way to detect, using Javascript or jQuery, whether the browser supports position:sticky or not?

I know most modern browsers support it, but some older browsers and some mobile browsers don't.

I'm not interested in a polyfill. I want to take certain actions only if position:sticky works, otherwise just leave things as they are.

like image 615
clami219 Avatar asked Dec 10 '22 01:12

clami219


2 Answers

A great and powerful way to check if a CSS feature is available is to use the CSS.supports JavaScript function:

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

I hope this answers your question, but I think it's worth mentioning that if you're tempted to use CSS.supports() you should at least consider responding to a lack of feature just using CSS alone. While JavaScript is a great way to make dynamic changes to a page, you often don't need it to have your page respond to a lack of a feature. This is especially for CSS features like sticky.

E.g.

/* 
  ...
  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 */
}

And even then, you often don't even need to go this fancy. For example, let's say you have a nav bar that you would like to be position:sticky if possible, but otherwise just position:absolute. Even though some browsers don't understand sticky, you can say:

.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 ... */
}
like image 61
aaaidan Avatar answered Apr 06 '23 00:04

aaaidan


From 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;
  });
});

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

with:

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

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

Working example (w/o Modernizr dependencies):

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());
like image 20
4 revs, 2 users 88% Avatar answered Apr 06 '23 00:04

4 revs, 2 users 88%