Thursday, March 13, 2014

Microsoft 70-480: Structure a CSS file by using CSS selectors

Exam Objectives


Reference elements correctly; implement inheritance; override inheritance by using !important; style an element based on pseudo-elements and pseudo-classes (for example, :before, :first-line, :first-letter, :target, :lang, :checked, :first-child)


Quick Overview of Training Materials


Programming in HTML5 with JavaScript and CSS3 - Training Guide - Chapter 4
Mozilla Dev Net - inheritance, specificity
MSDN - Understanding CSS Selectors
The Cascade - Sitepoint
CSS-Tricks.com - When using !important is the right choice
!important CSS Declarations: How and When to Use Them
w3.org - CSS2 Appendix F. Full property table

*I covered selectors in depth in another blog post, so this one will focus instead on inheritance, cascading, specificity, and using (or not using) !important.



Understanding Cascading


CSS rules for rendering an HTML document can come from multiple sources, not just those rules specified by the page author in the page's CSS file.  The CSS specification lists three origins for style sheets:
  • Author: The one writing the web page. Sytle sheets are typically tied to the page with a <link>
  • User: Users can specify their own style rules in a user style sheet. Some browsers allow users to specify style rules.
  • User Agent: browsers have default style sheets that are applied with the author and user don't specify style rules.
To calculate the value of style properties for a given element, the browser  follows these steps:
  • Find all style declarations that match the element based on the specified selectors. A given element may have multiple conflicting styles that apply based on class, type, and attribute selectors or combinators.
  • Sort according to importance (use of !important) and origin (author, user, user agent) with the following precedence (lowest to highest):
    • user agent default styling
    • user styling (normal importance)
    • author styling (normal importance)
    • author styling (!important)
    • user styling (!important)
  • Rules with the same precedence level according to origin and importance are then sorted based on specificity.  Specificity is calculated a particular way in CSS, with a clear hierarchy of precedences among selector types:
         The highest specificity (call it 'a') is the style="" attribute on the element itself.
         The second highest (call it 'b') is the ID selector
         Next (call it 'c') are attribute selectors including class and pseudo-classes
         Lastly (call it 'd') are elements types and psuedo-elements
    Specificity is calculated by counting the number of each class of selector (a, b, c, d) in the CSS rule. So a rule like div.red[data-attr] would have a specificity of 0,0,2,1 because it has two attribute selectors (.red and [data-attr]) and one element selector (div).  This can create curious situations, for example consider these two rule (where #child is a div under #parent):
         #parent div {background-color: red}  - 0,1,0,1
         #child {background-color: blue} - 0,1,0,0
    Even though #child is specifically selected by id, the styling rule for divs under #parent are more specific, and thus #child would be colored red. It's worth noting that a number in a higher category (a, b, c, d) will always overrule a number in a lower category.  0,0,1,0 is still higher specificity than 0,0,0,15 (I tried...)
  • Finally, if two rules also have the same specificity, they are applied in textual order, thus the last specified will be applied. Consider the child-parent example. If they are changed slightly:
         #parent div {background-color: red}  - 0,1,0,1
         div #child {background-color: blue} - 0,1,0,1
    They how have the same specificity. div #child was specified last, so #child would be blue.
    This JSFiddle looks at specificity:


Using !important


Overusing the !important keywork can lead to unexpected behavior and hard to maintain code.  Abusing the !important keyword is bad practice and, as a rule, should not be used, because it disrupts the normal flow of styling.  However, there are specific cases (identified in CSS-Tricks and Smashing Magazine articles) where it may be desirable to use !important:
  • utility classes (e.g. button)
  • user style sheets (to aid in accessibility). Because user !important declarations override author !important rules, users who need, say, large text due to poor eyesight can make CSS that work for them.
  • urgent bug fixes (which should be temporary until a more elegant CSS fix is found)
  • debugging in developer tools (which is completely ephimeral)
Also, keep in mind that declaring a shorthand property (like background, margin, border, etc) !important is equivalent to declaring all of the subproperties as !important.


Inheritance


Certain CSS properties are inherited from parent elements when they aren't specified.  For example, if we specify the text color of <p> to be blue, and in that paragraph we have an <em> tag with no specific CSS rule, the text in that <em> tag will inherit the text color from the <p> tag, and thus be blue.  Not all properies are inheritable: borders are an example. If our <p> tag has a border specified, the <em> tag won't get its own border by default. However, if we set the rule em {border: inherit}  we can force the emphasis tag to inherit border styling, which will result in an additional border around the emphasized text.  This table at w3.org (for CSS2) includes all CSS properties and states in the Inherited? column whether that property is inherited by default.  Any property can be forced to be inherited by setting the style to inherit as above. Below is an example:

<p style="border: medium solid;padding:5px;">This paragraph has <em style="border: inherit">emphasized text</em> in it.</p>

This paragraph has emphasized text in it.

No comments:

Post a Comment