CSS - Its All About Understanding Selectors
Introduction - Only 2 Things to Learn
CSS Is Easy! Repeat it aloud a few times until you've removed any notion from your head that its difficult to learn. In this article I'm going to demystify it and break it down to a level that is easy to understand and hopefully put you on your way to being a CSS guru.
There are only 2 concepts to learn because CSS boils down to just Selectors and Rules. Selectors are used to select the markup we want to style and rules are the styles to apply to the selected elements. When you see an entry or statement in a css file, the part within the curly braces { } are the rules, and the part preceding it is the selector. Consider this simple example of an Element Selector:
p { border:solid thin black; }
The selector p means select all p (paragraph html element) and the rule says put a border on it.
Most people generally find it easy to understand the rules part of a css statement and can easily lookup what to put there online or from reference books to achieve their goal. But the true power of CSS is in understanding selectors and it seems many people struggle needlessly with CSS because they don't learn enough about selectors to make their work easy. Selectors are how you select the elements to style and the main thing holding people back from applying styles is that they can't figure out how to select the elements they want to style. In mojoPortal, if you master the use of CSS selectors you can easily select pretty much anything in the html you want. So my goal in this article is to teach you how to select anything you want in the markup. I'm not going to show you any glorious style rules, you can probably come up with better ones than me anyway. I'm not a good designer at all but I am very good at taking someone else's design and making a mojoPortal skin, and the only reason I'm good at that is because I understand CSS Selectors well enough that I can pretty much select anything I want and I just apply the rules that the designer came up with. The rest of this article is just going to be a series of illustrations and explanations of the kinds of CSS selectors you can use. I'm going to start with the easy ones you probably already know and then show more complex ones that will help you get to the next level.
Element Selectors
We already saw a simple element selector that selects all paragraphs:
p { border:solid thin black; }
Its easy to understand but lets give a few more examples to show additional concepts. Suppose you want to select all TextBoxes and put a border on them:
input[type=text] { border:solid thin black; }
The selector "input[type=text]" means select all inputs with the type attribute equal to text.
or all dropdown lists:
input[type=select] { border:solid thin black; }
We can also select things by their containment like this:
div div input[type=text] { border:solid thin black; }
means select all inputs with type = text and which live at least 2 levels deep within nested div elements
body {} - Select the body element.
div {} - Select all div elements.
h1 {} - Select all h1 elements.
div h2 {} - Select all h2 elements that are within a div.
Class and ID Selectors
Class selectors and ID selectors are the most basic and commonly used selectors and generally when people begin to learn CSS they learn to use class names on their markup and then can apply styles using a Class Selector. So maybe I have a div like this:
<div class="productwrapper">
some additional markup about a product goes here
</div>
Now I can put a border on that div and any others that have the same class with a selector and rule like this (note that class names are case sensitive):
.productwrapper { border:solid thin black; }
ID selectors are similar but only apply to a specific element because ids on elements must be unique.
<div id="divMyProduct">
some additional markup about a product goes here
</div>
To put a border on this one I need a selector and rule like this:
#divMyProduct { border:solid thin black; }
In mojoPortal and other Content Management Systems and in ASP.NET in general we don't make much use of ID selectors because IDs are generally generated by the system and are long and ugly to ensure their uniqueness so we can't really predict them or rely on them as easily as class selectors. You can use them on plain html elements in the layout.master file but best not to anywhere else. We don't really need them as its always possible to achieve the same thing with class selectors and much easier to work with. So I'm not going to dicuss ID selectors further, the rest of this section will be showing you some things you may not know about using class selectors.
You can Apply More Than One Class To An Element
This is something many people don't realize, consider this markup:
<div class="panelwrapper survey">
some additional markup produced by the Survey features goes here
</div>
The div has 2 class names separated by a space and this is perfectly valid, both class rules will be applied. So if I have css like this:
.panelwrapper { border: solid thin black; }
.survey { color: red; }
Its going to put a border on the div and make any text inside it red.
We take adavantage of this multiple class name feature of CSS in mojoPortal to make it easy to have consistent style across features and to make it possible to style features differently if you want to. The above is a real example from mojoPortal, if you put a survey on a page it will have a div containing it with those very classes "panelwrapper survey" and if you put a plain Html Content feature on a page it will have a div with the class="panelwrapper htmlmodule". So what this means is we can use the .panelwrapper selector to apply the same style rules across features but if we want to only affect the Survey feature we can use .survey and if we want to make the Html feature styled different than other features we can do it using the .htmlmodule class selector.
Now for a good example to show you the power of selectors, lets say that I'm using the Survey feature and I want textbox questions to be wider. You may look in the rendered markup and hope you will find a class name on the text box that you can use, but there is no class name on the textbox. If you only know basic class selectors you will be stumped and struggle with this problem, but it becomes easier if you know that you can use the class name of a parent element to help select the textbox so you can style it. Looking more at the rendered markup we see that the textbox for the survey question is contained inside a div with class="settingrow". So you could style it with this:
.settingrow input[type=text] { width:300px;}
This will make all textboxes that are contained within a an element with the class settingrow have a width of 300 pixels. But maybe this is too general of a rule and it will affect other features where textboxes are used inside divs with the settingrow class, so we want to make it more specific. We look further at the rendered markup and notice that there is a div wrapping the survey with class="panelwrapper survey" so we can make a more specific selector like this:
.survey .settingrow input[type=text] { width:300px;}
Now our selector only applies to the survey feature. The selector says select all textboxes contained in an element with the class settingrow which is also contained in an element with the class survey.
Notice that class selectors don't care what kind of element it is, .cool will select any element with the class cool. I may be using that class on some divs on some paragrapghs or on some links. If I only want to select div elements with the class cool my selector will be like this:
div.cool { }
If I only want to select paragraphs with the class cool I can use:
p.cool {}
If I want to select all paragraphs inside a div with the class cool its like this:
div.cool p {}
If I only want to style links inside a paragraph with the class cool that is also inside a div with the class cool I can use:
div.cool p.cool a {}
Or maybe I only want the links that ar further contained within span elements:
div.cool p.cool span a {}
Are you beginning to get the idea? I hope so. We're basically chaining together selectors to refine our selection. You should experiment with it and gradually you'll learn to select anything you want.
Descendant Selectors
We've already seen Descendant Selectors but thought I should give you the name for it as it helps us discuss it more easily once we have a name for it. They are also known as Contextual Selectors. Descendant selectors are just other selectors chained together that enable you to select based on the structure of the markup.
li ul {} - Selects any ul that is contained within an li.
ul ul {} - Selects only ul elements that are the contained somewhere within another ul.
ul li ul li a {} - Selects links that are in li elements.
Note that descendant selectors don't care how deep the containment is.
div a {} is going to affect all a elements contained in a div no mater if they are nested within some other element inside the div.
Attribute Selectors
We've also seen attribute selectors already but thought it worth giving a few more examples. Attribute selectors allow us to select elements based on their attributes. We are very familiar with class selectors, but did you know you can select elements by class also using an attribute selector.
p[class=cool] {}
is equivalent to:
p.cool {}
because class name is also an attribute, but we can use quite a variety of attributes.
We can also select things based merely on the presence of an attribute. For example if we want to use green font on any link that has a title we can do this:
a[title] { color:green; }
Or maybe we have links to a particular site that we want to have larger font than the rest:
a[href="http://www.mojoportal.com"] { font-size: larger; }
Selecting Children
Some of these are not supported equally across browsers.
Selecting children is more specific than descendant selectors. While "div a {}" will select all a elements even if they wrapped by other elements, like an a inside a p that is inside a div will also be selected. If I only want to select a elements that live immediately inside my div and not ones contained within other elements the selector would be like this:
div > a {}
Selecting Adjacent Sibling Elements
Some of these are not supported equally across browsers.
h2 + p { margin-top: 2px; }
Select only the p elements that come right after an h2 element.
Pseudo Class Selectors
Some of these are not supported equally across browsers.
:focus {} - Selects any element that has the focus.
:hover {} - Selects any element that the mouse is hovering over.
More familiar examples are pseudo classes used with links:
a:link { color: #6297BC; }
a:visited { color: #6297BC; }
a:hover { color: #72A545; }
a:active { color: #6297BC; }
Applying The Same Rule to More Than One Selector
You can apply the same rule to multiple selectors by separating the selectors with commas like this:
h1, h2, h3 {color: green;}
The rule will be applied to each of the 3 selectors, the first selector selects all h1 elements, the second one selects all h2 elements and so on. They can be complex selectors too:
div.cool ul a, .verycool p a {}
I hope these examples get you experimenting and discovering how to select what you want, then you can get creative with the style rules and teach me something!