Skip to content

浏览器的标准模式和怪异模式

由于之前 html/css 的标准未完成之前, 各个浏览器的代码解析执行不一样, 没有统一的标准, 而之前的很多网页都是在这种非标准的模式下开发出来的,浏览器厂家为了兼容之前的代码能够正常解析运行的运行模式就是怪异模式.

浏览器运行代码的模式

怪异模式: 浏览器没有按照 w3c 来兼容代码的运行模式 什么叫没有按照 w3c 来兼容低吗的运行模式? 就是没有这行代码 <!doctype html> 标准模式: 浏览器按照 w3c 标准来兼容代码的运行模式 也就是写上这行代码 doctype html

获取浏览器运行代码的模式

javascript
document.compatMode; // 获取浏览器运行代码的模式
// BackCompat: 怪异模式
// CSS1Compat: 标准模式

浏览器如何选择解析运行模式(怪异模式/标准模式)

使用 doctype 声明来判断

怪异模式和标准模式的区别

  1. CSS 盒模型的区别: 比如低版本的 IE, 盒模型的高度是包括边框的高度
  2. JS 属性差异: 比如获取整个文档, 低版本浏览器可能是是用 document.body而现在的浏览器用的是 document.documentElement

惰性函数

参考: https://github.com/mqyqingfeng/Blog/issues/44

获取已经滚动的高度(兼容低版本浏览器)

javascript
// 普通函数: 调用一次判断一次
function getScrollOffset() {
  if(window.pageXOffset) {
    // 如果可以使用 pageXOffset
    return {
      top: window.pageXOffset,
      left: window.pageYOffset,
    }
  } else  {
    // 如果不可以使用 pageXOffset, 就使用 document.body + document.documentElement
    return {
      top: document.body.scrollTop + document.documentElement.scrollTop,
      left: document.body.scrollLeft + document.documentElement.scrollLeft
    }
  }
}


// 惰性函数(推荐这种方式): 只会判断一次(当这个函数第一次被执行的时候才会执行判断)
function getScrollOffset() {
  if(window.pageXOffset) {
    getScrollOffset = function() {
      return {
        top: window.pageXOffset,
        left: window.pageYOffset,
      };
    };
  }else {
  	getScrollOffset = function() {
    	return {
        top: document.body.scrollTop + document.documentElement.scrollTop,
        left: document.body.scrollLeft + document.documentElement.scrollLeft
      }
    };
  }
  return getScrollOffset();
}


惰性函数(闭包): 只会判断一次(代码执行到这行直接执行判断, 然后返回函数)
var getScrollOffset = (function() {
  // 如果可以使用 pageXOffset
	if(window.pageXOffset) {
    return function () {
      return {
        top: window.pageXOffset,
        left: window.pageYOffset,
    	}
    }
  }

  // 如果不可以使用 pageXOffset, 就使用 document.body + document.documentElement
  return function() {
    return {
      top: document.body.scrollTop + document.documentElement.scrollTop,
      left: document.body.scrollLeft + document.documentElement.scrollLeft
    }
  };
})();

获取可视区域的宽/高度

常规写法:

javascript
// 可视区域高度
window.clientHeight;

// 可视区域宽度
window.clientWidth;

低版本浏览器: IE9 及以下兼容写法:

javascript
// 标准模式:
document.documentElement.clientHeight;
document.documentElement.clientWidth;

// 怪异模式:
document.body.clientHeight;
document.body.clientWidth;

封装兼容性写法:

javascript
// 获取浏览器可视区域的宽度和高度
var getViewportSize = (function () {
  if (window.innerWidth) {
    return function () {
      return {
        width: window.innerWidth,
        height: window.innerHeight,
      };
    };
  }

  return function () {
    // 低版本浏览器
    var key = document.compatMode === "BackCompat" ? "body" : "documentElement";
    return {
      width: document[key].clientWidth,
      height: document[key].clientHeight,
    };
  };
})();

// --- 获取浏览器可视区域的宽度和高度
function getViewportSize() {
  if (window.innerWidth) {
    getViewportSize = function () {
      return {
        width: window.innerWidth,
        height: window.innerHeight,
      };
    };
  } else {
    getViewportSize = function () {
      // ie
      var key = document.compatMode === "BackCompat" ? "body" : "documentElement";
      return {
        width: document[key].clientWidth,
        height: document[key].clientHeight,
      };
    };
  }
  return getViewportSize();
}

获取网页的总高度 scrollHeight/scrollWidth

javascript
/**
 * 获取滚动的宽度/高度
 * @returns {object: {width, height}}
 */
var getScrollSize = (function () {
  if (document.body.scrollHeight) {
    return function () {
      return {
        width: document.body.scrollWidth,
        height: document.body.scrollHeight,
      };
    };
  } else {
    return function () {
      return {
        width: document.documentElement.scrollWidth,
        height: document.documentElement.scrollHeight,
      };
    };
  }
})();

/**
 * 获取滚动的宽度/高度
 * @returns {object: {width, height}}
 */
function getScrollSize() {
  if (document.body.scrollHeight) {
    getScrollSize = function () {
      return {
        width: document.body.scrollWidth,
        height: document.body.scrollHeight,
      };
    };
  } else {
    getScrollSize = function () {
      return {
        width: document.documentElement.scrollWidth,
        height: document.documentElement.scrollHeight,
      };
    };
  }
  return getScrollSize();
}

获取元素距离浏览器的左上角的 offset

javascript
function getFixedPosition() {
  var parent = el.offsetParent; // 找到当前元素有定位属性的父级元素(如果找不到就会一直向上找, 知道body为止)
  var offsetLeft = el.offsetLeft;
  var offsetTop = el.offsetTop;

  while (parent) {
    offsetLeft += parent.offsetLeft;
    offsetTop += parent.offsetTop;
    parent = parent.offsetParent; // 找父元素的有定位属性的父级元素
  }

  return {
    left: offsetLeft,
    top: offsetTop,
  };
}

操作浏览器滚动条

  1. window.scroll/window.scrollTo: 滚动到指定位置
  2. window.scrollBy: 在当前的浏览器滚动条位置的基础上滚动指定数值
javascript
window.scrollTo(300, 400); // x轴滚动到300px的位置 y轴滚动到400px的位置

// 假设默认滚动条x,y轴的位置是: 0, 0
window.scrollBy(200, 300); // 第一次: x: 200 y:300
window.scrollBy(200, 300); // 第二次: x: 400 y:600

Released under the MIT License.