JavaScript核心之CSS详解(CSS规则,getComputedStyle(),matchMedia(),CSS事件)

目录

1 CSS规则

1.1 CSSRule接口

1.1.1 cssText

1.1.2 parentStyleSheet

1.1.3 parentRule

1.1.4 type

1.2 CSSStyleRule接口

1.2.1 selectorText属性

1.2.2 style属性

1.3 CSSMediaRule接口

1.4 CSSStyleDeclaration对象

1.4.1 getPropertyPriority()

1.4.2 getPropertyValue()

1.4.3 item()

1.4.4 removeProperty()

1.4.5 setProperty()

2 window.getComputedStyle()

3 window.matchMedia()

3.1 基本用法

3.2 监听事件

4 CSS事件

4.1 transitionEnd事件

4.2 animationstart事件,animationend事件,animationiteration事件


1 CSS规则

一条CSS规则包括两个部分:CSS选择器和样式声明。下面就是一条典型的CSS规则。

选择符{属性:属性值}

.myClass {
  background-color: yellow;
}

1.1 CSSRule接口

CSS规则部署了CSSRule接口,它包括了以下属性。

1.1.1 cssText

cssText属性返回当前规则的文本。

// CSS代码为
// body { background-color: darkblue; }

var stylesheet = document.styleSheets[0];
stylesheet.cssRules[0].cssText
// body { background-color: darkblue; }

1.1.2 parentStyleSheet

parentStyleSheet属性返回定义当前规则的样式表对象。

1.1.3 parentRule

parentRule返回包含当前规则的那条CSS规则。最典型的情况,就是当前规则包含在一个@media代码块之中。如果当前规则是顶层规则,则该属性返回null。

1.1.4 type

type属性返回有一个整数值,表示当前规则的类型。

最常见的类型有以下几种。

  • 1:样式规则,部署了CSSStyleRule接口
  • 3:输入规则,部署了CSSImportRule接口
  • 4:Media规则,部署了CSSMediaRule接口
  • 5:字体规则,部署了CSSFontFaceRule接口

1.2 CSSStyleRule接口

如果一条CSS规则是普通的样式规则,那么除了CSSRule接口,它还部署了CSSStyleRule接口。

CSSRule接口有以下两个属性。

1.2.1 selectorText属性

selectorText属性返回当前规则的选择器。

var stylesheet = document.styleSheets[0];
stylesheet.cssRules[0].selectorText // ".myClass"

1.2.2 style属性

style属性返回一个对象,代表当前规则的样式声明,也就是选择器后面的大括号里面的部分。该对象部署了CSSStyleDeclaration接口,使用它的cssText属性,可以返回所有样式声明,格式为字符串。

document.styleSheets[0].cssRules[0].style.cssText
// "background-color: gray;font-size: 120%;"

1.3 CSSMediaRule接口

如果一条CSS规则是@media代码块,那么它除了CSSRule接口,还部署了CSSMediaRule接口。

该接口主要提供一个media属性,可以返回@media代码块的media规则。

1.4 CSSStyleDeclaration对象

每一条CSS规则的样式声明部分(大括号内部的部分),都是一个CSSStyleDeclaration对象,主要包括三种情况。

  • HTML元素的行内样式(<elem style="...">)
  • CSSStyleRule接口的style属性
  • window.getComputedStyle()的返回结果

每一条CSS属性,都是CSSStyleDeclaration对象的属性。不过,连词号需要编程骆驼拼写法。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.color // "red";
styleObj.fontSize // "100%"

除了CSS属性以外,CSSStyleDeclaration对象还包括以下属性。

  • cssText:当前规则的所有样式声明文本。该属性可读写,即可用来设置当前规则。
  • length:当前规则包含多少条声明。
  • parentRule:包含当前规则的那条规则,同CSSRule接口的parentRule属性。

CSSStyleDeclaration对象包括以下方法。

1.4.1 getPropertyPriority()

getPropertyPriority方法返回指定声明的优先级,如果有的话,就是“important”,否则就是空字符串。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.getPropertyPriority('color') // ""

1.4.2 getPropertyValue()

getPropertyValue方法返回指定声明的值。

// CSS代码为
// color:red;

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.getPropertyValue('color') // "red"

1.4.3 item()

item方法返回指定位置的属性名。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.item(0) // "color"
// 或者
styleObj[0] // "color"

1.4.4 removeProperty()

removeProperty方法用于删除一条CSS属性,返回被删除的值。

// CSS代码为
// color:red;

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.removeProperty('color') // "red"

1.4.5 setProperty()

setProperty方法用于设置指定的CSS属性,没有返回值。

var styleObj = document.styleSheets[0].cssRules[1].style;
styleObj.setProperty('color', 'green', 'important');

下面是遍历一条CSS规则所有属性的例子。

var styleObj = document.styleSheets[0].cssRules[0].style;
for (var i = styleObj.length - 1; i >= 0; i--) {
   var nameString = styleObj[i];
   styleObj.removeProperty(nameString);
}

上面删除了一条CSS规则的所有属性,更简便的方法是设置cssText属性为空字符串。

styleObj.cssText = '';

2 window.getComputedStyle()

getComputedStyle方法接受一个DOM节点对象作为参数返回一个包含该节点最终样式信息的对象。所谓“最终样式信息”,指的是各种CSS规则叠加后的结果。

var div = document.querySelector('div');
window.getComputedStyle(div).backgroundColor

getComputedStyle方法还可以接受第二个参数,表示指定节点的伪元素。

var result = window.getComputedStyle(div, ':before');

getComputedStyle方法返回的是一个CSSStyleDeclaration对象。但是此时,这个对象是只读的,也就是只能用来读取样式信息,不能用来设置。如果想设置样式,应该使用Element节点的style属性。

var elem = document.getElementById("elem-container");
var hValue = window.getComputedStyle(elem,null).getPropertyValue("height");

3 window.matchMedia()

3.1 基本用法

window.matchMedia方法用来检查CSS的mediaQuery语句。各种浏览器的最新版本(包括IE 10+)都支持该方法,对于不支持该方法的老式浏览器,可以使用第三方函数库matchMedia.js。

CSS的mediaQuery语句有点像if语句,只要显示媒介(包括浏览器和屏幕等)满足mediaQuery语句设定的条件,就会执行区块内部的语句。下面是mediaQuery语句的一个例子。

@media all and (max-width: 700px) {
  body {
    background: #FF0;
  }
}

上面的CSS代码表示,该区块对所有媒介(media)有效,且视口的最大宽度不得超过700像素。如果条件满足,则body元素的背景设为#FF0。

需要注意的是,mediaQuery接受两种宽度/高度的度量,一种是上例的“视口”的宽度/高度,还有一种是“设备”的宽度/高度,下面就是一个例子。

@media all and (max-device-width: 700px) {
  body {
    background: #FF0;
  }
}

视口的宽度/高度(width/height)使用documentElement.clientWidth/clientHeight来衡量,单位是CSS像素;设备的宽度/高度(device-width/device-height)使用screen.width/height来衡量,单位是设备硬件的像素。

window.matchMedia方法接受一个mediaQuery语句的字符串作为参数,返回一个mediaQueryList对象。该对象有以下两个属性。

  • media:返回所查询的mediaQuery语句字符串。
  • matches:返回一个布尔值,表示当前环境是否匹配查询语句。
var result = window.matchMedia("(min-width: 600px)");
result.media // (min-width: 600px)
result.matches // true

下面是另外一个例子,根据mediaQuery是否匹配当前环境,执行不同的JavaScript代码。

var result = window.matchMedia('@media all and (max-width: 700px)');

if (result.matches) {
  console.log('页面宽度小于等于700px');
} else {
  console.log('页面宽度大于700px');
}

下面的例子根据mediaQuery是否匹配当前环境,加载相应的CSS样式表。

var result = window.matchMedia("(max-width: 700px)");

if (result.matches){
  var linkElm = document.createElement('link');
  linkElm.setAttribute('rel', 'stylesheet');
  linkElm.setAttribute('type', 'text/css');
  linkElm.setAttribute('href', 'small.css');

  document.head.appendChild(linkElm);
}

3.2 监听事件

window.matchMedia方法返回的MediaQueryList对象有两个方法,用来监听事件:addListener方法和removeListener方法。如果mediaQuery查询结果发生变化,就调用指定的回调函数。

var mql = window.matchMedia("(max-width: 700px)");

// 指定回调函数
mql.addListener(mqCallback);

// 撤销回调函数
mql.removeListener(mqCallback);

function mqCallback(mql) {
  if (mql.matches) {
    // 宽度小于等于700像素
  } else {
    // 宽度大于700像素
  }
}

上面代码中,回调函数的参数是MediaQueryList对象。回调函数的调用可能存在两种情况。一种是显示宽度从700像素以上变为以下,另一种是从700像素以下变为以上,所以在回调函数内部要判断一下当前的屏幕宽度。

4 CSS事件

4.1 transitionEnd事件

CSS的过渡效果(transition)结束后,触发transitionEnd事件。

el.addEventListener("transitionend", onTransitionEnd, false);

function onTransitionEnd() {
  console.log('Transition end');
}

transitionEnd的事件对象具有以下属性。

  • propertyName:发生transition效果的CSS属性名。
  • elapsedTime:transition效果持续的秒数,不含transition-delay的时间。
  • pseudoElement:如果transition效果发生在伪元素,会返回该伪元素的名称,以“::”开头。如果不发生在伪元素上,则返回一个空字符串。

实际使用transitionend事件时,需要添加浏览器前缀。

el.addEventListener('webkitTransitionEnd '
  + 'transitionend '
  + 'msTransitionEnd '
  + 'oTransitionEnd ', function(){
  el.style.transition = 'none';
});

4.2 animationstart事件,animationend事件,animationiteration事件

CSS动画有以下三个事件。

  • animationstart事件:动画开始时触发。
  • animationend事件:动画结束时触发。
  • animationiteration事件:开始新一轮动画循环时触发。如果animation-iteration-count属性等于1,该事件不触发,即只播放一轮的CSS动画,不会触发animationiteration事件。
div.addEventListener('animationiteration', function() {
  console.log('完成一次动画');
});

这三个事件的事件对象,都有animationName属性(返回产生过渡效果的CSS属性名)和elapsedTime属性(动画已经运行的秒数)。对于animationstart事件,elapsedTime属性等于0,除非animation-delay属性等于负值。


var el = document.getElementById("animation");

el.addEventListener("animationstart", listener, false);
el.addEventListener("animationend", listener, false);
el.addEventListener("animationiteration", listener, false);

function listener(e) {
  var li = document.createElement("li");
  switch(e.type) {
    case "animationstart":
      li.innerHTML = "Started: elapsed time is " + e.elapsedTime;
      break;
    case "animationend":
      li.innerHTML = "Ended: elapsed time is " + e.elapsedTime;
      break;
    case "animationiteration":
      li.innerHTML = "New loop started at time " + e.elapsedTime;
      break;
  }
  document.getElementById("output").appendChild(li);
}

上面代码的运行结果是下面的样子。

Started: elapsed time is 0
New loop started at time 3.01200008392334
New loop started at time 6.00600004196167
Ended: elapsed time is 9.234000205993652

animation-play-state属性可以控制动画的状态(暂停/播放),该属性需求加上浏览器前缀。

element.style.webkitAnimationPlayState = "paused";
element.style.webkitAnimationPlayState = "running";

猜你喜欢

转载自blog.csdn.net/u012060033/article/details/89792370