Creating a Style Sheet
With an understanding of what a style sheet is fresh in your memory, you can actually begin the process of making one for your SVG content. You can start by creating an internal CSS style sheet.
To make sense of all this style information, you can modify the raindrop example from last hour, shown in Figure 6.1. Using Listing 5.10 as a foundation, you'll need to insert a style element into your new document (line 6 in Listing 6.1). Within this element, you will need to insert a CDATA section (line 7), which alerts the SVG viewer not to parse its contents.
Figure 6.1 An internal style sheet can provide the information to paint this raindrop.
Now it's time to create a rule. First take the two style declarations used to create the appearance of a yellow fill and a black stroke to create a declaration block on line 8. Then create a selector name, such as style1, to label this block. Lastly, use the class attribute (instead of the style property, as Listing 5.8 showed) to associate your new style with the path element on line 12.
Listing 6.1 Using a Style Sheet to Define an Object's Style
01: <?xml version="1.0" standalone="no"?> 02: <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> 03: 04: <svg width="500" height="300"> 05: 06: <style type="text/css"> 07: <![CDATA[ 08: .style1 {stroke:black; fill:yellow;} 09: ]]> 10: </style> 11: 12: <path class="style1" d="M250,140 c 0,0 -16,24 -16,33 c 0,9 7,15 16,15 c 9,0 16,-7 16,-15 c 0,-9 -16,-33 -16,-33"/> 13: 14: </svg>
Your style sheet now contains all your style information for the raindrop. Now, to demonstrate the efficiency of CSS style sheet application, you can create two more raindrops, each using the same class.
First, take Listing 6.1 and duplicate (via a copy and paste) the raindrop path twice. As you were working with relative path coordinates, you can change the first coordinates of the first drop (line 12 in Listing 6.2) and the last drop (line 16) by 100 horizontal pixels. Subsequently, that path's coordinates will follow the lead of their first coordinate, creating three evenly spaced drops in a straight horizontal line (see Figure 6.2).
Figure 6.2 An internal style sheet can provide the same information to paint several pieces of artwork.
As you duplicated the original drop, the two new drops will already have the class="style1" code applied. Now, load this new document in your browser, and you should see results similar to Figure 6.2.
Listing 6.2 Using a Style Sheet to Define an Object's Style
01: <?xml version="1.0" standalone="no"?> 02: <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> 03: 04: <svg width="500" height="300"> 05: 06: <style type="text/css"> 07: <![CDATA[ 08: .style1 {stroke:black; fill:yellow;} 09: ]]> 10: </style> 11: 12: <path class="style1" d="M150,140 c 0,0 -16,24 -16,33 c 0,9 7,15 16,15 c 9,0 16,-7 16,-15 c 0,-9 -16,-33 -16,-33"/> 13: 14: <path class="style1" d="M250,140 c 0,0 -16,24 -16,33 c 0,9 7,15 16,15 c 9,0 16,-7 16,-15 c 0,-9 -16,-33 -16,-33"/> 15: 16: <path class="style1" d="M350,140 c 0,0 -16,24 -16,33 c 0,9 7,15 16,15 c 9,0 16,-7 16,-15 c 0,-9 -16,-33 -16,-33"/> 17: 18: </svg>
Now you've successfully created a style sheet and figured out how to apply one of its classes to your artwork. Your next step will be to create multiple classes.
In Listing 6.2, you added two new raindrops to your document. If you decided that you wanted to change the appearance of these two new drops, giving one a black stroke and no designated fill and another a yellow fill but no black stroke, you would need to create two new classes.
To do so, duplicate the style1 rule twice and rename the two resulting rules' selectors style2 and style3 respectively. Listing 6.3 shows these two new rules on lines 9 and 10. Make each style unique by deleting the fill:yellow; declaration from the style2 class and the stroke:black; declaration from the style3 class. Finally, apply style2 to the second drop (line 16) and style3 to the third drop (line 18). When you're done, your results should look like Figure 6.3.
Listing 6.3 Using a Style Sheet to Define Several Different Objects' Style
01: <?xml version="1.0" standalone="no"?> 02: <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> 03: 04: <svg width="500" height="300"> 05: 06: <style type="text/css"> 07: <![CDATA[ 08: .style1 {stroke:black; fill:yellow;} 09: .style2 {stroke:black;} 10: .style3 {fill:yellow;} 11: ]]> 12: </style> 13: 14: <path class="style1" d="M150,140 c 0,0 -16,24 -16,33 c 0,9 7,15 16,15 c 9,0 16,-7 16,-15 c 0,-9 -16,-33 -16,-33"/> 15: 16: <path class="style2" d="M250,140 c 0,0 -16,24 -16,33 c 0,9 7,15 16,15 c 9,0 16,-7 16,-15 c 0,-9 -16,-33 -16,-33"/> 17: 18: <path class="style3" d="M350,140 c 0,0 -16,24 -16,33 c 0,9 7,15 16,15 c 9,0 16,-7 16,-15 c 0,-9 -16,-33 -16,-33"/> 19: 20: </svg>
Figure 6.3 Each raindrop is using a unique class to define its appearance.
Although this method accomplishes the goal of creating three differently styled objects, you've ended up duplicating your style declarations several times. Rather than defining your rules with multiple style declarations, you can instead give each declaration its own rule, allowing you the flexibility to change an object's appearance without first creating a new rule.
By naming each style declaration, you can free yourself to make class combinations on the artwork's element rather than inside the style sheet. As an example, consider an instance where you want to change the color of an object in your artwork. First, you must find the object you wish to modify. Once found, you see which selector name is being referenced, and then you must double back to your style sheet to modify the appropriate rules.
Instead of darting back and forth between two locations in your code (or in some cases between two documents, should you be using an external style sheet), you can simply replace one selector name with another if you have a unique selector name for each declaration (several fills, in this instance). By keeping the groupings of an object's style on the object level, rather than on the style sheet level, you are afforded a greater control over your artwork, allowing you to quickly edit it.
Try this out by creating a new document based on Listing 6.3. First, delete the style1 class, and then apply both style2 and style3 to the first raindrop. To apply more than one class to an object, separate class attribute values with a space (see line 14 of Listing 6.4).
Listing 6.4 Associating Only One Declaration with Each Selector
01: <?xml version="1.0" standalone="no"?> 02: <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" 03: "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> 04: 05: <svg width="500" height="300"> 06: 07: <style type="text/css"> 08: <![CDATA[ 09: .style2{stroke:black;} 10: .style3{fill:yellow;} 11: ]]> 12: </style> 13: 14: <path class="style2 style3" 15: d="M150,140 16: c 0,0 -16,24 -16,33 17: c 0,9 7,15 16,15 18: c 9,0 16,-7 16,-15 19: c 0,-9 -16,-33 -16,-33"/> 20: 21: <path class="style2" 22: d="M250,140 23: c 0,0 -16,24 -16,33 24: c 0,9 7,15 16,15 25: c 9,0 16,-7 16,-15 26: c 0,-9 -16,-33 -16,-33"/> 27: 28: <path class="style3" 29: d="M350,140 30: c 0,0 -16,24 -16,33 31: c 0,9 7,15 16,15 32: c 9,0 16,-7 16,-15 33: c 0,-9 -16,-33 -16,-33"/> 34: 35: </svg>
Though the code may have changed, the result of your experiment here will look exactly the same as Figure 6.3. On a small level such as this three raindrop example, you may not see any value in naming each style declaration. The results, however, begin to manifest themselves once you start dealing with very long and complicated SVG documents.
Labeling Your Style Sheet's Rules
For simplicity's sake, the three rules you just dealt with were arbitrarily named to represent each style declaration: style1, style2, and style3, respectively. However, should you hand this SVG file to a fellow developer, these three names would seem rather meaningless. Not only would they rightfully appear to be a random naming scheme, but the names could also cause confusion in large-scale coding projects. For instance, if the developer knew she wanted to make a circle yellow, she would have no choice but to refer to the style sheet to see what class accomplished this task.
There is a simpler way, though. Naming a class's selector according to its purposes gives a development team a common language to work with. By creating a unified and descriptive class-naming system, developers (yourself included) will be able to quickly determine the name of their desired class.
For instance, rather than naming your first selector style2, use a name that reflects the actual style declaration, such as StrokeBlack. In Listing 6.5, style2 and style3 (lines 9 and 10) have been renamed to more closely reflect their respective declarations' functions.
Listing 6.5 Name Selectors to Mirror Their Declarations' Functions
01: <?xml version="1.0" standalone="no"?> 02: <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" 03: "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> 04: 05: <svg width="500" height="300"> 06: 07: <style type="text/css"> 08: <![CDATA[ 09: .StrokeBlack{stroke:black;} 10: .FillYellow{fill:yellow;} 11: ]]> 12: </style> 13: 14: <path class="StrokeBlack FillYellow" 15: d="M150,140 16: c 0,0 -16,24 -16,33 17: c 0,9 7,15 16,15 18: c 9,0 16,-7 16,-15 19: c 0,-9 -16,-33 -16,-33"/> 20: 21: <path class="StrokeBlack" 22: d="M250,140 23: c 0,0 -16,24 -16,33 24: c 0,9 7,15 16,15 25: c 9,0 16,-7 16,-15 26: c 0,-9 -16,-33 -16,-33"/> 27: 28: <path class="FillYellow" 29: d="M350,140 30: c 0,0 -16,24 -16,33 31: c 0,9 7,15 16,15 32: c 9,0 16,-7 16,-15 33: c 0,-9 -16,-33 -16,-33"/> 34: 35: </svg>
Again, this listing will appear the same as Figure 6.3. However, when another developer examines this code, she will be able to quickly identify the function of the class being applied without needing to look up the selector in the style sheet. Should you follow a naming convention such as this and your style sheet be two pages long with 50 fills and 50 strokes, the same developer would be able to guess (with a high probability at success) at the selector name of a red fill: FillRed. When faced with large documents of code and an impending deadline, such naming conventions can be a lifesaver for your development team.
CAUTION
Be certain to be consistent in naming conventions. If you name one class StrokeGreen and another class BlueStroke, you will destroy the usefulness of your system. If done inconsistently, a developer will be forced to look up every selector name, as a naming convention (such as <propertyName><propertyValue>) is not being followed.