为什么 $('#foo').css('width', $('#foo').css('width')) 会改变宽度?

10

人们会认为,在下面这段jQuery代码之后,选中#foo

宽度不会改变;毕竟,我们将其宽度设置为它本应该有的值:

var original_width = $('#foo').css('width');
$('#foo').css('width', original_width);

实际上,这个看起来合理的猜测是错误的,正如在此页面所示。我提供下面的代码。重要的是要注意,四个主要部分,对应于四个.level-0 div,都具有相同的结构和内容。其中第二个和第四个(具有jqbug类)将其宽度“重新设置”(通过一些JS,如上所述),使其值等于其本来就有的值。对于第二个情况,这个操作实际上改变了宽度;对于第四个情况,宽度保持不变,像预期的那样。第二个和第四个情况之间唯一的区别是前者的box-sizing参数为border-box

<div class="level-0 border-box">
    <div id="i1" class="level-1">
      <p>Lorem ipsum dolor sit amet</p>
    </div>
</div>

<div class="level-0 border-box">
    <div class="level-1 jqbug">
      <p>Lorem ipsum dolor sit amet</p>
    </div>
</div>

<div class="level-0">
    <div id="i1" class="level-1">
      <p>Lorem ipsum dolor sit amet</p>
    </div>
</div>

<div class="level-0">
    <div class="level-1 jqbug">
      <p>Lorem ipsum dolor sit amet</p>
    </div>
</div>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js">
</script>


  (function ($) {
    $('.jqbug').each(function () {
      $(this).css('width', $(this).css('width'));
    });

  }(jQuery));


*{
  outline:3px solid green;
}

.border-box, .border-box *{
  -webkit-box-sizing:border-box;
     -moz-box-sizing:border-box;
          box-sizing:border-box;
}

.level-0{
  position:relative;
  margin:10px auto;
  width:300px;
  height:100px;
  font-family:consolas,monaco,courier,monospace;
}
.level-1{
  position:absolute;
  padding:10px 20px;
  background-color:#0aa;
  font-size:15px;
}
在这个jsFiddle中,使用的代码与上面显示的完全相同,所有的
最终都具有相同的宽度。一方面,这是好的:结果具有预期的外观。另一方面,jsFiddle的结果并不代表浏览器直接产生的结果,这与jQuery的行为一样令人困惑。
我的问题是:
  1. 这是jQuery的错误还是这种令人困惑的行为与CSS规范一致?
  2. 需要做什么才能使jsFiddle产生的结果看起来像浏览器产生的结果?
编辑:我修改了JS(在上面链接的页面、jsFiddle以及本帖子中),以匹配Marco Biscaro的答案所给出的内容;这对于直接由浏览器显示的页面外观没有任何影响,但它确实影响了jsFiddle的结果。现在后者显示各个
之间的宽度没有任何区别。这个结果仍然与浏览器直接产生的结果不同,所以情况并没有比之前好多少:我们仍然有jQuery会产生令人惊讶的结果,而jsFiddle会产生与浏览器结果不匹配的结果。

渴望发一个“哈哈”的帖子,但我宁愿有建设性的意见.. :) 可能是你的CSS重置有问题吗? 尝试在不同的浏览器中测试了吗? 有些浏览器倾向于计算宽度。 - Oliver M Grech
2
你从未设置宽度,所以jQuery尝试获取它,可能使用outerWidth,因为它获取包括填充的宽度。使用$('.jqbug').width()可以获得正确的值。 - adeneo
@adeneo 为什么不把这个作为回答发出来呢?在我看来似乎很合理。 - Matt Kieran
3个回答

1
你有两个不同的 div 具有相同的类。当你这样做:
$('.jqbug').css('width')

其中一个div的宽度被返回(我不知道jQuery如何确定其中之一)。在您托管的页面中,返回值为234px,而在jsFiddle中返回值为274px(同样,我不知道确切原因)。这就是为什么两个页面之间行为不同的原因。
返回的值被应用为两个div的宽度,但由于一个div具有box-sizing: border-box而另一个没有,因此一个div比另一个更大。
如果您将宽度设置为原始宽度并使用$(document).readyhttp://bugs.jquery.com/ticket/14084),则如预期地,jQuery不会更改任何div的宽度。
$(document).ready(function () {
    $('.jqbug').each(function () {
        $(this).css('width', $(this).css('width'));
    });
});

“jQuery不会像预期的那样更改任何div的宽度”这种说法在jsFiddle之外是不正确的;我已经更改了代码以匹配您发布的内容,第二个div仍然更改了其宽度。请参见我上面的编辑。 - kjo
1
@kjo 如果使用$(document).ready,它就能工作。这是jQuery的一个bug。 - Marco Biscaro
1
@MarcoBiscaro:我无法感谢你的足够!今天我一直在经历一个又一个毫无意义的情况。你的帖子是全天第一件有意义的事情... - kjo

0
这个问题是由于第一个div在父元素上有border-box这个CSS类,而其宽度与第二个元素的父元素不同,后者没有设置border-box所导致的。
border-box设置了盒模型尺寸。这意味着它将采用宽度+填充。
这会导致由jQuery设置的内联宽度被覆盖。

0

只需使用outerWidth,它将计算包括填充和边框在内的实际宽度

var original_width = $('#foo').outerWidth();

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