JavaScript中offsetWidth的bug及解决方法


Posted in Javascript onMay 17, 2017

offsetWidth表示对象的可见宽度。
比如:

#div1 {
 width: 100px;
 height: 200px;
 background: red;
}

结果:100

#div1 {
 width: 100px;
 height: 200px;
 background: red;
 border: 2px solid black;
}

结果:104 (100 + 2 + 2)

#div1 {
 width: 100px;
 height: 200px;
 background: red;
 border: 2px solid black;
 padding: 20px;
}

结果:144 (100 + 2 + 2 + 20 + 20)

#div1 {
 width: 100px;
 height: 200px;
 background: red;
 margin: 4px;
}

结果:100

**

所以,offsetWidth = width + padding + border, 和margin无关。

**
下面来看一个例子:

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>offsetWidth</title>
 <style type="text/css">
  #div1 {
   width: 500px;
   height: 200px;
   background: red;
  }
 </style>
</head>
<body>
 <div id="div1"></div>
 <script type="text/javascript">
  var oDiv = document.getElementById('div1');
  setInterval(function() {
   oDiv.style.width = oDiv.offsetWidth - 1 + 'px';
  }, 50);
 </script>
</body>
</html>

现象:红色div逐渐变窄,直到消失,没问题!

如果给div加一个border,呢?

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>offsetWidth</title>
 <style type="text/css">
  #div1 {
   width: 500px;
   height: 200px;
   background: red;
   border: 1px solid black;
  }
 </style>
</head>
<body>
 <div id="div1"></div>
 <script type="text/javascript">
  var oDiv = document.getElementById('div1');
  setInterval(function() {
   oDiv.style.width = oDiv.offsetWidth - 1 + 'px';
  }, 50);
 </script>
</body>
</html>

现象:红色div不仅没有变窄,反而越来越宽……

JavaScript中offsetWidth的bug及解决方法*

原因也很简单:就是border的直接原因,因为offsetWidth是把border算进去的,定时器轮询的时候,第一次,width : 102 - 1 == 101 ,那么offsetWidth立马就变为103;第二次,width: 103 - 1 == 102, 那么offsetWidth立马就变为104;紧接着第三次,width: 104 - 1 == 103, offsetWidth就为104了……

倘若把 oDiv.style.width = oDiv.offsetWidth - 1 + ‘px'; 换成 -2,那么红色div就不动了,不会变宽也不会变窄,因为offsetWidth为102,减去2就是100和原本的width相等,下一次循环,offsetWidth就等于100加上border的2,再减去2还是100,所以不动……*

解决方案也很简单,惹不起还躲不起?不用offsetWidth了!

我们都知道,获取元素的行间样式直接用element.style.width即可,但是这只针对元素的行间样式,如果写在css中,你就获取不到了.

但也是有办法的:

  • IE中用element.currentStyle.width / element.currentStyle.[‘width'];
  • 非IE中用getComputedStyle(element, false)[‘width']
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>offsetWidth</title>
 <style type="text/css">
  #div1 {
   width: 500px;
   height: 200px;
   background: red;
   border: 1px solid black;
  }
 </style>
</head>
<body>
 <div id="div1"></div>
 <script type="text/javascript">

  var oDiv = document.getElementById('div1');
  function getStyle(obj, attr) {
   if (obj.currentStyle) {//IE
    return obj.currentStyle[attr];
   } else {
    return getComputedStyle(obj, false)[attr];
   }
  }
  alert(getStyle(oDiv, 'width'));//直接弹出 “500px”
 </script>
</body>
</html>

有了上面的这个封装,我们就可以解决offsetWidth带来的困扰了

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>offsetWidth</title>
 <style type="text/css">
  #div1 {
   width: 500px;
   height: 200px;
   background: red;
   border: 1px solid black;
  }
 </style>
</head>
<body>
 <div id="div1"></div>
 <script type="text/javascript">
  var oDiv = document.getElementById('div1');
  function getStyle(obj, attr) {
   if (obj.currentStyle) {//IE
    return obj.currentStyle[attr];
   } else {
    return getComputedStyle(obj, false)[attr];
   }
  }
  setInterval(function() {
   //parseInt是因为getStyle()返回的是‘px'带单位,要整数化
   oDiv.style.width = parseInt(getStyle(oDiv, 'width')) - 1 + 'px';
  }, 30);
 </script>
</body>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Using the TextRange Object
Oct 14 Javascript
非常有用的40款jQuery 插件推荐(系列二)
Dec 25 Javascript
jquery 构造函数在表单提交过程中修改数据
May 25 Javascript
JavaScript中Date.toSource()方法的使用教程
Jun 12 Javascript
详解JavaScript的另类写法
Apr 11 Javascript
使用Bootstrap Tabs选项卡Ajax加载数据实现
Dec 23 Javascript
Angularjs实现分页和分页算法的示例代码
Dec 23 Javascript
jquery dataTable 获取某行数据
May 05 jQuery
浅谈webpack SplitChunksPlugin实用指南
Sep 17 Javascript
jQuery子选择器与可见性选择器实例分析
Jun 28 jQuery
使用Vue实现简单计算器
Feb 25 Javascript
JavaScript交换变量的常用方法小结【4种方法】
May 07 Javascript
Bootstrap 表单验证formValidation 实现远程验证功能
May 17 #Javascript
基于vue+ bootstrap实现图片上传图片展示功能
May 17 #Javascript
JavaScript运动框架 多物体任意值运动(三)
May 17 #Javascript
BootStrap表单验证 FormValidation 调整反馈图标位置的实例代码
May 17 #Javascript
JavaScript运动框架 解决防抖动问题、悬浮对联(二)
May 17 #Javascript
vue之nextTick全面解析
May 17 #Javascript
Vue.js学习教程之列表渲染详解
May 17 #Javascript
You might like
php生成固定长度纯数字编码的方法
2015/07/09 PHP
使用WordPress发送电子邮件的相关PHP函数用法解析
2015/12/15 PHP
Ubuntu中支持PHP5与PHP7双版本的简单实现
2018/08/19 PHP
JavaScript高级程序设计(第3版)学习笔记9 js函数(下)
2012/10/11 Javascript
用js判断页面是否加载完成实现代码
2012/12/11 Javascript
Jquery实现搜索框提示功能示例代码
2013/08/13 Javascript
extjs4 treepanel动态改变行高度示例
2013/12/17 Javascript
node.js实现逐行读取文件内容的代码
2014/06/27 Javascript
JavaScript设计模式之策略模式实例
2014/10/10 Javascript
11种ASP连接数据库的方法
2015/09/18 Javascript
浅谈JS原型对象和原型链
2016/03/02 Javascript
Node.js环境下编写爬虫爬取维基百科内容的实例分享
2016/06/12 Javascript
PHP捕捉异常中断的方法
2016/10/24 Javascript
JavaScript中关于iframe滚动条的去除和保留
2016/11/17 Javascript
简单实现JavaScript图片切换效果
2016/11/28 Javascript
Angularjs中的ui-bootstrap的使用教程
2017/02/19 Javascript
详解Angular 4.x Injector
2017/05/04 Javascript
解决Extjs下拉框不显示的问题
2017/06/21 Javascript
浅谈angular2 组件的生命周期钩子
2017/08/12 Javascript
JS匿名函数和匿名自执行函数概念与用法分析
2018/03/16 Javascript
详解Vue.js中引入图片路径的几种方式
2019/06/17 Javascript
简单了解Vue computed属性及watch区别
2020/07/10 Javascript
jQuery实现查看图片功能
2020/12/01 jQuery
[59:00]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD BO3 第一场 3月7日
2021/03/11 DOTA
浅谈numpy数组的几种排序方式
2017/12/15 Python
Python数据结构之双向链表的定义与使用方法示例
2018/01/16 Python
Python实现的爬取网易动态评论操作示例
2018/06/06 Python
使用Python OpenCV为CNN增加图像样本的实现
2019/06/10 Python
Python用字典构建多级菜单功能
2019/07/11 Python
乌克兰在线药房:Аптека24
2019/10/30 全球购物
Java面试笔试题大全
2016/11/23 面试题
幼儿园教研工作总结2015
2015/05/12 职场文书
2015年行政管理人员工作总结
2015/10/15 职场文书
4种非常实用的python内置数据结构
2021/04/28 Python
vue完美实现el-table列宽自适应
2021/05/08 Vue.js
PyTorch 如何设置随机数种子使结果可复现
2021/05/12 Python