## 9.1 CSS Style sheet overview
A style sheet is added to an HTML document by either using the *HTMLLinkElement* node (i.e. *`<link href="stylesheet.css" rel="stylesheet" type="text/css">`*) to include an external style sheet or the*HTMLStyleElement* node (i.e. *`<style></style>`*) to define a style sheet inline. In the HTML document below both of these *Element* node's are in the DOM and I verify which constructor, constructs these nodes.
live code: [http://jsfiddle.net/domenlightenment/yPYyC](http://jsfiddle.net/domenlightenment/yPYyC)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<link id="linkElement" href="http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css" rel="stylesheet" type="text/css">
<style id="styleElement">
body{background-color:#fff;}
</style>
</head>
<body>
<script>
//logs function HTMLLinkElement() { [native code] }
console.log(document.querySelector('#linkElement').constructor);
//logs function HTMLStyleElement() { [native code] }
console.log(document.querySelector('#styleElement').constructor);
</script>
</body>
</html>
~~~
Once a style sheet is added to an HTML document its represented by the *CSSStylesheet* object. Each CSS rule (e.g. *body{background-color:red;}*) inside of a style sheet is represent by a *CSSStyleRule* object. In the code below I verify which constructor constructed the style sheet and each CSS rule (selector & its css properties and values) in the style sheet.
live code: [http://jsfiddle.net/domenlightenment/UpLzm](http://jsfiddle.net/domenlightenment/UpLzm)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<style id="styleElement">
body{background-color:#fff;}
</style>
</head>
<body>
<script>
//logs function CSSStyleSheet() { [native code] } because this object is the stylesheet itself
console.log(document.querySelector('#styleElement').sheet.constructor);
//logs function CSSStyleRule() { [native code] } because this object is the rule inside of the style sheet
console.log(document.querySelector('#styleElement').sheet.cssRules[0].constructor);
</script>
</body>
</html>
~~~
Keep in mind that selecting the element that includes the style sheet (i.e. *`<link>`* or *`<style>`*) is not the same as accessing the actual object (*CSSStyleSheet*) that represents the style sheet itself.
## 9.2 Accessing all style sheets (i.e. *CSSStylesheet* objects) in the DOM
*document.styleSheets* gives access to a list of all style sheet objects (aka *CSSStylesheet*) explicitly linked (i.e.*`<link>`*) or embedded (i.e. *`<style>`*) in an HTML document. In the code below *styleSheets* is leverage to gain access to all of the style sheets contained in the document.
live code: N/A
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<link href="http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css" rel="stylesheet" type="text/css">
<style>
body{background-color:red;}
</style>
</head>
<body>
<script>
console.log(document.styleSheets.length); //logs 2
console.log(document.styleSheets[0]); // the <link>
console.log(document.styleSheets[1]); // the <style>
</script>
</body>
</html>
~~~
### Notes
*styleSheet* is live just like other node lists
The *length* property returns the number of stylesheets contained in the list starting at 0 index (i.e.*document.styleSheets.length*)
The style sheets included in a *styleSheets* list typically includes any style sheets created using the *`<style>`* element or using a *`<link>`* element where *rel* is set to *"stylesheet"*
In addtion to using *styleSheets* to access a documents styles sheets its also possible to access a style sheet in an HTML document by first selecting the element in the DOM (*`<style>`* or *`<link>`*) and using the *.sheet* property to gain access to the *CSSStyleSheet* object. In the code below I access the style sheets in the HTML docment by first selecting the element used to include the style sheet and then leveraging the *sheet* property.
live code: [http://jsfiddle.net/domenlightenment/jFwKw](http://jsfiddle.net/domenlightenment/jFwKw)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<link id="linkElement" href="http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css" rel="stylesheet" type="text/css">
<style id="styleElement">
body{background-color:#fff;}
</style>
</head>
<body>
<script>
//get CSSStylesheeet object for <link>
console.log(document.querySelector('#linkElement').sheet); //same as document.styleSheets[0]
//get CSSSstylesheet object for <style>
console.log(document.querySelector('#styleElement').sheet); //same as document.styleSheets[1]
</script>
</body>
</html>
~~~
## 9.3 CSSStyleSheet properties and methods
To get accurate information pertaining to the available properties and methods on an *CSSStyleSheet* node its best to ignore the specification and to ask the browser what is available. Examine the arrays created in the code below detailing the properties and methods available from a *CSSStyleSheet* node.
live code: [http://jsfiddle.net/domenlightenment/kNyL2](http://jsfiddle.net/domenlightenment/kNyL2)
~~~
<!DOCTYPE html>
<html lang="en">
<head><style id="styleElement">body{background-color:#fff;}</style></head>
<body>
<script>
var styleSheet = document.querySelector('#styleElement').sheet;
//text own properties
console.log(Object.keys(styleSheet).sort());
//text own properties & inherited properties
var styleSheetPropertiesIncludeInherited = [];
for(var p in styleSheet){
styleSheetPropertiesIncludeInherited.push(p);
}
console.log(styleSheetPropertiesIncludeInherited.sort());
//text inherited properties only
var styleSheetPropertiesOnlyInherited = [];
for(var p in styleSheet){
if(!styleSheet.hasOwnProperty(p)){
styleSheetPropertiesOnlyInherited.push(p);
}
}
console.log(styleSheetPropertiesOnlyInherited.sort());
</script>
</body>
</html>
~~~
A *CSSStyleSheet* object accessed from a *styleSheets* list or via the *.sheet* property has the following properties and methods:
* *disabled*
* *href*
* *media*
* *ownerNode*
* *parentStylesheet*
* *title*
* *type*
* *cssRules*
* *ownerRule*
* *deleteRule*
* *inserRule*
### Notes
*href*, *media*, *ownerNode*, *parentStylesheet*, *title*, and *type* are read only properties, you can't set its value using these properteis
## 9.4 CSSStyleRule overview
A *CSSStyleRule* object represents each CSS rule contained in a style sheet. Basicly a *CSSStyleRule* is the interface to the CSS properties and values attached to a selector. In the code below we programaticlly access the details of each rule contained in the inline style sheet by accessing the *CSSStyleRule* object that represents the CSS rule in the style sheet.
live code: [http://jsfiddle.net/domenlightenment/fPVS8](http://jsfiddle.net/domenlightenment/fPVS8)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<style id="styleElement">
body{background-color:#fff;margin:20px;} /*this is a css rule*/
p{line-height:1.4em; color:blue;} /*this is a css rule*/
</style>
</head>
<body>
<script>
var sSheet = document.querySelector('#styleElement');
console.log(sSheet.cssRules[0].cssText); //logs "body { background-color: red; margin: 20px; }"
console.log(sSheet.cssRules[1].cssText); //logs "p { line-height: 1.4em; color: blue; }"
</script>
</body>
</html>
~~~
## 9.5 *CSSStyleRule* properties and methods
To get accurate information pertaining to the available properties and methods on an *CSSStyleRule* node its best to ignore the specification and to ask the browser what is available. Examine the arrays created in the code below detailing the properties and methods available from a *CSSStyleRule*node.
live code: [http://jsfiddle.net/domenlightenment/hCX3U](http://jsfiddle.net/domenlightenment/hCX3U)
~~~
<!DOCTYPE html>
<html lang="en">
<head><style id="styleElement">body{background-color:#fff;}</style></head>
<body>
<script>
var styleSheetRule = document.querySelector('#styleElement').sheet.cssRule;
//text own properties
console.log(Object.keys(styleSheetRule).sort());
//text own properties & inherited properties
var styleSheetPropertiesIncludeInherited = [];
for(var p in styleSheetRule){
styleSheetRulePropertiesIncludeInherited.push(p);
}
console.log(styleSheetRulePropertiesIncludeInherited.sort());
//text inherited properties only
var styleSheetRulePropertiesOnlyInherited = [];
for(var p in styleSheetRule){
if(!styleSheetRule.hasOwnProperty(p)){
styleSheetRulePropertiesOnlyInherited.push(p);
}
}
console.log(styleSheetRulePropertiesOnlyInherited.sort());
</script>
</body>
</html>
~~~
Scripting the rules (e.g. *body{background-color:red;}*) contained inside of a style sheet is made possible by the *CSSrule* object. This object provides the following properties:
* *cssText*
* *parentRule*
* *parentStylesSheet*
* *selectorText*
* *style*
* *type*
## 9.6 Getting a list of CSS Rules in a style sheet using *CSSRules*
As previously discussed the *styleSheets* list provides a list of style sheets contained in a document. The*CSSRules* list provides a list (aka *CSSRulesList*) of all the CSS rules (i.e. *CSSStyleRule* objects) in a specific style sheet. The code below logs a *CSSRules* list to the console.
live code: [http://jsfiddle.net/domenlightenment/qKqhJ](http://jsfiddle.net/domenlightenment/qKqhJ)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<style id="styleElement">
body{background-color:#fff;margin:20px;}
p{line-height:1.4em; color:blue;}
</style>
</head>
<body>
<script>
var sSheet = document.querySelector('#styleElement').sheet;
//array like list containing all of the CSSrule objects repreesenting each CSS rule in the style sheet
console.log(sSheet.cssRules);
console.log(sSheet.cssRules.length); //logs 2
//rules are index in a CSSRules list starting at a 0 index
console.log(sSheet.cssRules[0]); //logs first rule
console.log(sSheet.cssRules[1]); //logs second rule
</script>
</body>
</html>
~~~
## 9.7 Inserting & deleting CSS rules in a style sheet using *.insertRule()*and *.deleteRule()*
The *insertRule()* and *deleteRule()* methods provided the ability to programatically manipulate the CSS rules in a style sheet. In the code below I use *insertRule()* to add the css rule *p{color:red}* to the inline style sheet at index 1\. Remeber the css rules in a style sheet are numerical index starting at 0\. So by inserting a new rule at index 1 the current rule at index 1 (i.e. *p{font-size:50px;}*) is push to index 2.
live code: [http://jsfiddle.net/domenlightenment/T2jzJ](http://jsfiddle.net/domenlightenment/T2jzJ)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<style id="styleElement">
p{line-height:1.4em; color:blue;} /*index 0*/
p{font-size:50px;} /*index 1*/
</style>
</head>
<body>
<p>Hi</p>
<script>
//add a new CSS rule at index 1 in the inline style sheet
document.querySelector('#styleElement').sheet.insertRule('p{color:red}',1);
//verify it was addedconsole.log(document.querySelector('#styleElement').sheet.cssRules[1].cssText);
//Delete what we just added
document.querySelector('#styleElement').sheet.deleteRule(1);
//verify it was removedconsole.log(document.querySelector('#styleElement').sheet.cssRules[1].cssText);
</script>
</body>
</html>
~~~
Deleting or removing a rule is as simple as calling *deleteRule()* method on a style sheet and passing it the index of the rule in the style sheet to be deleted.
### Notes
Inserting and deleting rules is not a common practice given the difficulty around managing the cascaade and using a numeric indexing system to update a style sheet (i.e. determining at what index a style is located without previewing the contents of the style sheet itself.). Its much simpler working with CSS rules in CSS and HTML files before they are served to a client than programaticlly altering them in the client after the fact.
## 9.8 Editing the value of a *CSSStyleRule* using the *.style* property
Just like the *.style* property that facilitates the manipulation of inline styles on element nodes there is a also*.style* property for *CSSStyleRule* objects that orchestrates the same manipulation of styles in style sheets. In the code below I levereage the *.style* property to set and get the value of css rules contained in the inline style sheet.
live code: [http://jsfiddle.net/domenlightenment/aZ9CQ](http://jsfiddle.net/domenlightenment/aZ9CQ)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<style id="styleElement">
p{color:blue;}
strong{color:green;}
</style>
</head>
<body>
<p>Hey <strong>Dude!</strong></p>
<script>
var styleSheet = document.querySelector('#styleElement').sheet;
//Set css rules in stylesheet
styleSheet.cssRules[0].style.color = 'red';
styleSheet.cssRules[1].style.color = 'purple';
//Get css rules
console.log(styleSheet.cssRules[0].style.color); //logs 'red'
console.log(styleSheet.cssRules[1].style.color); //logs 'purple'
</script>
</body>
</html>
~~~
## 9.9 Creating a new inline CSS style sheets
To craft a new style sheet on the fly after an html page is loaded one only has to create a new *`<style>`* node, add CSS rules using *innerHTML* to this node, then append the*`<style>`* node to the HTML document. In the code below I programatily craft a style sheet and add the *body{color:red}* CSS rule to the style sheet, then append the stylesheet to the DOM.
live code: [http://jsfiddle.net/domenlightenment/bKXAk](http://jsfiddle.net/domenlightenment/bKXAk)
~~~
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<p>Hey <strong>Dude!</strong></p>
<script>
var styleElm = document.createElement('style');
styleElm.innerHTML = 'body{color:red}';
//notice markup in the document changed to red from our new inline stylesheet
document.querySelector('head').appendChild(styleElm);
</script>
</body>
</html>
~~~
## 9.10 Programatically adding external style sheets to an HTML document
To add a CSS file to an HTML document programatically a *`<link>`* element node is created with the appropriate attributes and then the *`<link>`* element node is appended to the DOM. In the code below I programatically include an external style sheet by crafting a new *`<link>`* element and appending it to the DOM.
live code: [http://jsfiddle.net/domenlightenment/dtwgC](http://jsfiddle.net/domenlightenment/dtwgC)
~~~
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<script>
//create & add attributes to <link>
var linkElm = document.createElement('link');linkElm.setAttribute('rel', 'stylesheet');linkElm.setAttribute('type', 'text/css');
linkElm.setAttribute('id', 'linkElement');linkElm.setAttribute('href', 'http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css');
//Append to the DOM
document.head.appendChild(linkElm);
//confrim its addition to the DOM
console.log(document.querySelector('#linkElement'));
</script>
</body>
</html>
~~~
## 9.11 Disabling/Enabling style sheets using *disabled* property
Using the *.disabled* property of a *CSSStyleSheet* object its possible to enable or disabled a style sheet. In the code below we access the current disabled value of each style sheet in the document then proceed to disabled each style sheet leveraging the *.disabled* property.
live code: [http://jsfiddle.net/domenlightenment/L952Z](http://jsfiddle.net/domenlightenment/L952Z)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<link id="linkElement" href="http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css" rel="stylesheet" type="text/css">
<style id="styleElement">
body{color:red;}
</style>
</head>
<body>
<script>
//Get current boolean disabled value
console.log(document.querySelector('#linkElement').disabled); //log 'false'
console.log(document.querySelector('#styleElement').disabled); //log 'false'
//Set disabled value, which of courese disabled all styles for this document
document.document.querySelector('#linkElement').disabled = true;
document.document.querySelector('#styleElement').disabled = true;
</script>
</body>
</html>
~~~
### Notes
Disabled is not an avaliable attributre of a or element according to the specification. Trying to add this as an attribute in the HTML document itself will fail (and likley cause parsing errors where styles are ignored) in the majority of modern browsers in use today.
- Foreword
- Introduction
- Preface
- About the Author
- Chapter 1 - Node Overview
- Chapter 2 - Document Nodes
- Chapter 3 - Element Nodes
- Chapter 4 - Element Node Selecting
- Chapter 5 - Element Node Geometry & Scrolling Geometry
- Chapter 6 - Element Node Inline Styles
- Chapter 7 - Text Nodes
- Chapter 8 - DocumentFragment Nodes
- Chapter 9 - CSS Style Sheets & CSS rules
- Chapter 10 - JavaScript in the DOM
- Chapter 11 - DOM Events
- Chapter 12 - Creating dom.js - a wishful jQuery inspired DOM Library for modern browers