Find all block elements
Question by Ilya Volodin
I need to find all block elements in a given node. Block elements are not just elements that have display:block
in the CSS, but also default block elements like div
and p
.
I know I can just get computed style of the element and check for the display
property, however, my code will execute in a long loop and getting computed styles flushes reflow stack every time, so it will be very expansive.
I’m looking for some trick to do this without getComputedStyle
.
Edit
Here’s my current code that I would like to improve:
var isBlockOrLineBreak = function(node)
{
if (!node) {
return false;
}
var nodeType = node.nodeType;
return nodeType == 1 && (!inlineDisplayRegex.test(getComputedStyleProperty(node, "display")) || node.tagName === "BR")
|| nodeType == 9 || nodeType == 11;
};
Another edit
jQuery’s .css calls getComputedStyle under the hood. So that’s not what I’m looking for.
My solution
Thanks everyone for suggestions. Unfortunately, none of them matched what I was looking for. After a lot of digging through documentation I realized that there’s no real way to do this without getComputedStyle. However, I came up with the code that should avoid getComputedStyle as much as humanly possible. Here’s the code:
$.extend($.expr[':'], {
block: function(a) {
var tagNames = {
"ADDRESS": true,"BLOCKQUOTE": true,"CENTER": true,"DIR": true,"DIV": true,
"DL": true,"FIELDSET": true,"FORM": true,"H1": true,"H2": true,"H3": true,
"H4": true,"H5": true,"H6": true,"HR": true,"ISINDEX": true,"MENU": true,
"NOFRAMES": true,"NOSCRIPT": true,"OL": true,"P": true,"PRE": true,"TABLE": true,
"UL": true,"DD": true,"DT": true,"FRAMESET": true,"LI": true,"TBODY": true,
"TD": true,"TFOOT": true,"TH": true,"THEAD": true,"TR": true
};
return $(a).is(function() {
if (tagNames[this.tagName.toUpperCase()]) {
if (this.style.display === "block")
{
return true;
}
if (this.style.display !== "" || this.style.float !== "")
{
return false;
}
else {
return $(this).css("display") === "block";
}
}
else {
if (this.style.display === "block") {
return
}
else {
return $(this).css("display") === "block";
}
}
});
}
});
Usage of this code is very simple just do $(“:block”) or $(“form :block”). This will avoid using .css property in a lot of cases, and only fallback to it as a last resort.
Starx’s answer was what gave me the idea to do this, so I’m going to mark his message as an answer.
Answer by Starx
The best way I see is to
- assign a common class to all the
not-native
block element and - using jQuery’s
mulitple-selector
.
Then we can do it as simple as this this
CSS:
.block { display: block; }
jQuery:
var blockelements = $("div, p, table, ..., .block");
// ^ represents other block tags
If you want to include all the block elements. Here is a link