Element から CSS Selector を取得する
コード
getCSSSelector.js/**
* Element から CSS Selector を取得する
* @author toshi (https://github.com/k08045kk)
* @license MIT License | https://opensource.org/licenses/MIT
* @version 1
* @since 1 - 20230211 - 初版
* @see https://www.bugbugnow.net/2023/02/get-css-selector.html
* @see https://gist.github.com/k08045kk/d239bec86ae9b06c438e7e2bf67575fb
* @param {Element} element - 要素
* @return {string} - CSS Selector
*/
var getCSSSelector = function(element) {
if (!(element && element instanceof Node)
|| !(element.nodeType === Node.ELEMENT_NODE || (element=element.parentElement))) {
return 'unknown';
}
var array = [];
for (; element; element=element.parentElement) {
if (element.id) {
// #id
array.unshift('#'+element.id)
break;
} else {
// tagName.className:nth-of-type(n)
var tagName = element.tagName;
var text = tagName.toLowerCase();
var list = element.classList;
var len = list.length;
for (var i=0; i<len; i++) { text += '.'+list[i]; }
var n = 0;
for (var pre=element; (pre=pre.previousElementSibling) && (pre.tagName != tagName || ++n); ) {}
var nth = n+1;
if (!n) {
for (var next=element; (next=next.nextElementSibling) && (next.tagName != tagName || !++n); ) {}
}
if (n) {
text += ':nth-of-type('+nth+')';
}
array.unshift(text);
}
}
return array.join(' > ');
};
getCSSSelector.min.js/*! getCSSSelector.js | MIT License | https://gist.github.com/k08045kk */var getCSSSelector=function(a){if(!(a&&a instanceof Node)||a.nodeType!==Node.ELEMENT_NODE&&!(a=a.parentElement))return"unknown";for(var e=[];a;a=a.parentElement)if(a.id){e.unshift("#"+a.id);break}else{for(var f=a.tagName,g=f.toLowerCase(),b=a.classList,c=b.length,d=0;d<c;d++)g+="."+b[d];b=0;for(c=a;(c=c.previousElementSibling)&&(c.tagName!=f||++b););c=b+1;if(!b)for(d=a;(d=d.nextElementSibling)&&(d.tagName!=f||!++b););b&&(g+=":nth-of-type("+c+")");e.unshift(g)}return e.join(" > ")};
更新履歴
備考
document.querySelector()
で Element
を取得可能な CSS Selector
を取得します。
ただ、上記コードが完全なコードではなく突き詰めれば多彩なバリエーションを作成できます。例えば次のような関数が考えられます。
- 行数最小の関数
- オプションによる高機能関数
.className
を含まない:nth-of-type(n)
を含まない:nth-child(n)
で実装する- 一部の属性を追記する(
<a>
のhref
属性等) - Element 以外の対策除去(Node or null 対策)
- XML モード対応(tagName の大文字小文字対策)
上記コードは、「結果の読みやすさ」と「処理の継続性」を考慮して作成しています。「結果の読みやすさ」を無視できるのであれば、.className
部分を削除できます。同様に「処理の継続性」を無視できるのであれば、Node
やnull
などへの対応部分を削除できます。tagName
の大文字小文字を考慮すれば、XMLモードに対応することもできます。
使用例(Bookmarklet)
ページ上の要素をクリックすると、 コンソールへ CSS Selector を出力します。
getCSSSelector.bookmarklet.jsjavascript:/*! included (getCSSSelector.js | MIT License | gist.github.com/k08045kk) */(function(){window.addEventListener("click",function(h){var k=console,l=k.log,a;if((a=h.target)&&a instanceof Node&&(a.nodeType===Node.ELEMENT_NODE||(a=a.parentElement))){for(var e=[];a;a=a.parentElement)if(a.id){e.unshift("#"+a.id);break}else{for(var f=a.tagName,g=f.toLowerCase(),b=a.classList,c=b.length,d=0;d<c;d++)g+="."+b[d];b=0;for(c=a;(c=c.previousElementSibling)&&(c.tagName!=f||++b););c=b+1;if(!b)for(d=a;(d=d.nextElementSibling)&&(d.tagName!=f||!++b););b&&(g+=":nth-of-type("+c+")");e.unshift(g)}a=e.join(" > ")}else a="unknown";l.call(k,a,h.target)})})();
無圧縮コード
getCSSSelector.bookmarklet.js/*! included (getCSSSelector.js | MIT License | gist.github.com/k08045kk) */
(function () {
var getCSSSelector = function(element) {
if (!(element && element instanceof Node)
|| !(element.nodeType === Node.ELEMENT_NODE || (element=element.parentElement))) {
return 'unknown';
}
var array = [];
for (; element; element=element.parentElement) {
if (element.id) {
// #id
array.unshift('#'+element.id)
break;
} else {
// tagName.className:nth-of-type(n)
var tagName = element.tagName;
var text = tagName.toLowerCase();
var list = element.classList;
var len = list.length;
for (var i=0; i<len; i++) { text += '.'+list[i]; }
var n = 0;
for (var pre=element; (pre=pre.previousElementSibling) && (pre.tagName != tagName || ++n); ) {}
var nth = n+1;
if (!n) {
for (var next=element; (next=next.nextElementSibling) && (next.tagName != tagName || !++n); ) {}
}
if (n) {
text += ':nth-of-type('+nth+')';
}
array.unshift(text);
}
}
return array.join(' > ');
};
window.addEventListener('click', function(event) {
console.log(getCSSSelector(event.target), event.target);
});
})();