聊聊 CSS 选择器

聊聊 CSS 选择器

firefox 开发者工具有一个很酷的功能:在查看器中右键单击某元素,选择“复制唯一选择器”,刻意复制定位至该元素的唯一选择器。这跟 CSS 选择器的功能恰好相反,可以视作 document.querySelector 的逆运算。

这个功能 firefox 怎么实现的呢? grep 源码,追踪到 browser/devtools/inspector/inspector-panel.js 文件中下列代码:

/**
 * Copy a unique selector of the selected Node to the clipboard.
 */
function InspectorPanel_copyUniqueSelector() {
    if (!this.selection.isNode()) {
        return;
    }

    let toCopy = CssLogic.findCssSelector(this.selection.node);
    if (toCopy) {
        clipboardHelper.copyString(toCopy);
    }
}

根据 CssLogic 又跟踪到 toolkit/devtools/styleinspector/css-logic.js 文件:

/**
 * Find a unique CSS selector for a given element
 * @returns a string such that ele.ownerDocument.querySelector(reply) === ele
 * and ele.ownerDocument.querySelectorAll(reply).length === 1
 */
CssLogic.findCssSelector = function CssLogic_findCssSelector(ele) {
  ele = LayoutHelpers.getRootBindingParent(ele);
  var document = ele.ownerDocument;
  if (!document || !document.contains(ele)) {
    throw new Error('findCssSelector received element not inside document');
  }

  // document.querySelectorAll("#id") returns multiple if elements share an ID
  if (ele.id && document.querySelectorAll('#' + CSS.escape(ele.id)).length === 1) {
    return '#' + CSS.escape(ele.id);
  }

  // Inherently unique by tag name
  var tagName = ele.localName;
  if (tagName === 'html') {
    return 'html';
  }
  if (tagName === 'head') {
    return 'head';
  }
  if (tagName === 'body') {
    return 'body';
  }

  // We might be able to find a unique class name
  var selector, index, matches;
  if (ele.classList.length > 0) {
    for (var i = 0; i < ele.classList.length; i++) {
      // Is this className unique by itself?
      selector = '.' + CSS.escape(ele.classList.item(i));
      matches = document.querySelectorAll(selector);
      if (matches.length === 1) {
        return selector;
      }
      // Maybe it's unique with a tag name?
      selector = tagName + selector;
      matches = document.querySelectorAll(selector);
      if (matches.length === 1) {
        return selector;
      }
      // Maybe it's unique using a tag name and nth-child
      index = positionInNodeList(ele, ele.parentNode.children) + 1;
      selector = selector + ':nth-child(' + index + ')';
      matches = document.querySelectorAll(selector);
      if (matches.length === 1) {
        return selector;
      }
    }
  }

  // Not unique enough yet.  As long as it's not a child of the document,
  // continue recursing up until it is unique enough.
  if (ele.parentNode !== document) {
    index = positionInNodeList(ele, ele.parentNode.children) + 1;
    selector = CssLogic_findCssSelector(ele.parentNode) + ' > ' +
            tagName + ':nth-child(' + index + ')';
  }

  return selector;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值