lesson 2

CSS part 1

Syntax

Each style rule is made up of one selector and one declaration. The declaration defines one or more property:value pairs describing a specific style setting, and the selector identifies one or more elements to which those settings are to be applied.


    selector {
      property: value;
    }
        

Shorthand syntax

A handfull of properties can be written in either short- or longhand notation. font, background, margin, padding, border, outline, list-style, and transition all have sub-properties that can be written separately, or combined into a single property:


    selector {
      background-color: red;
      background-image: url('/images/red-tile.png');
      background-repeat: repeat;
      background-position: 0 0;
    }

    selector {
      background: red url('/images/red-tile.png') repeat 0 0;
    }

    selector {
      margin-top: 5px;
      margin-right: 10px;
      margin-bottom: 15px;
      margin-left: 20px;
    }

    selector {
      margin: 5px 10px 15px 20px; /* top, right, bottom, left */
      margin: 5px 10px 15px; /* top, left-right, bottom */
      margin: 5px 15px; /* top-bottom, left-right */
      margin: 5px; /* top-right-left-bottom */
    }
        

Each property has it's own specific syntax and rules, so keep a reference link handy

Units of measure

CSS supports serveral different units of measure, many of which only make sense when printing. In a screen based context, there are only three suitable measurement units:

Ems and percentage are clearly relative units, but because some newer devices have vastly higher pixel densities, the hardware pixel can be considered a relative value as well. Devices like the iPhone 4, with a pixel density of 2, need to render pixel measurements at twice their actual size in order to compensate. There are changes afoot to develop an optical reference pixel that would be the same absolute size across all screens, but we aren't there yet.

Vendor Prefixes

Introduced in CSS 2.1 as a 'beta' flag for new style properties, vendor prefixes allow browser vendors to implement new features before there is a standard syntax. On the whole, this is a good idea, but in practice it can mean more typing:


    -webkit-transition: background-color 0.25s;
    -moz-transition: background-color 0.25s;
    -ms-transition: background-color 0.25s;
    -o-transition: background-color 0.25s;
    transition: background-color 0.25s;
        

Most of the new CSS3 features are still vendor prefixed in the latest versions of browsers, so be sure to consult a reference before writting.

Vendor prefixes are good for the web: don't just use -webkit- and forget the rest

Selectors

A rule's selector can vary from the very specific to the very general, targeting one or many elements at a time. Selector syntax is very flexible, and is designed to allow for combining and grouping individual types.

Basic selectors

Select by id

Select a specific element by id:


    #wrapper {
      margin: 20px;
    }
        

Select by class

Select one or more elements by class:


    .highlight {
      color: yellow;
    }
        

Select by tag name

Select one or more elements by tag name:


    p {
      padding: 0 10px 20px;
    }
        

Select descendants

Select one or more elements nested (at any level) within a parent element:


    li a {
      text-decoration: underline;
    }
        

Select direct descendants

Select one or more elements nested directly below a parent element:


    #wrapper>section {
      float: left;
    }
        

Select by attribute

Select one or more elements based on their attributes:


    /* all img elements with a title attribute */
    img[title] {
      border: 1px solid red;
    }
    /* all a elements with a specific link destination */
    a[href="#"] {
      background-color: #3c3c3c;
    }
    /* all a elements starting with a specific value (external links) */
    a[href^="http"] {
      background-image: url('images/external-link.png');
    }
    /* all form submit buttons */
    input[type=submit] {
      border: none;
    }
        

Select by pseudo class

Select one or more elements based on a specific state:


    /* all a elements during mouse hover state */
    a:hover {
      text-decoration: underline;
    }
    /* all input textfield elements during keyboard focus */
    input[type=text]:focus {
      color: red;
    }
    /* all divs except for #wrapper */
    /* NOT FOR OLDie */
    div:not(#wrapper) {
      margin: 2em
    }
        

Select a pseudo element

Select one or more parts of an element:


    /* first line of all paragraphs */
    p::first-line {
      padding-left: 10px;
    }
    /* first letter of all paragraphs */
    p::first-letter {
      font-size: 1.2em;
    }
        

Pseudo elements are designated by double :: but work with single : for backwards compatibility

Selector Collections

Selectors can be collected in order to apply a style declaration to many elements at the same time:


    /* HTML5 reset */
    article, aside, details, figcaption, figure,
    footer, header, hgroup, menu, nav, section {
      display: block;
    }
    /* typographic styles common to all headings */
    h1, h2, h3, h4, h5 {
      font-family: "Gill Sans", sans-serif;
      letter-spacing: 1px;
    }
        

Selector parsing

Knowing how browsers parse selectors helps avoid inefficient element selection and potential performance issues. The right-most selector in a selector combination is referred to as the key selector because selectors are matched from right to left. This enables browsers to determine which elements don't match as quickly as possible.

Selectors with a right-most selector that matches many elements can have an impact on page rendering speed

Inheritance

Certain style properties are inheritable, passed down from parent to child through the DOM tree. This allows child elements to automatically adopt styles without any explicit declaration. The most important inherited styles are typographic (color, font-size, font-weight, font-family, line-height, text-align, etc):


    body {
      font-size: 14px;
      font-family: sans-serif;
      color: black;
    }
        

Define your basic typographic rules on the body in order to force a consistent style

The Cascade

The cascade is a set of rules that determine which styles are ultimately applied to an element when there are multiple sources, including which styles prevail during conflict. If more than one style is applied from different rules, they are combined, and any conflicts are resolved based on the rule's specificity.

Specificity

When there are conflicting styles, properties of the most specific style overwrite less specific ones. Browsers use a formula to determine a style's specificity based on values assigned to the style's selector:

UA styles < tag < class < id < style attr

In the case of a tie, the last style to be applied wins.

!important

Because of this value based approach, there are some cases where it may be very difficult to override a particular style, particularly when ID selectors have been used. In these cases, it is possible to overrule any style no matter it's specificity:


    #nav a {
      color: red;
    }
    a {
      color: black !important;
    }
        

Avoid the use of !important under all but the most life-threatening circumstances

Resets

Because browsers apply default styling to most elements (especially form elements), it can be desirable to reset styles to a basic state before you begin any styling. As mentioned in the previous lesson, it's sometimes also necessary to apply display:block to HTML5 structural elements. These reset rules should be included before all others to ensure that they don't overrule any custom style declarations.


    /* http://meyerweb.com/eric/tools/css/reset/
       v2.0 | 20110126
       License: none (public domain)
    */
    html, body, div, span, applet, object, iframe,
    h1, h2, h3, h4, h5, h6, p, blockquote, pre,
    a, abbr, acronym, address, big, cite, code,
    del, dfn, em, img, ins, kbd, q, s, samp,
    small, strike, strong, sub, sup, tt, var,
    b, u, i, center,
    dl, dt, dd, ol, ul, li,
    fieldset, form, label, legend,
    table, caption, tbody, tfoot, thead, tr, th, td,
    article, aside, canvas, details, embed,
    figure, figcaption, footer, header, hgroup,
    menu, nav, output, ruby, section, summary,
    time, mark, audio, video {
      margin: 0;
      padding: 0;
      border: 0;
      font-size: 100%;
      font: inherit;
      vertical-align: baseline;
    }
    /* HTML5 display-role reset for older browsers */
    article, aside, details, figcaption, figure,
    footer, header, hgroup, menu, nav, section {
      display: block;
    }
    body {
      line-height: 1;
    }
    ol, ul {
      list-style: none;
    }
    blockquote, q {
      quotes: none;
    }
    blockquote:before, blockquote:after,
    q:before, q:after {
      content: '';
      content: none;
    }
    table {
      border-collapse: collapse;
      border-spacing: 0;
    }
        

Resets even out browser rendering differences by resetting their default styles

The Box Model

Though probably obvious, it's important to note that every element rendered by the browser is bound by a rectangular box. This box, and the properties that make up it's dimensions, is known as the box model. The model affects the dimensions of elements and how they interact with each other.

By default, the actual dimension of an element, and the space it takes up on screen, includes the padding and border dimensions. Although perhaps not entirely logical, the width and height properties define the content width and height only, not it's bounding rectangle.

Width = width + padding-left + padding-right + border-left + border-right

This behaviour has implications for defining precise pixel dimensions of elements, as well as relative, percentage based layout:


    /* actual box dimensions are 540px X 240px */
    #box {
      width: 500px;
      height: 200px;
      padding: 20px;
    }

    /* actual column width is wider than 50% */
    .column {
      width: 50%;
      height: 100%;
      padding: 0 20px;
    }
        

Remember that the default behaviour for block-level elements is to take up all available width, so it's often desirable to set width:auto instead of width:100%. This will allow the use of padding and borders where otherwise it would not be possible. More here

This default behaviour can often be frustrating, and will sometimes lead to extra markup to fix layout problems. One option, however, is to change the box model behaviour to include padding and border dimensions inside width/height declarations:


    .sane-box-model {
      -moz-box-sizing: border-box;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
    }

    /* actual width will be 100% and will play nice with the neighbours */
    div.sane-box-model {
      width: 100%;
      padding: 40px;
      border: 10px solid red;
    }
        

This property is supported on all browsers since IE8, so it's generally safe, and even recommended by some to apply to all elements:


    * {
      -moz-box-sizing: border-box;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
    }
        

Display

Before we embark on questions of layout and positioning, it's useful to first address the various display states available to elements. The aptly named display property is the most important way to control an element's rendering:

Visibility

Another means of controlling the display of an element is with the visiblity property. Unlike display, visiblity does not alter the document flow, but simply changes whether the element is visible or not:

Opacity

Conceptually related to visibility, the opacity property controls the degree of transparency of an element:


    <img src="/images/image.jpg">

    img {
      opacity: 0.25;
    }
          

OldIE doesn't support the opacity property, but you can achieve the same with the IE-only
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
[Note that opacity values are from 0-1, and IE filter from 0-100]

Overflow

When the content inside an element is larger than it's defined width and height, the content can spill outside of it's container in all sorts of odd ways. By specifying an overflow property, you can control the behaviour:

Positioning

Controlling the position of elements is one of the most important, and often challenging, tasks of the styling process. The primary tool for directing the position of elements is the position property:


    <div id="#wrapper">
      <div id="#box1" class="box"></div>
      <div id="#box2" class="box"></div>
    </div>

    #wrapper {
      position: relative;
    }
    .box {
      width: 40px;
      height: 40px;
      background-color: #f26522;
    }
    #box1 {
      position: absolute;
      bottom: 10px;
      right: 10px;
      background-color: #009BC8;
    }
          

Centering

Trying to center an element, either vertically or horizontally, is often more frustrating than you would expect it to be. Certainly, centering horizontally is far easier than the vertical variety, and in all cases it's far easier with elements that have a fixed dimension.

Margin auto

Using margin value of auto for both margin-left and margin-right will center a block element:


    <div id="#box1"></div>

    #box1 {
      width: 40px;
      height: 40px;
      background-color: #f26522;
      margin: 0 auto;
    }
          

Negative margins

Positioning an element absolutely in the middle of it's parent, then applying negative margins equal to half it's height and width will center a fixed sized block element:


    <div id="#wrapper">
      <div id="#box1"></div>
    </div>

    #wrapper {
      position: relative;
    }
    #box1 {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 40px;
      height: 40px;
      margin-top: -20px;
      margin-left: -20px;
      background-color: #f26522;
    }
          

Text-align center

Adding text-align:center to a parent container will horizontally center all inline elements (text, images, etc):


    <div id="#wrapper">
      <p>text</p>
      <img src="/images/little-image.jpg">
    </div>

    #wrapper {
      text-align: center;
    }
          

text

Line-height

Adding line-height equal to height will center a single line of text vertically:


    <li>
      <a>menu link</a>
    </li>

    li {
      background-color: #666666;
    }
    li a {
      height: 100px;
      line-height: 100px;
    }
          

MENU LINK

This is just scratching the surface of all the hacky posibilities that lay just one Google search away.

Taming the layout beast will require patience and experimentation

Floating

The float property is another way to control layout, allowing an element to pull right or left and have content flow around itself. This is often used to wrap text around images, but can also be used to create column layouts and horizontal menus. The values for float include:

Here is the intended use of floats:


    <div id="#wrapper">
      <p>I love cats, they are so cute and cuddly and they smell nice.</p>
      <img src="/images/little-image.jpg">
    </div>

    img {
      float: left;
    }
          

I love cats, they are so cute and cuddly and they smell nice.

And an example of using it for structural layout:


    <div id="#wrapper">
      <div id="#box1" class="box"></div>
      <div id="#box2" class="box"></div>
    </div>

    .box {
      width: 40px;
      height: 40px;
    }
    #box1 {
      float: left;
      background-color: #f26522;
    }
    #box2 {
      float: right;
      background-color: #009BC8;
    }
          

Clearing

Because floating elements takes them out of the regular flow of the document, we often get undesirable behaviour with content that comes after those elements. The clear property is the companion to float in that it determines how non-floated siblings react to a floated brother or sister:


    <div id="#wrapper">
      <div id="#box1" class="box"></div>
      <div id="#box2" class="box"></div>
      <div id="#box3"></div>
    </div>

    .box {
      width: 40px;
      height: 60px;
    }
    #box1 {
      float: left;
      background-color: #f26522;
    }
    #box2 {
      float: right;
      background-color: #009BC8;
    }
    #box3 {
      clear: both;
      width: 100%;
      height: 20px;
      color: #00c830;
    }
          

Collapsing

A side-effect of all this floating is that a container of floated elements will collapse on itself unless it has a defined height (floated elements are taken out of the regular flow, remember?). There are many ways to 'fix' float clearing to prevent collapsing, including adding a bottom element with clear:both as in the above example. If we wish to avoid extra markup, we can use one of the following tricks:


    /* this will trick the container into not collapsing... */
    /* ...but may hide content */
    #wrapper {
      width: 100%;
      overflow: hidden;
    }

    /* this is the same as adding an extra element in markup, but all in css */
    #wrapper:after {
      content: ".";
      display: block;
      height: 0;
      clear: both;
      visibility: hidden;
    }
        

z-index

With the ability to position elements nearly at will, it often becomes necessary to manage element stacking order. Controlling the order in which elements overlap is done with the z-index property, which simply takes a numeric value (negative or positive) to resolve which element lies above another:


    <div id="#wrapper">
      <div id="#box1" class="box"></div>
      <div id="#container">
        <div id="#box2" class="box"></div>
        <div id="#box3" class="box"></div>
      </div>
    </div>

    #wrapper {
      position: relative;
    }
    .box {
      position: absolute;
      width: 40px;
      height: 40px;
    }
    #box1 {
      top: 10px;
      left: 10px;
      z-index: 3;
      background-color: #f26522;
    }
    #box2 {
      top: 30px;
      left: 30px;
      background-color: #009BC8;
      z-index: 2;
    }
    #box3 {
      top: 50px;
      left: 50px;
      background-color: #00c830;
      z-index: 1;
    }
          

z-index only works on positioned elements (relative, absolute, or fixed)

Stacking order is also subject to the current stacking context, much like positioning is subject to positioning context. So, if a group of stacked elements reside in a stacked parent, their stacking order is relative to each other, not the global stacking order:


    <div id="#wrapper">
      <div id="#box1" class="box"></div>
      <div id="#box2" class="box"></div>
      <div id="#box3" class="box"></div>
    </div>

    #wrapper {
      position: relative;
    }
    .box, #container {
      position: absolute;
    }
    #box1 {
      z-index: 3;
      background-color: #f26522;
    }
    #container {
      z-index: 2;
      background-color: #cccccc;
    }
    #box2 {
      background-color: #009BC8;
      z-index: 999;
    }
    #box3 {
      background-color: #00c830;
      z-index: 100;
    }
          

the default value for z-index is 0, so negative values will position an element behind non-positioned/stacked elements

next up...more CSS

60