在Opera浏览器中获取计算出的像素宽度

6
如何在Opera中获取元素的计算宽度?在其他浏览器中,我可以这样做:
// getComputedStyle wrapper
function getStyle(element, styleProp) {
  return element.currentStyle ? element.currentStyle[styleProp] :
      getComputedStyle(element, null).getPropertyValue(styleProp);
}

...但是在Opera浏览器上只能部分运作。它返回了许多"auto",而不是其他浏览器中有用的像素值。

这里有一个实时演示,可以将一些文本扩展到适合的盒子中。它在Opera浏览器上无法正常工作,因为计算出的宽度是auto,而不是其他浏览器中的px值。

live demo in different browsers

我该如何在Opera浏览器中获取更有用的计算样式,例如元素的像素宽度?

我知道,在这种情况下,我可以使用offsetWidth代替获取计算样式。我感谢您的建议,但这个问题的真正重点是我想知道如何在Opera浏览器中获取计算样式,其中样式实际上是以单位计算的。对于此问题,我不关心offsetWidth


1
为什么你不使用任何框架来检测不同浏览器中的宽度和高度? jQuery使这个例程变得简单而优雅。只需要使用 $(glyph).width() 代替 getStyle(glyph, 'width') http://jsbin.com/ikatuc/2/edit#javascript,HTML,live 在Opera 10.63,IE6-8,Chrome,Firefox中测试 - Sergey Ratnikov
4个回答

5

CSS所谓的“计算值”并不总是你所期望的。我猜Opera在这里遵循规范,而其他浏览器则会执行他们认为更有用的操作。

我建议使用element.offsetWidth代替getComputedStyle()来实现这个目的。


嗯,我本来想使用真正的DOM方法,但也许在这里使用非标准的offsetWidth更有意义。你能提供一下相关规范的链接吗?你说Opera完全遵循了这个规范的部分,我感到很惊讶,如果这确实是指定的行为,那么他们是唯一这样做的人。 - Dagg Nabbit
注意:我不是CSS大师。然而,我的理解是,在CSS中有一个区别(请参见http://www.w3.org/TR/CSS2/cascade.html以获取定义)在“计算”和“实际”值之间,其中“计算”可能并不总是实际的像素值。现在,这可能没有被规范足够详细,让我精确地声称Opera做得“正确”-让我们说我们在实施时认为它是完全正确的,但其他浏览器似乎正在发布其他决策.. ;) - hallvors
但是等等,它在这里说:“另一方面,相对值必须转换为计算值... 'auto'值必须计算”...这不是听起来像Opera正在提供的这些“auto”值应该转换为单位吗? - Dagg Nabbit
FYI:used values在CSS 2.1中被引入,相当于CSS 2.0中的computed values。术语computed values在CSS 2.1中有不同的含义。请参见:https://developer.mozilla.org/en/DOM/window.getComputedStyle#Notes - gblazex
啊哈。定义的方式被改变了,真的很令人困惑 :-o 但是听起来这是Opera的一个bug,而且尽管名称如此,该方法实际上应该返回CSS 2.1中定义的使用值。 - hallvors
显示剩余3条评论

2

在IE <= 8中也会失败。

原因是因为在这种情况下currentStylegetComputedStyle的工作方式不同。如果您首先测试getComputedStyle,它将在Opera和IE 9-10中起作用。Opera在许多情况下尝试模仿IE(请参见innerText vs textContent),因此它也有currentStyle

但是请注意,如果所涉及的元素在其样式中具有display:inline(FF、Chrome、IE),则会失去您的“预期”行为,因为它们将为您报告“auto”……除了……你猜对了,在Opera中,它将向您显示元素的“正确”px宽度。

如果您需要一个通用函数,最好包括一个通用库(您将发现这些库充满了您永远不需要的边缘情况)。如果您有一个特定的目的要解决,您可以使用兼容的替代品。

在这种情况下,计算样式并不真正有用。您需要的可能是clientWidthoffsetWidthscrollWidth,具体取决于您的需求。它们的区别主要在于您是否想包括填充、bordermargin和/或被剪切的区域(如果内容水平溢出)。

它们甚至支持像IE 6这样的古老浏览器,实际上这些属性最初是由微软在第一次浏览器战争中引入的(就像innerHTML一样)。

您可以通过在MSDN或MDN中搜索来了解更多信息。


计算样式在除Opera之外的所有其他浏览器中对我非常有用。这个问题是关于如何在Opera中获得有用的计算样式,而不是如何通过clientWidth来解决它。如果我改变示例以获取字体颜色或其他内容,是否会有帮助? - Dagg Nabbit
好的,我刚刚回答了你的问题(根据你的标题和原始描述)。如果你有一个具体的问题,为什么要问其他的东西呢?我不确定你是想解决问题还是只想制造问题... - gblazex
我有一个具体的问题。我的原始帖子以"How can I get more useful computed styles, such as the pixel width of an element, in Opera?" 结尾。这是我的问题摘要。没有改变。我想获取计算样式,而不是offsetWidth。 - Dagg Nabbit
1
当然有一个使用案例。使用案例是getStyle函数,它显示在帖子的顶部。它在每个浏览器中的行为都相同,但在Opera中不同。我希望它在Opera中的行为与其他浏览器中的行为相同。这方面没有任何歧义。 - Dagg Nabbit
1
先检查 getComputedStyle,这个方法非常好用。谢谢。 - Dagg Nabbit
显示剩余3条评论

0
您可以使用以下代码在Opera中获取属性:
document.defaultView.getComputedStyle(element,null).getPropertyValue(styleProp);

0

如果你保持良好的代码结构,从未将脚本元素作为body元素的子元素,那么这就不应该是一个困难的问题,即使它被验证了,因为它会导致非常糟糕的编码实践。另一方面,我赞扬你使用appendChild而不是不可靠的innerHTML,所以至少你正在努力不走捷径。

使用匿名函数来执行onload事件,这样你可以执行多个函数。我不熟悉字形(SVG?),所以我无法让任何浏览器以7px之外的任何大小呈现字形。

这是重新处理后的代码...

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>get computed width in pixels in Opera</title>
<script type="application/javascript">
//<![CDATA[

// getComputedStyle wrapper
function getStyle(element, styleProp)
{
 return element.currentStyle ? element.currentStyle[styleProp] : getComputedStyle(element, null).getPropertyValue(styleProp);
}

// cheesy convenience function
function textDiv(textContent, className)
{
 var tmp = document.createElement('div');
 if (className) tmp.className = className;
 tmp.appendChild(document.createTextNode(textContent));
 return tmp;
}

window.onload = function()
{
 var box = document.getElementById('box'),glyph = box.appendChild(textDiv('g', 'glyph')),size=500;

 glyph.style.position = 'absolute';
/*
 document.getElementById('status').appendChild(textDiv('Initial computed width: ' + getStyle(glyph, 'width')));

 while (parseInt(getStyle(glyph, 'width'), 10) <  100)
 {
  glyph.style.fontSize = size++ + '%';
 }
*/
 document.getElementById('status').appendChild(document.createTextNode(document.getElementById('box').firstChild.scrollWidth+'px'));
}

//]]>
</script>
</head>

<body>

<div id="status"></div>
<div id="box"></div>

</body>
</html>

jsbin必须将那些脚本元素放在那里,我只是在脚本面板中输入了它们。 "Glyph"在这里没有太多意义;在我从中复制粘贴代码时更有意义。它基本上意味着“符号”。在这种情况下,符号是字母G。 - Dagg Nabbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接