手写的一个兼容各种浏览器的javascript getStyle函数(获取元素的样式)

要想获取HTML元素的计算样式一直都存在很多的兼容问题,各浏览器都会存在一些差异,Firefox、webkit(Chrome,Safari)支持W3C标准的方法:getComputedStyle(),而IE6/7/8不支持标准的方法但是有私有的属性来实现:currentStyle,IE9和Opera两个都支持。有了这2个方法和属性基本上可以满足大多数要求了。

代码如下:

var getStyle = function( elem, type ){
 return 'getComputedStyle' in window ? getComputedStyle(elem, null)[type] : elem.currentStyle[type];
};

但是对于自适应的宽度和高度使用currentStyle就没法获取到计算的值,只能返回auto,而getComputedStyle()就可以返回计算的值,解决这个问题有好几种办法。我之前想到的是用clientWidth/clientHeight减去padding的值,这样就可以在不支持标准方法的浏览器中获取到计算的宽度和高度。前几天看到司徒正美采用了另一种办法,使用getBoundingClientRect()方法获取到元素在页面中的位置,然后right减去left就是宽度,bottom减去top就是高度。我对他的代码做了一些小小的修改,最终代码如下:

代码如下:

var getStyle = function( elem, style ){
 return 'getComputedStyle' in window ?
 getComputedStyle( elem, null )[style] :
 function(){
  style = style.replace( /\-(\w)/g, function( $, $1 ){
   return $1.toUpperCase();
  });

var val =  elem.currentStyle[style];

if( val === 'auto' && (style === "width" || style === "height") ){
   var rect =  elem.getBoundingClientRect();
   if( style === "width" ){
    return rect.right - rect.left + 'px';
   }else{
    return rect.bottom - rect.top + 'px';
   }
  }
  return val;
 }();
};

// 调用该方法
var test = document.getElementById( 'test' ),
      // 获取计算的宽度
    tWidth = getStyle( test, 'width' );

新的问题,如果元素的宽度或高度使用了em或%的单位,getComputedStyle()返回的值就会自动将em或%换成px的单位,currentStyle就不会,而如果是font-size使用em为单位,在Opera下返回的是0em,Opera真的很恐怖!

后来在使用发现中还有一些没想到的兼容问题,今天我对原来的代码进行了优化,并对一些常见的兼容问题进行了处理。

在javascript中“-”(中划线或连字符)代表的是减号,而在CSS中,许多样式属性都有这个符号,如padding-left、font-size等,所以在javascript中如果出现如下的代码就一个错误:


代码如下:

elem.style.margin-left = "20px";

正确的写法应该是:


代码如下:

elem.style.marginLeft = "20px";

这里需要把CSS的中划线去掉并把原来紧跟在中划线后的字母大写,俗称“驼峰式”写法,不管是使用javascript设置或是获取元素的CSS样式都应该是驼峰式的写法。但是不少对CSS熟悉而又对javascript不太熟悉的新手朋友总是会犯这种低级错误,使用replace的高级用法可以很简单的将CSS属性中的中划线替换成驼峰式的写法。


代码如下:

var newProp = prop.replace( /\-(\w)/g, function( $, $1 ){
    return $1.toUpperCase();
});

对于float,在javascript中属于保留字,在javascript中设置或获取元素的float的值,都有其他的代替写法,在标准浏览器中为cssFloat,而在IE6/7/8中为styleFloat。

如果top、right、bottom、left没有一个显式的值,在获取这些值的时候部分浏览器会返回一个auto,虽然auto这个值是一个合法的CSS属性值,但绝不是我们想要的结果,而应该是0px。

在IE6/7/8中要设置元素的透明度需要用到滤镜、如:filter:alpha(opacity=60),对于标准浏览器直接设置opacity即可,IE9两种写法都支持,我对获取元素的透明度也做了兼容处理,只要使用opacity就可以获取到所有浏览器元素的透明度的值。

在IE6/7/8中获取元素的宽度和高度已经在上篇文中介绍过了,这里就不再复述了。还有一个需要注意的地方就是,如果元素的样式是使用style内联的写法,或者是已经使用javascript设置过样式的属性,可以使用下面的方法获取到元素的计算样式:


代码如下:

var height = elem.style.height;

这个方法比读取getComputedStyle或currentStyle中的属性值都要快,应该优先使用,当然前提条件就是样式是通过内联的写法设置的(使用javascript设置也是设置内联样式)。优化过的最终代码如下:

代码如下:

var getStyle = function( elem, p ){
 var rPos = /^(left|right|top|bottom)$/,
 ecma = "getComputedStyle" in window,
 // 将中划线转换成驼峰式 如:padding-left => paddingLeft
 p = p.replace( /\-(\w)/g, function( $, $1 ){
 return $1.toUpperCase();
 });
 // 对float进行处理  
 p = p === "float" ? ( ecma ? "cssFloat" : "styleFloat" ) : p;

return !!elem.style[p] ?
 elem.style[p] :
 ecma ?
 function(){
 var val = getComputedStyle( elem, null )[p];
 // 处理top、right、bottom、left为auto的情况
 if( rPos.test(p) && val === "auto" ){
 return "0px";
 }
 return val;
 }() :
 function(){
 var <a href="http://wirelesscasinogames.com">wirelesscasinogames.com</a> val = elem.currentStyle[p];
 // 获取元素在IE6/7/8中的宽度和高度
  if( (p === "width" || p === "height") && val === "auto" ){
  var rect = elem.getBoundingClientRect();    
  return ( p === "width" ? rect.right - rect.left : rect.bottom - rect.top ) "px";
  }
 // 获取元素在IE6/7/8中的透明度
  if( p === "opacity" ){
  var filter = elem.currentStyle.filter;
  if( /opacity/.test(filter) ){
   val = filter.match( /\d / )[0] / 100;
  return (val === 1 || val === 0) ? val.toFixed(0) : val.toFixed(1);
  }
  else if( val === undefined ){
  return "1";
  }
  }
  // 处理top、right、bottom、left为auto的情况
  if( rPos.test(p) && val === "auto" ){
  return "0px";
  }
  return val;
 }();
};

下面是调用示例:

代码如下:

<style>
.box{
 width:500px;
 height:200px;
 background:#000;
 filter:alpha(opacity=60);
 opacity:0.6;
}
</style>

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

<script>
var box = document.getElementById( "box" );

alert( getStyle(box, "width") ); // "500px"
alert( getStyle(box, "background-color") ); // "rgb(0, 0, 0)" / "#000"
alert( getStyle(box, "opacity") ); // "0.6"
alert( getStyle(box, "float") ); // "none"
</script>

(0)

相关推荐

  • JavaScript获取网页、浏览器、屏幕高度和宽度汇总

    经常发现在写JavaScript的时候,都需要用到网页.浏览器或屏幕的高度和宽度来解决布局定位的问题,时常前用后忘,要不就是在网上search,干脆自己总结一下,这样也方便再次使用,省时省力. 网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWidth (包括边线的宽) 网页可见区域高:document.body.offsetHeight (包括边线的

  • JavaScript跨浏览器获取页面中相同class节点的方法

    网页开发时,在很多时候我们需要操作相同类名的元素,即class相同的元素.昨天参加笔试,有一道相关的题目没答上来: JavaScript获取页面中class为test的节点 于是收集了一些相关的资料,在本文中列举了两种我觉得比较好的方法,不足之处,还望大家批评指正.如果大家有更好的方法,希望可以分享. Solution1 Jeremy Keuth方案 Jeremy Keuth大叔在<JavaScript DOM 编程艺术>(第2版)(英文:DOM Scripting-Web Design wi

  • javascript获取浏览器类型和版本的方法(js获取浏览器版本)

    复制代码 代码如下: function getExplorerInfo() { var explorer = window.navigator.userAgent.toLowerCase() ; //ie  if (explorer.indexOf("msie") >= 0) {    var ver=explorer.match(/msie ([\d.]+)/)[1];    return {type:"IE",version:ver}; } //firef

  • javascript 获取浏览器版本

    工作中需要通过JS去获取当前使用的浏览器的名字以及版本号,网上大堆资料都有一个关键词是 navigator.appName,但是这个方法获取的浏览器的名字只有两种要么是IE要么就是Netscap,倒是可以用来判断是否使用了IE,但是我想获取具体的浏览器产品名字比如  Firefox,Chrome等. 复制代码 代码如下: function BroswerUtil() { } BroswerUtil.prototype = {     getBrowserVersion: function ()

  • javascript获取和判断浏览器窗口、屏幕、网页的高度、宽度等

    HTML精确定位属性:scrollLeft,scrollWidth,clientWidth,offsetWidth scrollHeight: 获取对象的滚动高度.scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离scrollWidth:获取对象的滚动宽度offsetHeight:获取对象相对于版面或由父坐标 offsetParent 属性指定的父坐标的高度offsetLeft:获取对

  • JavaScript获取各大浏览器信息图示

    如何获取浏览器信息 Window有navigator对象让我们得知浏览器的全部信息.我们可以利用一系列的API函数得知浏览器的信息. JavaScript代码如下: 复制代码 代码如下: function message(){ txt = "<p>浏览器代码名: " + navigator.appCodeName + "</p>"; txt+= "<p>浏览器名称: " + navigator.appName

  • javascript实现获取浏览器版本、操作系统类型

    代码很简洁,功能很实用,这里就不多废话了,直接给大家奉上代码: /** * Created by Administrator on 15-1-12. */ function BroswerUtil() { } BroswerUtil = { //检测浏览器版本 getBrowserVersion: function () { var agent = navigator.userAgent.toLowerCase(); var arr = []; var Browser = ""; va

  • javascript使用百度地图api和html5特性获取浏览器位置

    复制代码 代码如下: <!DOCTYPE html><html><body><p id="demo">点击这个按钮,获得您的位置:</p><button onclick="getLocation()">试一下</button><script src="http://api.map.baidu.com/api?v=1.4" type="text/ja

  • javascript获取设置div的高度和宽度兼容任何浏览器

    Javascript如何获取和设置div的高度和宽度,并且兼容任何浏览器?看代码: 复制代码 代码如下: <div id="div1" style="height:300px;width:200px;">http://www.itdos.com</div> <div id="div2" style="height:30px;width:20px;">http://www.itdos.com&

  • 手写的一个兼容各种浏览器的javascript getStyle函数(获取元素的样式)

    要想获取HTML元素的计算样式一直都存在很多的兼容问题,各浏览器都会存在一些差异,Firefox.webkit(Chrome,Safari)支持W3C标准的方法:getComputedStyle(),而IE6/7/8不支持标准的方法但是有私有的属性来实现:currentStyle,IE9和Opera两个都支持.有了这2个方法和属性基本上可以满足大多数要求了. 复制代码 代码如下: var getStyle = function( elem, type ){ return 'getComputed

  • Bootstrap编写一个兼容主流浏览器的受众门户式风格页面

    上一次写的<Bootstrap编写一个兼容主流浏览器的受众巨幕式风格页面>(点击打开链接)部分老一辈的需求可能对这种后现代的风格并不满意,没关系,我们完全可以改变布局拉成门户式的风格,他们马上就接受了: 首先,门户式的布局的大概你要清楚,这一才利于我们快速布局开头是一个较小的巨幕,后是一个导航栏,这里还是用到了按钮组接着是各个专栏,这里是关于bootstrap栅格系统与面板的运用,最后是版权信息,这里还是一个面板. 反正个人觉得这种门户式的布局风格烂大街,但不知道为何似乎很受众的样子. 我们需

  • Bootstrap编写一个兼容主流浏览器的受众巨幕式风格页面

    虽然说IE6除了部分要求苛刻的需求以外已经被可以不考虑了,但是WIN7自带的浏览器IE8还是需要支持的. 本文这个方法主要的优点,个人觉得就是准备少,不需要上网寻找大量的图片做素材,你只要准备好一个bootstrap.jquery与photoshop就可以了,bootstrap与jquery怎么配置,可以参考<Bootstrap编写一个在当前网页弹出可关闭的对话框 非弹窗>(点击打开链接) 被要求编写一个网站,常常会被如何布局困扰,其实也不难,如果能够熟练使用Bootstrap,并且有一套特定

  • 手写Vue内置组件component的实现示例

    目录 前言 内置组件component的使用 component组件的原理分析 虚拟DOM与原生DOM render函数的使用 尝试手写实现component 总结 最近在复习Vue的源码,今天带大家手写实现一下Vue内置组件component,比较简单,最近面试有被问到. 前言 Vue大家都很熟悉,除了原生的组件,其自己也封装了一下内置组件,比如component,transition,keep-alive等等. component算是用的比较多的了,当我们遇到需要根据不同条件显示不同组件的时

  • Promise对象all与race方法手写示例

    目录 前言 Promise.all 介绍 手写 Promise.race 介绍 手写 前言 在理解了手写promsie.then的方法后,再来看它的其他方法,感觉真的简单了不少. Promise.all 介绍 Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例. const p = Promise.all([p1, p2, p3]); 上面代码中,Promise.all()方法接受一个数组作为参数,p1.p2.p3都是 Promise 实例.另外

  • 兼容FireFox 用javascript写的一个画图函数

    早晨醒来突然想写一个画图函数,以前在网上看到有人做过,但都是用VML做的,只有ie支持. 偶这个是用<div>形成的绝对定位的点画出来的,兼容各种浏览器. Untitled 1 .style1 { font-size: x-small; } function makedot(x,y){ //画点函数 document.write(" ") } /** 函数功能:根据给定的圆心和半径画圆 函数思路:根据半径及圆心坐标利用数学方法计算从0°到360°的每点的坐标,并画出来. *

  • 如何手写一个Spring Boot Starter

    何为 Starter ? 想必大家都使用过 SpringBoot,在 SpringBoot 项目中,使用最多的无非就是各种各样的 Starter 了.那何为 Starter 呢?你可以理解为一个可拔插式的插件(组件).或者理解为场景启动器. 通过 Starter,能够简化以前繁杂的配置,无需过多的配置和依赖,它会帮你合并依赖,并且将其统一集成到一个 Starter 中,我们只需在 Maven 或 Gradle 中引入 Starter 依赖即可.SpringBoot 会自动扫描需要加载的信息并启动

  • 如何从零开始利用js手写一个Promise库详解

    前言 ECMAScript 是 JavaScript 语言的国际标准,JavaScript 是 ECMAScript 的实现.ES6 的目标,是使得 JavaScript 语言可以用来编写大型的复杂的应用程序,成为企业级开发语言. 概念 ES6 原生提供了 Promise 对象. 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理. 三道思考题 刚开始写前端的时候,处理异步请求经常用

  • vue用Object.defineProperty手写一个简单的双向绑定的示例

    前言 上次写了一个Object.defineProperty() 不详解,文末说要写用它来写个双向绑定.说话算话,说来就来 前文链接 Object.defineProperty() 不详解 先看最后效果 model演示.gif 什么是双向绑定? 1.当一个对象(或变量)的属性改变,那么调用这个属性的地方显示也应该改变,模型到视图(model => view) 2.当调用属性的这个地方改变了这个属性(通常是一个表单元素),那么这个对象(或变量)的属性也会改为最新的值 ,即视图到模型(view =>

  • 一个手写的vue放大镜效果

    组件使用less,请确保已安装loader 本组件为放大镜组件,传参列表为: •width: 必传,设置放大镜的宽高(正方形),放大区域等同,放大倍数为2倍 •picList:必传,传入图片列表 使用示例: script: import mirror from 'xx/mirror' export default { components:{ mirror }, data(){ return { width:300, picList:[ xxxxxx, xxxxxx ], } } } html:

随机推荐