使用Mootools Element.Dimensions我可以获得任何元素的计算大小(以像素为单位)。但是,我无法确定元素是否已使用像素值或百分比值进行调整(除了具有内联样式的特殊情况)。
这样做有明智的方法吗?我能想到的唯一解决方案(它太可靠了,几乎不值得这个名字)是遍历文档样式表,寻找与目标元素匹配的选择器,然后查看目标属性的声明样式。
背景
我正在尝试用CKEditor个实例替换某个类的所有textareas。理想情况下,100%宽度的textareas将被类似样式的编辑器实例替换 - 因此它们可以在窗口调整大小上缩放 - 而固定大小的textareas将被固定大小的编辑器替换。
是的,我可以给他们一个不同的类(如果没有很好的解决方案,我会这样做),但理想情况下我希望能够放入我的CKEditor脚本并让一切正常工作而无需调整HTML。
答案 0 :(得分:4)
可以做到。看看这个问题(Why does getComputedStyle return 'auto' for pixels values right after element creation?)给了我们一些提示。
如果您将元素的样式设置为display = none,然后调用getComputedStyle,您将获得计算值(百分比宽度或' auto'或任何样式表应用于元素)而不是像素宽度。
工作代码 jsfiddle https://jsfiddle.net/wtxayrnm/1/
function getComputedCSSValue(ele, prop) {
var resolvedVal = window.getComputedStyle(ele)[prop];
//does this return a pixel based value?
if (/px/.test(resolvedVal)) {
var origDisplay = ele.style.display;
ele.style.display = 'none';
var computedVal = window.getComputedStyle(ele)[prop];
//restore original display
ele.style.display = origDisplay;
return computedVal;
} else {
return resolvedVal;
}
}
应该注意的是,这将导致布局重新呈现,但是,根据您的情况,它可能比遍历所有样式表规则或克隆元素(这可能导致一些级联)更简单的解决方案规则不适用。)
答案 1 :(得分:3)
不熟悉Motools,但在jQuery中你可以做到。
点击此处观看直播演示http://jsbin.com/ewuqa
或者检查一下它还会处理多个匹配的CSS规则,但只返回正确的值(我唯一不愿意处理的是设置!important
)。
包含JS
http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
http://github.com/hafriedlander/jquery.concrete/raw/master/vendor/jquery.selector/jquery.class.js
http://github.com/hafriedlander/jquery.concrete/raw/master/vendor/jquery.selector/jquery.selector.js
http://github.com/hafriedlander/jquery.concrete/raw/master/vendor/jquery.selector/jquery.selector.specifity.js
自己的职能
function compare(as,bs) {
return (as[0] - bs[0]) || (as[1] - bs[1]) || (as[2] - bs[2]);
}
//selector should only match a single element
//property is a css style-name
//returns the set css value (if set) for matched element, not the computed value
//also handles multiple matching rules and only returns most specific match
//doesn't handle !important
function whatIsSet(selector, property) {
var se = $(selector);
var regex = new RegExp("(.*)-(.)(.*)","g");
var p = property;
if (/-/.test(p)) {
p = regex.exec(property);
p = p[1] + p[2].toUpperCase() + p[3];
}
if (se.get(0).style[p] != undefined && se.get(0).style[p] != '')
return se.get(0).style[p];
var matchers = new Object();
var mostSpecific = undefined;
for(var i = 0; i < document.styleSheets.length; i++) {
//IE support
var rules =
document.styleSheets[i].cssRules ?
document.styleSheets[i].cssRules :
document.styleSheets[i].rules;
for (var j=0; j < rules.length; j++)
if (rules[j].style[p])
if (jQuery.inArray(se, $(rules[j].selectorText)))
matchers[rules[j].selectorText] = rules[j].style[p];
}
for(var i in matchers) {
if(mostSpecific != undefined) {
var ms = $.selector(mostSpecific).specifity();
var is = $.selector(i).specifity();
mostSpecific = compare(ms, is) > 0 ? mostSpecific : i;
} else
mostSpecific = i;
}
return matchers[mostSpecific];
}
CSS
body { background-color: #000; font: 16px Helvetica, Arial; color: #fff; }
#myElement {background-color: yellow; width:10%}
div {background-color: green; width:200px}
div#myElement {background-color: blue; width:30%}
div.asd#myElement {background-color: red; width:50%;}
HTML
<div id="myElement" class="asd" style="width:91%">asd</div>
<input
type="button"
onclick="javascript:alert('width originally set to: '+
whatIsSet('#myElement', 'width'));"
value="Tell me original width!"><br>
<input
type="button"
onclick="javascript:alert('height originally set to: '+
whatIsSet('#myElement', 'height'));"
value="Tell me original height!"><br>
<input
type="button"
onclick="javascript:alert('background-color originally set to: '+
whatIsSet('#myElement', 'background-color'));"
value="Tell me original background-color!"><br>
答案 2 :(得分:1)
在IE中,element.currentStyle.width
。在许多其他浏览器中,getComputedStyle(element, null).getPropertyValue('width')
。
答案 3 :(得分:1)
我已从一个已关闭的副本中迁移并更新了我的答案:
How to tell if an element has a fluid width
不想走下扫描风格的路线我发现这有效...但不幸的是只有firefox :(对我而言,如果元素没有任何东西可以计算它的宽度(即它不是它应该返回原始值 - 这就是FireFox的作用:
function isElementFluid(elm){
var clone = elm.cloneNode(false);
if( window.getComputedStyle ) {
value = window.getComputedStyle(clone,null).width;
} else if( clone.currentStyle ) {
value = clone.currentStyle.width;
}
return (value && String(value).indexOf('%') != -1 );
}
(尚未测试IE)
然而,Webkit和Opera会返回一个空白值 - 这又是我同意FireFox实现的另一个例子,并且对其他人不满意。好吧,不是被计算机击败的粉丝;)所以提出了这个功能 - 完全超过顶部,但它似乎确实有效。我还没有在IE上测试这个,因为我现在还没有Windows机器。当原始的FireFox版本非常简洁时,它很烦人,但这里的逻辑是合理的 - 它可以回归到普通人在测试时是否有弹性。
function isElementFluid(elm){
var wrapper, clone = elm.cloneNode(false), ow, p1, p2;
if( window.getComputedStyle ) {
value = window.getComputedStyle(clone,null).width;
} else if( clone.currentStyle ) {
value = clone.currentStyle.width;
}
/// the browsers that fail to work as Firefox does
/// return an empty width value, so here we fall back.
if ( !value ) {
/// remove styles that can get in the way
clone.style.margin = '0';
clone.style.padding = '0';
clone.style.maxWidth = 'none';
clone.style.minWidth = 'none';
/// create a wrapper that we can control, my reason for
/// using an unknown element is that it stands less chance
/// of being affected by stylesheets - this could be improved
/// to avoid possible erroneous results by overriding more css
/// attributes with inline styles.
wrapper = document.createElement('wrapper');
wrapper.style.display = 'block';
wrapper.style.width = '500px';
wrapper.style.padding = '0';
wrapper.style.margin = '0';
wrapper.appendChild(clone);
/// insert the element in the same location as our target
elm.parentNode.insertBefore(wrapper,elm);
/// store the clone's calculated width
ow = clone.offsetWidth;
/// change the wrapper size once more
wrapper.style.width = '600px';
/// if the new width is the same as before, most likely a fixed width
if( clone.offsetWidth == ow ){
/// tidy up
elm.parentNode.removeChild(wrapper);
return false;
}
/// otherwise, calculate the percentages each time - if they
/// match then it's likely this is a fluid element
else {
p1 = Math.floor(100/500*ow);
p2 = Math.floor(100/600*clone.offsetWidth);
/// tidy up
elm.parentNode.removeChild(wrapper);
return (p1 == p2) ? Math.round(p1)+'%' : false;
}
}
else {
p1 = (value && String(value).indexOf('%') != -1);
return p1 ? value : false;
}
}
答案 4 :(得分:0)
我怀疑它可以做到。您非常准确地描述了原因:只有在元素的样式属性中才能访问此类信息。我能想到的唯一方法是稍微扩大父容器,看看textarea的大小是否成比例增长,但这可能并不总是可行,并且可能很难使跨浏览器功能化。
但是,我对更积极的答案非常感兴趣。