使用 jQuery 检查元素是否处于正常流程中的最优雅的方法是什么?
根据CSS3 规范,
如果满足以下条件,则框属于流:
其 'display' 的使用值为 'block', 'list-item', 'table' 或template。
它的'float'的使用值为'none'。
其“位置”的使用值是“静态”或“相对”。
它要么是流根的子节点,要么是属于流的框的子节点。
我应该检查所有这些条件,还是有更好的方法?
使用 jQuery 检查元素是否处于正常流程中的最优雅的方法是什么?
根据CSS3 规范,
如果满足以下条件,则框属于流:
其 'display' 的使用值为 'block', 'list-item', 'table' 或template。
它的'float'的使用值为'none'。
其“位置”的使用值是“静态”或“相对”。
它要么是流根的子节点,要么是属于流的框的子节点。
我应该检查所有这些条件,还是有更好的方法?
我怀疑有更好的方法,但另一种方法是:
1)用包装器包围元素
2) 将包装器的高度和宽度与被包装的元素进行比较
例如:
$('#elementToTest').clone().addClass('clone').wrap('<div></div>')
if($('#elementToTest.clone').height()>$('#elementToTest.clone').parent().height()){
//outside the normal flow
}
我认为另一个“流动”要求是overflow
设置为visible
.
浮动、绝对定位的元素、不是块框的块容器(例如内联块、表格单元格和表格标题),以及具有“溢出”而不是“可见”的块框(除非该值已被传播到视口)为其内容建立新的块格式化上下文。
根据您引用的要求和overflow
要求,这是使用 jquery 执行此操作的一种方法:
function isInFlow(elm, ctxRoot) {
ctxRoot = ctxRoot || document.body;
var $elm = $(elm),
ch = -1,
h;
if (!$elm.length) {
return false;
}
while ($elm[0] !== document.body) {
h = $elm.height();
if (h < ch || !okProps($elm)) {
return false;
}
ch = h;
$elm = $elm.parent();
if (!$elm.length) {
// not attached to the DOM
return false;
}
if ($elm[0] === ctxRoot) {
// encountered the ctxRoot and has been
// inflow the whole time
return true;
}
}
// should only get here if elm
// is not a child of ctxRoot
return false;
}
function okProps($elm) {
if ($elm.css('float') !== 'none'){
return false;
}
if ($elm.css('overflow') !== 'visible'){
return false;
}
switch ($elm.css('position')) {
case 'static':
case 'relative':
break;
default:
return false;
}
switch ($elm.css('display')) {
case 'block':
case 'list-item':
case 'table':
return true;
}
return false;
}
有关测试用例,请参阅此jsFiddle。
我不确定它是否会更好使用window.getComputedStyle()
。
该函数正在检查是否elm
在ctxRoot
的流或块格式化上下文中(我认为它以前被称为)。如果ctxRoot
未提供,它将检查body
元素。这不会检查以确保ctxRoot
正在流动。所以,有了这个 HTML
<div id="b" style="overflow: hidden;">
<div id="ba">ba
<p id="baa">baa</p>
<span id="bab">bab</span>
<span id="bac" style="display:block;">bac</span>
</div>
</div>
测试用例是:
var b = $('#b')[0];
console.log('no ',isInFlow(b));
console.log('no ',isInFlow('#ba'));
console.log('yes ',isInFlow('#ba', b));
console.log('no ',isInFlow('#baa'));
console.log('yes ',isInFlow('#baa', b));
console.log('no ',isInFlow('#bab'));
console.log('no ',isInFlow('#bab', b));
console.log('no ',isInFlow('#bac'));
console.log('yes ',isInFlow('#bac', b));
您可以通过使用数据注释来预先消除对它的需求,而不是追溯地查看它。任何时候创建或定义元素时,将其属性设置data-flow
为 true 或 false。
例如:
var newDiv = document.createElement("div");
newDiv.style.position = "absolute";
newDiv.setAttribute("data-flow","false");
或者在 html 中
<div style="position:absolute;" data-flow="false"></div>
然后您可以使用选择器简单地选择这些元素:
$('*[data-flow=false]')