本內容是《Web前端開發之Javascript視頻》的課件,請配合大師哥《Javascript》視頻課程學習。
JavaScript也可以針對CSS進行編程,也就是所謂的腳本化CSS;通過腳本化CSS,同樣可以達到一系列的視覺效果;
在HTML中定義樣式的方式有3種:通過<link>元素包含外部樣式表文件、使用<style>元素定義嵌入式樣式、以及使用style特性定義特定元素的內聯樣式;
DOM2級樣式模塊圍繞這3種應用樣式的機制提供了一套API,可以檢測瀏覽器支持DOM2級定義的CSS能力;
var supportsDOM2CSS = document.implementation.hasFeature("CSS","2.0");
var supportsDOM2CSS2 = document.implementation.hasFeature("CSS2","2.0");
腳本化內聯樣式:
腳本化CSS最簡單直接的方式就是更改文檔元素的style屬性;任何支持style特性的HTML元素在Javascript中都有一個對應的style屬性,這個style屬性比較特殊,它不是字符串,而是一個CSSStyleDeclaration對象,包含著通過HTML的style特性指定的所有樣式信息,但不包含從外部樣式表或嵌入樣式表經層疊而來的樣式;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.style); // CSSStyleDeclaration
mydiv.style.fontSize = "24px";
mydiv.style.color = "purple";
style屬性作為CSSStyleDeclaration對象,其就代表了內聯樣式,其保存了所有的樣式屬性,但如果元素沒有設置style特性或沒有使用腳本設置該特性,style中的樣式屬性值均為空字符串;
只要取得一個有效的DOM元素的引用,就可以隨時使用Javascript為其設置樣式;
var myDiv = document.getElementById("myDiv");
myDiv.style.backgroundColor = "red";
myDiv.style.width = "100px";
myDiv.style.height = "200px";
myDiv.style.border = "1px solid black";
以這種方式改變樣式時,元素的外觀會自動被更新;
通過style對象,同樣可以取得style特性中指定的樣式;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.style.backgroundColor);
console.log(mydiv.style.width);
console.log(mydiv.style.height);
腳本化的CSS屬性的名稱和值:
在style特性中指定的任何CSS屬性都將表現為這個style對象的相應屬性;對于使用短劃線的CSS屬性名,必須將其轉換成駝峰大小寫形式,才能通過js來訪問,如:
CSS屬性 JS屬性
background-imagestyle.backgroundImage
color style.color
display style.display
font-family style.fontFamily
多數情況下,都可以通過簡單地轉換屬性名的格式來實現轉換,但是,當一個CSS屬性名在Javascript中如果是保留字或關鍵字時,在其前加”css”前綴,例如float屬性,由于float是JS中的保留字,因此不能被用作屬性名,其值應為cssFloat;低版本IE支持styleFloat;
mydiv.style.backgroundColor = "purple";
mydiv.style.borderRightStyle = "solid";
mydiv.style.borderRightColor = "green";
mydiv.style.cssFloat = "left";
mydiv.style.styleFloat = "left";
通過CSSStyleDeclaration對象設置style屬性值時,值都應該是字符串,都應該放到引號內,并且不帶分號;
在標準模式下,所有度量值都必須指定一個度量單位;在混合模式下,可以省略單位;
mydiv.style.width = 300; // 錯誤,但在混雜模式下默認為300px
mydiv.style.width = "300"; // 錯誤,但在混雜模式下默認為300px
通過計算得來的值,也要在最后加上單位;
var x = 10, leftMargin=20, leftBorder=10;
mydiv.style.left = (x + leftMargin + leftBorder) + "px";
帶單位唯一不好的地方就是,如果要獲取這個值,參與其他的數學運算,因為其是字符串,所以不能直接使用,必須轉換為數值才能參與運算,例如使用parseInt()或parseFloat()等方法進行轉換;
var rect = mydiv.getBoundingClientRect();
console.log(rect);
var borderWidth = parseFloat(mydiv.style.width);
console.log(borderWidth);
一些CSS屬性是復合屬性,比如:margin就是margin-top、margin-right、margin-bottom、margin-left的復合屬性;CSSStyleDeclaration對象也有與之對應的復合屬性;
mydiv.style.margin = "20px 30px 40px 50px";
mydiv.style.marginTop = "50px";
mydiv.style.marginLeft = "50px";
當設置復合屬性margin時,其會自動計算其所對應的相關聯的屬性;
即然style是元素的特性,那么也可以通過setAttribute()、getAttribute()等方法來設置style特性;
mydiv.setAttribute("style","width: 300px; height:200px; background-color: purple;");
console.log(mydiv.style);
console.log(mydiv.getAttribute("style"));
style對象的屬性和方法:
style對象中還定義一些屬性和方法,這些屬性和方法在提供元素的style特性值的同時,也可以修改樣式;
cssText:能夠訪問到style特性中的CSS代碼;
length:應用給元素的CSS屬性的數量;
parentRule:表示CSS信息的CSSRule對象;
getPropertyCSSValue(propertyName):返回包含給定的屬性的值CSSValue對象;已廢棄;
getPropertyPriority(propertyName);如果給定的屬性使用了!important設置,則返回important;否則返回空字符串;
getPropertyValue(propertyName):返回給定的屬性的值;
item(index):返回給定位置的CSS屬性的名;
removeProperty(propertyName):從樣式中刪除給定的屬性;
setProperty(propertyName,value,priority):為給定的屬性設置為屬性值,并加上優先權標志(”important”或一個空字符串);
cssText屬性:返回瀏覽器對style特性中CSS代碼的內部表示,在寫入模式下,賦給cssText的值會重寫整個style特性的值;
mydiv.style.cssText = "width: 300px; height:200px; background-color: purple;";
console.log(mydiv.style.cssText);
console.log(mydiv.getAttribute("style"));
設置cssText屬性的目的就是為元素快速應用多個CSS特性,可以一次性應用所有的變化;
item()方法和length屬性:設計length屬性的目的,就是將其與item()方法配套使用,以便迭代元素中定義的CSS屬性名;在使用length和item()時,style對象實際上是一個集合,可以使用方括號來代替item()來取得給定位置的css屬性名;
console.log(mydiv.style.length);
for(var i=0; i<mydiv.style.length; i++){
// console.log(mydiv.style.item(i));
console.log(mydiv.style[i]);
}
getPropertyValue(propertyName)方法:取得給定的屬性的值;
console.log(mydiv.style.getPropertyValue("background-color"));
for(var i=0; i<mydiv.style.length; i++){
var prop = mydiv.style[i]; // 取得屬性名
var value = mydiv.style.getPropertyValue(prop); // 取得屬性值
console.log(prop + ":" + value);
}
getPropertyCSSValue(propertyName)方法:該方法會返回一個包含兩個屬性的CSSValue對象,這兩個屬性分別是:cssText和cssValueType,其中cssText屬性的值與getPropertyValue()方法返回的值相同,而cssValueType屬性則是一個數值常量,表示值的類型:0表示繼承的值,1表示基本的值,2表示值列表,3表示自定義的值;
var value = mydiv.style.getPropertyCSSValue("background-color");
console.log(value);
console.log(value.cssText);
console.log(value.cssValueType);
這個方法已經被廢棄了,幾乎所有的瀏覽器都不支持;
getPropertyPriority(propertyName);如果給定的屬性使用了!important設置,則返回important;否則返回空字符串;
console.log(mydiv.style.getPropertyPriority("background-color")); // important
setProperty(propertyName,value,priority):為給定的屬性設置為屬性值,并加上優先權標志,priority 為可選(”important”或一個空字符串);
mydiv.style.setProperty("background-color","purple","important");
removeProperty(propertyName)方法:可以從元素的樣式中移除某個CSS屬性,移除一個屬性,意味著該屬性將應用默認的樣式(從其他樣式表經層疊而來);
mydiv.style.removeProperty("background-color");
parentRule:只讀,表示CSS信息的CSSRule對象;
var rule = mydiv.style.parentRule;
console.log(rule); // null
計算的樣式:
雖然style對象能夠提供style特性所有樣式信息,但它不包含那些從其他樣式表層疊而來并影響到當前元素的實際樣式信息;所以,需要使用計算樣式;
計算樣式是一組屬性值,它由瀏覽器通過把內聯樣式結合所有鏈接樣式表中所有可應用的樣式規則后導出(計算)得到的,也就是一組在呈現元素時實際使用的屬性;
getComputedStyle()方法:
該方法是window對象的方法,可以通過window.getComputedStyle(),或者
document.defaultView.getComputedStyle()方法調用,而document.defaultView的返回值就是window;
該方法接受兩個參數:要取得計算樣式的元素和一個偽元素字符串(如::after);如果不需要偽元素,第二個參數可以為null或一個空字符串;該方法返回一個CSSStyleDeclaration對象,與style屬性的類型相同,區別在于它是只讀的,其中包含當前元素的所有計算的樣式;
<style>
#mydiv{background-color: purple; width: 100px; height: 100px;}
</style>
<div id="mydiv" style="background: pink; border: 1px solid black;">mydiv</div>
<script>
var mydiv = document.getElementById("mydiv");
var computedStyle = document.defaultView.getComputedStyle(mydiv,null);
console.log(computedStyle);
console.log(computedStyle.backgroundColor);
console.log(computedStyle.width);
console.log(computedStyle.height);
console.log(computedStyle.border);
</script>
注:以上border屬性可能不會返回實際的border規則(如IE和Firefox返回空字符串),原因是不同瀏覽中解釋復合屬性的方式不同,因為設置這種屬性實際上會涉及很多其他屬性,例如:border,實際上調協了四個邊的邊框寬度、顏色等,因此border不會返回,但
computedStyle.borderleftWidth會返回值;
console.log(computedStyle.borderLeftWidth);
console.log(computedStyle.borderLeftColor);
另外,不同瀏覽器表示值的方式可能會有所區別;
計算后的樣式也包含屬于瀏覽器內部樣式表的樣式信息,因此任何具有默認值的CSS屬性都會表現在計算后的樣式中;如visibility屬性都有一個默認值,有些瀏覽器設置為visible,而有些設置為inherit;
計算樣式的CSSStyleDeclaration對象和表示內聯樣式的對象之間有一些重要的區別:
計算樣式的屬性是只讀的;
計算樣式的值是絕對值,類似百分比和點之類的相對的單位將全部轉換為絕對值;所有指定尺寸,例如外邊距大小和字體大小等屬性都有一個以像素為度量單位的值;相關顏色的屬性將以”rgb(#,#,#)”或”rgba(#,#,#,#)”的格式返回;
不計算復合屬性,它們只基于最基礎的屬性,例如,不要查詢margin屬性,應該使用marginLeft或marginTop等;
計算樣式的cssText屬性未定義(也就是該屬性返回空字符串);
計算樣式和內聯樣式可以同時使用;
// 用指定的因子縮放元素e的文本尺寸
function scale(e, factor){
// 用計算樣式查詢當前文本的尺寸
var size = parseInt(window.getComputedStyle(e,"").fontSize);
// 用內聯樣式來放大尺寸
e.style.fontSize = factor * size + "px";
}
// 用指定的因子修改元素的背景顏色
// factors > 1 顏色變淺,factors < 1顏色變暗
function scaleColor(e, factor){
var color = window.getComputedStyle(e,"").backgroundColor;
var components = color.match(/[\d\.]+/g); // 解析r、g、b分量
for(var i=0; i<3; i++){ // 循環r,g,b
var x = Number(components[i]) * factor; // 縮放每個值
x = Math.round(Math.min(Math.max(x, 0), 255)); // 設置邊界并取整
components[i] = String(x);
}
if(components.length == 3) // rgb()顏色
e.style.backgroundColor = "rgb(" + components.join() + ")";
else // rgba()顏色
e.style.backgroundColor = "rgba(" + components.join() + ")";
}
var mydiv = document.getElementById("mydiv");
scale(mydiv, 1.5);
scaleColor(mydiv, .5);
低版本的IE不支持getComputedStyle()方法,但它有一種類似的概念;在IE中,具有style屬性的元素還有一個currentStyle屬性,該屬性是CSSStyleDeclaration的實例,包含當前元素全部計算后的樣式,但只有IE支持;
var computedStyle = mydiv.currentStyle;
console.log(computedStyle.backgroundColor);
console.log(computedStyle.width);
console.log(computedStyle.height);
console.log(computedStyle.borderLeftWidth);
兼容函數:
function getStyle(obj, attr){
if(window.getComputedStyle)
return getComputedStyle(obj, null)[attr];
else
return obj.currentStyle[attr];
}
var mydiv = document.getElementById("mydiv");
var backgroundColor = getStyle(mydiv, "background-color");
console.log(backgroundColor); // rgb(245, 222, 179)
// 或者
function getCss(obj, css){
return (document.defaultView.getComputedStyle ?
document.defaultView.getComputedStyle(obj,null) :
obj.currentStyle)[css];
}
var borderTopWidth = getCss(mydiv, "border-top-width");
console.log(borderTopWidth); // 1px
封裝一下函數,用來獲取CSS屬性值,如:
function getComputedStyles(elem,prop) {
var cs = window.getComputedStyle(elem,null);
if (prop) {
console.log(prop+" : "+cs.getPropertyValue(prop));
return;
}
var len = cs.length;
for (var i=0;i<len;i++) {
var style = cs[i];
console.log(style+" : "+cs.getPropertyValue(style));
}
}
getComputedStyles(mydiv); // 查詢所有
getComputedStyles(mydiv,"background-color"); // 只查詢一個屬性
與偽元素一起使用:getComputedStyle可以從偽元素中提取樣式信息(例如:::after, ::before, ::marker, ::line-marker);
<style>
#mydiv::after{content: "大師哥王唯";}
</style>
<div id="mydiv"></div>
<script>
var mydiv = document.getElementById("mydiv");
var computedStyle = document.defaultView.getComputedStyle(mydiv,":after");
console.log(computedStyle.content);
<script>
使用計算樣式是可以獲取元素的幾何尺寸和位置的,但是其獲得的結果并不一定是我們所期望的,此時可以使用getBoundingClientRect(),其返回的值是與呈現的效果是一致的;
console.log(computedStyle.left); // auto
console.log(computedStyle.top); // auto
console.log(computedStyle.width); // 300px
// left:8 top:8 width:302,包括了border
var rect = mydiv.getBoundingClientRect();
console.log(rect);
腳本化CSS類:
也可以腳本化元素的class屬性,改變元素的class就改變了應用于元素的一組樣式表選擇器,它能在同一時刻改變多個CSS屬性;
className屬性:
與元素的class特性對應,即為元素指定的CSS類;由于class是ECMAScript保留字,所以在Javascript中使用className;
在操作類名時,需要通過className屬性添加、刪除和替換類名;
var mydiv = document.getElementById("mydiv");
mydiv.className = "container"; // 設置
mydiv.className = ""; // 刪除
mydiv.className = "other"; // 替換
// 或
if(mydiv.className == ""){
mydiv.className = "container";
}
元素可以設置多個CSS類,其className中保存的是擁有多個類名的字符串,因此即使只修改字符串一部分,都會覆蓋之前的值,所以每次都必須設置整個字符串的值;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.className); // db user disable
mydiv.className = "container";
console.log(mydiv.className); // container
如果要從class中只刪除一個類名,需要把多個類名拆開,刪除不想要的那個,然后再把其他類名拼成一個新字符串,如:
// 如,刪除user類
// 首先,取得類名字符串并拆分成數組
var mydiv = document.getElementById("mydiv");
var classNames = mydiv.className.split(/\s+/);
// 找到要刪的類名
var pos = -1, i, len;
for(i=0, len = classNames.length; i<len; i++){
if(classNames[i] == "user"){
pos = i;
break;
}
}
// 刪除類名
classNames.splice(i,1);
// 把剩下的類名拼成字符串并重新設置
mydiv.className = classNames.join(" ");
如果要添加類名,是可以直接通過拼接字符串完成,但在拼接之前,必須要通過檢測確定不會多次添加相同的類名;
Element.classList屬性:
HTML5新增了一種操作類名的方式,可以讓操作更簡單也更安全,即classList屬性,其是一個DOMTokenList對象,其是只讀的類數組對象,與其他DOM集合類似,它也有一個表示自己包含多少個元素的length屬性,而要取得每個元素可以使用item()方法,也可以使用方括號語法,此外,這個新類型還定義如下的方法:
- add(value):將給定的字符串值添加到列表中,如果值存在,就不添加;
- contains(value):表示列表中是否存在給定的值,如果存在返回true,否則,返回false;
- remove(value):從列表中刪除給定的字符串;
- toggle(value):如果列表中已經存在給定的值,刪除它,否則,添加它;
console.log(mydiv.classList); // DOMTokenList
mydiv.classList.add("container");
mydiv.classList.remove("container");
使用classList,可以確保其他類名不受此次修改的影響,可以極大地減少類似的基本操作的復雜性;
mydiv.classList.toggle("user"); // 切換user類
// 確定元素中是否包含既定的類名
if(mydiv.classList.contains("bd") && !mydiv.classList.contains("disabled")){
// To Do
}
// 迭代類名
for(var i=0,len=mydiv.classList.length; i<len; i++){
// To Do
console.log(mydiv.classList[i]);
}
有了classList屬性,除非需要全部刪除所有類名,或者完全重寫元素的class屬性,否則也就用不到className了;
需要確定的一點,classList這個DOMTokenList對象,它是實時的,如果className屬性改變了,它也會及時更新,同樣的,classList改變了,className屬性也會及時更新;
IE9以下的瀏覽器不支持classList屬性,可以自定義一個CSSClassList類,模擬DOMTokenList對象的方法;
function classList(e){
// 以下兩行先注釋,否則后面的toArray默認調用的是DOMTokenList對象的的toArray,而它并不存在
// 或者擴展內置的DOMTokenList的toArray
// if(e.classList) return e.classList; // 如果e.classList存在,則返回它
// else return new CSSClassList(e); // 否則,說偽造一個
return new CSSClassList(e);
}
// CSSClassList是一個模擬DOMTokenList的對象
function CSSClassList(e) { this.e = e;}
// 如果e.className包含類名c則返回true,否則返回false
CSSClassList.prototype.contains = function(c){
// 檢查c是否是合法的類名
if(c.length === 0 || c.indexOf(" ") != -1)
throw new Error("Invalid class name: '" + c + "'");
// 首先是常規檢查
var classes = this.e.className;
if(!classes) return false; // e不含類名
if(classes === c) return true; // e有一個完全匹配的類名
// 否則,把c自身看做一個單詞,利用正則表達式搜索c
return classes.search("\\b" + c + "\\b") != -1;
};
// 如果c不存在,將c添加到e.className中
CSSClassList.prototype.add = function(c){
if(this.contains(c)) return; // 如果存在,什么也不做
var classes = this.e.className;
if(classes && classes[classes.length - 1] != " ")
c = " " + c; // 如果需要加一個空格
this.e.className += c; // 將c添加到className中
};
// 將在e.className中出現的所有c都刪除
CSSClassList.prototype.remove = function(c){
if(c.length === 0 || c.indexOf(" ") != -1)
throw new Error("Invalid class name: '" + c + "'");
// 將所有作為單詞的c和多余的尾隨空格全部刪除
var pattern = new RegExp("\\b" + c + "\\b\\s*", "g");
this.e.className = this.e.className.replace(pattern, "");
};
// 如果c不存在,將c添加到e.className中,并返回true
// 否則,將e.className中出現的所有c都刪除,并返回false
CSSClassList.prototype.toggle = function(c){
if(this.contains(c)){ // 如果e.className包含類名c
thsi.remove(); // 刪除它
return false;
}else{
this.add(c); // 添加
return true;
}
};
// 返回e.className本身
CSSClassList.prototype.toString = function(){
return this.e.className;
};
// 返回在e.className中的類名
CSSClassList.prototype.toArray = function(){
return this.e.className.match(/\b\w+\b/g) || [];
};
// 應用
var mydiv = document.getElementById("mydiv");
var ccl = classList(mydiv);
console.log(ccl);
console.log(ccl.contains("newsdiv")); // true
ccl.add("topDiv");
ccl.remove("newsdiv");
ccl.toggle("newsdiv");
console.log(ccl.toString());
console.log(ccl.toArray());
腳本化樣式表:
在腳本化樣式表時,會使用到兩種類型的對象:
第一類是元素對象,包括通過<link>元素包含的樣式表和在<style>元素中定義的樣式表,這兩個元素本身是常規的文檔元素,分別是由HTMLLinkElement和HTMLStyleElement類型表示,它們都可以修改元素的特性,如果它們有id,可以通過getEleementById()來獲取它們;
// var mylink = document.getElementById("mylink");
var mylink = document.getElementsByTagName("link")[0];
console.log(mylink);
var mystyle = document.getElementsByTagName("style")[0];
console.log(mystyle);
所有瀏覽器都會包含<style>元素和rel特性被設置為stylesheet的<link>元素引入的樣式表;
第二類是CSSStyleSheet類型,表示樣式表本身;通過document.styleSheets屬性會返回一個只讀的類數組StyleSheetList對象集合,該集合具有length屬性和item()方法,集合內保存著CSSStyleSheet對象,表示與文檔關聯在一起的樣式表;
var styleList = document.styleSheets;
console.log(styleList); // StyleSheetList
console.log(styleList.length); // 3
console.log(styleList[0]); // CSSStyleSheet
// 遍歷
var sheet = null;
for(var i=0, len=document.styleSheets.length; i<len; i++){
sheet = document.styleSheets[i];
console.log(sheet.href);
}
可以直接通過HTMLLinkElement(<link>)或HTMLStyleElement(<style>)元素的sheet屬性獲取CSSStyleSheet對象;低版本的IE不支持sheet,但提供了一個同樣作用的styleSheet屬性;
var mylink = document.getElementById("mylink");
var mylink = document.getElementsByTagName("link")[0];
console.log(mylink.sheet); // CSSStyleSheet
console.log(mylink.styleSheet); // 在低版本的IE中返回CSSStyleSheet
var mystyle = document.getElementsByTagName("style")[0];
console.log(mystyle.sheet); // CSSStyleSheet
console.log(mystyle.styleSheet); // 在低版本的IE中返回CSSStyleSheet
兼容處理:
function getStyleSheet(element){
return element.sheet || element.styleSheet;
}
var link = document.getElementsByTagName("link")[0];
var sheet = getStyleSheet(link);
console.log(sheet.href);
在使用之前,檢測瀏覽器是否支持DOM2級樣式表;
var supportsDOM2StyleSheet = document.implementation.hasFeature("StyleSheets","2.0");
CSSStyleSheet對象:
接口代表一個 CSS 樣式表,并允許檢查和編輯樣式表中的規則列表;其繼承自StyleSheet接口,后者可以作為一個基礎接口來定義非CSS樣式表;從接口繼承的屬性如下:
disabled:表示樣式表是否被禁用的布爾值,R/W,將這個值設置為true可以禁用樣式表;
var styleList = document.styleSheets;
var ss = styleList[2];
console.log(ss.disabled);
ss.disabled = true; // 元素的樣式失效
// 封裝一個小函數,用來開啟或關閉樣式表
// 如果傳遞一個數字,將其當做document.styleSheets對象中一個索引
// 如果傳遞一個字符串,將其當作CSS選擇器并傳遞給document.querySelectorAll()
function disableStyleSheet(ss){
if(typeof ss === "number")
document.styleSheets[ss].disabled = true;
else{
var sheets = document.querySelectorAll(ss);
for(var i=0; i<sheets.length; i++)
sheets[i].disabled = true;
}
}
disableStyleSheet(0);
disableStyleSheet("style");
disableStyleSheet("link");
href:如果樣式表是通過<link>包含的,則是樣式表的URL,否則null;
media:當前樣式表支持的所有媒體類型的MediaList類數組集合;與所有DOM集合一樣,這個集合也有一個length屬性和一個item()方法;如果集合為空,表示樣式表適用于所有媒體;
<style media="screen and (min-width: 500px),tv and (max-width: 1000px)">
.container{width:300px;height:200px;background-color: salmon;}
</style>
<script>
var styleList = document.styleSheets;
var ss = styleList[2];
console.log(ss.media); // MediaList
console.log(ss.media.length); // 2
console.log(ss.media[0]); // screen and (min-width:500px)
console.log(ss.media.item(1)); // tv and (max-width:1000px)
MediaList對象還擁有mediaText屬性,返回元素media特性的值;
console.log(ss.media.mediaText);
MediaList對象擁有appendMedium(medium)和deleteMedium()方法,分別用作添加和刪除媒介;
ss.media.appendMedium("print");
ss.media.deleteMedium("tv and (max-width:1000px)");
一般來說,很少去操作media屬性;
ownerNode:指向擁有當前樣式表的節點的指針,樣式表可能是在HTML中通過<link>或<style>引入的,如果樣式表是其他樣式表是通過@import導入的,該屬性值為null,低版本IE不支持該屬性;
console.log(styleList[0].ownerNode); // link
console.log(styleList[1].ownerNode); // style
parentStyleSheet:在當前樣式表是通過@import導入的情況下,該屬性是一個指向導入它的樣式表的指針;
// styleList[1]獲取的是一個<style>其中使用@import導入一個CSS文件
console.log(styleList[1].cssRules[0]);
console.log(styleList[1].cssRules[0].parentStyleSheet); // CSSStyleSheet
title:ownerNode中title屬性的值;
type:表示樣式表類型的字符串,對CSS樣式表而言,是”text/css”;
注:除了disabled屬性之外,其他屬性都是只讀的;
操作樣式表規則:
除了以上所有這些屬性,CSSStyleSheet類型還定義了用來查詢、插入和刪除樣式表規則的API;
cssRules:返回樣式表中包含的所有樣式規則的CSSRuleList類型的實時集合,該集合中的元素為CSSStyleRule對象;低版本的IE不支持,但有個類似的rules屬性;
var ss = styleList[1];
console.log(ss);
console.log(ss.cssRules);
console.log(ss.rules); // 是IE專用
console.log(ss.cssRules[0]); // CSSStyleRule
ownerRule:如果樣式表是通過@import導入的,該屬性就是一個指針,返回表示導入的規則的CSSImportRule對象,否則為null,低版本的IE不支持;
insertRule(rule, index):創建(插入)規則,向CSSRules集合中指定的位置插入rule字符串,該方法接受兩個參數:規則文本和表示在哪里插入規則的索引;
var sheet = document.styleSheets[1];
sheet.insertRule("body{background-color:silver}",0);
console.log(sheet.cssRules);
低版本的IE支持一個類似的addRule(selector, style, index)方法,接受兩個必選和一個可選參數:選擇器和CSS樣式信息,一個可選參數:插入規則的位置;
document.styleSheets[1].addRule("h1","font-size:3em;color:red;",2);
console.log(document.styleSheets[1].cssRules);
這個方法所有瀏覽器也都支持;
跨瀏覽器方式:
var sheet = document.styleSheets[0];
function insertRule(sheet, selectorText, cssText, position){
if(sheet.insertRule){
sheet.insertRule(selectorText + "{" + cssText + "}", position);
}else{
sheet.addRule(selectorText, cssText, position);
}
}
insertRule(sheet, "body", "background-color:silver", 0);
deleteRule(index):刪除cssRules集合(樣式表)中指定位置的規則;低版本的IE不支持,但支持一個類似的removeRule()方法,這個方法所有瀏覽器也都支持;
document.styleSheets[1].deleteRule(0);
document.styleSheets[1].removeRule(0);
console.log(document.styleSheets[1].cssRules);
跨瀏覽器方式:
var sheet = document.styleSheets[0];
function deleteRule(sheet, index){
if(sheet.deleteRule){
sheet.deleteRule(index);
}else{
sheet.removeRule(index);
}
}
deleteRule(sheet,0);
CSSStyleRule規則對象:
CSSStyleRule對象表示樣式表中的每一條規則;繼承自CSSRule接口,實際上CSSRule是專供其他類型繼承的基類,其中最常見的是CSSStyleRule類型,表示樣式信息;
var sheet = document.styleSheets[2];
var rules = sheet.cssRules || sheet.rules;
var rule = rules[0];
console.log(rule); // CSSStyleRule
CSSRule接口屬性:
- cssText:返回整條規則對應的文本;低版本的IE不支持
- parentRule:只讀,如果當前規則是導入的規則,這個屬性引用的就是導入規則,否則為null;或此規則是 @media 塊中的樣式規則, 則其父規則將是該 CSSMediaRule;IE不支持
- parentStyleSheet:當前規則所屬的樣式表,低版本的IE不支持;
- type:表示規則類型的常量值,對于樣式規則,值為1;IE不支持;
這些常量被定義在CSSRule接口中,值為:
常量值接口
- CSSRule.STYLE_RULE1CSSStyleRule
- CSSRule.IMPORT_RULE3CSSImportRule
- CSSRule.MEDIA_RULE4CSSMediaRule
- CSSRule.FONT_FACE_RULE5CSSFontFaceRule
- CSSRule.PAGE_RULE6CSSPageRule
- CSSRule.KEYFRAMES_RULE7CSSKeyframesRule
- CSSRule.KEYFRAME_RULE8CSSKeyframeRule
- 9 保留供將來使用
- CSSRule.NAMESPACE_RULE10CSSNamespaceRule
- CSSRule.COUNTER_STYLE_RULE11CSSCounterStyleRule
- CSSRule.SUPPORTS_RULE12CSSSupportsRule
- CSSRule.DOCUMENT_RULE13CSSDocumentRule
- CSSRule.FONT_FEATURE_VALUES_RULE14
- CSSRule.VIEWPORT_RULE15CSSViewportRule
- CSSRule.REGION_STYLE_RULE16CSSRegionStyleRule
- CSSRule.UNKNOWN_RULE0CSSUnknownRule
- CSSRule.CHARSET_RULE2CSSCharsetRule
CSSStyleRule對象屬性:
- selectorText:只讀,返回當前規則的選擇器;
- style:只讀,返回一個CSSStyleDeclaration對象,可以通過它設置和取得規則中特定的樣式值;
- styleMap:一個StylePropertyMap對象;
console.log(rule.cssText); // 定義規則的字符串
console.log(rule.parentRule);
console.log(rule.parentStyleSheet); // CSSStyleSheet
console.log(rule.selectorText); // 選擇器
console.log(rule.style); // CSSStyleDeclaration
console.log(rule.styleMap); // StylePropertyMap
console.log(rule.type); // 1
最常用的是cssText、selectorText和style這三個屬性;cssText屬性與style.cssText屬性類似,但并不相同,前者包含選擇器和圍繞樣式信息的花括號,后者只包含樣式信息;cssText是只讀的,style.cssText是可寫的;
console.log(rule.cssText); // .container{color:white}
console.log(rule.style.cssText); // color:white
rule.style.cssText = "background-color:purple";
console.log(rule.cssText); // .container{background-color:purple;}
console.log(rule.style.cssText); // background-color:purple
rule.style.cssText += "color:white;";
大多數情況下,僅使用style屬性就可以滿足所有操作樣式規則的需求了;這個對象就像每個元素上的style屬性一樣,可以通過它讀取和修改規則中的樣式信息;
console.log(rule.style.width);
console.log(rule.style.height);
rule.style.backgroundColor = "lightgray";
console.log(rule.style.cssText);
CSSStyleRule對象的style屬性,使用方式和內聯style對象的使用方式是一致的,但要注意,一個是規則對象的style屬性對象,一個是內聯style對象;
// 遍歷樣式表的規則
var ss = document.styleSheets[0]; // 第一個樣式表
var rules = ss.cssRules ? ss.cssRules : ss.rules; // 樣式表規則
for(var i=0; i<rules.length; i++){
var rule = rules[i];
if(!rule.selectorText) continue; // 跳過@import和非樣式規則
var selector = rule.selectorText; // 選擇器
var ruleText = rule.style.cssText; // 文本形式的樣式
// 如果規則應用在h1元素上,也將其應用到h2元素上
// 注意,僅當選擇器在字面上為h1時這才起作用
if(selector == "h1"){
if(ss.insertRule)
ss.insertRule("h2 {" + ruleText + "}", rules.length);
else if(ss.addRule)
ss.addRule("h2", ruleText, rules.length);
}
// 如果規則設置了text-decoration屬性,則將其刪除
if(rule.style.textDecoration){
if(ss.deleteRule)
ss.deleteRule(i);
else if(ss.removeRule)
ss.removeRule(i);
i--; // 調整循環索引,因為以上的規則i+1現在即為規則i
}
}
創建新樣式表:
可以創建一個新樣式表并將其添加到文檔中;使用DOM技術,創建一個<style>元素,并將其插入到文檔的頭部,然后再用其innerHTML屬性來設置樣式表內容;在低版本的IE中,CSSStyleSheet對象通過非標準方法document.createStyleSheet()來創建,其樣式文本用cssText屬性值為指定;
// 創建一個新樣式表
// 對文檔添加一個樣式表,用指定的樣式填充它
// style參數可能是字符串或對象,如果它是字符串,就把它作為樣式表的文本
// 如果它是對象,將每個定義樣式規則的每個屬性添加到樣式表中
// 屬性名即為選擇器,其值即為對應的樣式
function addStyles(styles){
var styleElt, styleeSheet; // 先創建一個新樣式表
if(document.createStyleSheet) // 如果是IE
styleSheet = document.createStyleSheet();
else{
var head = document.getElementsByTagName("head")[0];
styleElt = document.createElement("style"); // 新的<style>元素
head.appendChild(styleElt);
// 這個新樣式表應該是最后一個
styleSheet = document.styleSheets[document.styleSheets.length - 1];
}
// 向其中插入樣式
if(typeof styles === "string"){
if(styleElt)
styleElt.innerHTML = styles;
else
styleSheet.cssText = styles; // IE
}else{ // 參數是規則對象
var i = 0;
for(selector in styles){
if(styleSheet.insertRule){
var rule = selector + "{" + styles[selector] + "}";
styleSheet.insertRule(rule, i++);
}else{
styleSheet.addRule(selector, styles[selector], i++);
}
}
}
}
// 應用
var styles = "h2 {font-size: 2em; color: red;}";
addStyles(styles);
var rule = document.styleSheets[1].cssRules[0];
addStyles(rule);
CSS動畫:腳本化CSS的最常見的用途之一就是產生視覺動畫效果;其原理是使用setTimeout()或setInterval()重復調用函數來修改元素的內聯樣式,以達到產生視覺差的動畫效果;
// 將e轉化為相對定位的元素,使之左右震動
// 第一個參數可以是元素對象也可以是元素的id
// 第二個參數是回調函數,將以e為參數,將在動畫結束時調用
// 第三個參數指定e震動的距離,默認是5px
// 第四個參數指定震動多久,默認是500ms
function shake(e, oncomplete, distance, time){
if(typeof e === "string") e = document.getElementById(e);
if(!time) time = 500;
if(!distance) distance = 5;
var originalStyle = e.style.cssText; // 保存e的原始style
e.style.position = "relative"; // 使e相對定位
var start = (new Date()).getTime(); // 動畫的開始時間
animate(); // 開始動畫
// 函數檢檢查消耗的時間,并更新e的位置
// 如果動畫完成,它將e還原為原始狀態
// 否則,它更新e的位置,安排它自身重新運行
function animate(){
var now = (new Date()).getTime(); // 得到當前時間
var elapsed = now - start; // 從開始以來消耗了多長時間
var fraction = elapsed / time; // 是總時間的幾分之幾
if(fraction < 1){ // 如果動畫未完成
// 作為動畫完成比例的函數,計算e的位置
// 使用正弦函數將完成比例乘以4pi,所以它來回往復兩次
var x = distance * Math.sin(fraction * 4 * Math.PI);
e.style.left = x + "px";
// 在25ms后或在總時間的最后嘗試再次運行函數
// 目的是為了產生每秒40幀的動畫
setTimeout(animate, Math.min(25, time - elapsed));
}else{
e.style.cssText = originalStyle; // 恢復原始樣式
if(oncomplete) // 調用回調函數
oncomplete(e);
}
}
}
// 應用
var mydiv = document.getElementById("mydiv");
shake(mydiv,function(e){console.log(e.style)},5,500);
// 以毫秒級的時間將e從完全不透明談出到完全透明
// 在調用函數時假設e是完全不透明
// oncomplete是一個可選的函數,以e為參數,它將在動畫結束時調用
// 如果不指定time,默認為500ms
function fadeOut(e, oncomplete, time){
if(typeof e === "string") e = document.getElementById(e);
if(!time) time = 500;
// 使用Math.sqrt作為一個簡單的緩動函數來創建動畫
// 非線性,由快到慢
var ease = Math.sqrt;
var start = (new Date()).getTime(); // 動畫的開始時間
animate(); // 開始動畫
function animate(){
var elapsed = (new Date()).getTime() - start; // 消耗時間
var fraction = elapsed / time; // 總時間的幾分之幾
if(fraction < 1){ // 如果動畫未完成
var opacity = 1 - ease(fraction); // 計算元素的不透明度
e.style.opacity = String(opacity); // 設計不透明度
setTimeout(animate, Math.min(25, time - elapsed));
}else{
e.style.opacity = "0"; // 完全透明
if(oncomplete)
oncomplete(e);
}
}
}
fadeOut(mydiv,null,500);
版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。