function isPositionFixed(element) {
  /**
   * @param {HTMLElement} element
   * @param {'overflowY'|'position'} attr
   * @return {string}
   */
  function getStyleAttrValue(element, attr) {
    // Check style before computedStyle as computedStyle is expensive.
    return element.style[attr] || window.getComputedStyle(element)[attr];
  }

  // Position fixed/sticky has no effect in case when document does not scroll.
  const htmlEl = document.querySelector('html');
  if (!htmlEl) throw new Error('html element not found in document');
  if (htmlEl.scrollHeight <= htmlEl.clientHeight ||
      !['scroll', 'auto', 'visible'].includes(getStyleAttrValue(htmlEl, 'overflowY'))) {
    return false;
  }

  /** @type {HTMLElement | null} */
  let currentEl = element;
  while (currentEl) {
    const position = getStyleAttrValue(currentEl, 'position');
    if ((position === 'fixed' || position === 'sticky')) {
      return true;
    }
    currentEl = currentEl.parentElement;
  }
  return false;
}
This function checks if an element or an ancestor of an element is `position:fixed`.
In addition we ensure that the element is capable of behaving as a `position:fixed`
element, checking that it lives within a scrollable ancestor.
@param {HTMLElement} element
@return {boolean}