Sunday, January 9, 2011

Hello, CSS3

Hello, CSS3

This week I'm all about embracing new-ish web standards. In a prior post, I marked up an HTML5 "Hello, World!" document using new semantic tags. Today I'm going to apply some CSS2 and CSS3 styles to that document to demonstrate the awesome new design features that are available in CSS3.

First, let's start by checking out how the HTML5 "Hello, World!" document renders without any styling applied:

No surprises in the screenshot above. The document gets rendered with just a bit of formatting for headers, lists & links. Let's add some CSS2 styles to spruce things up a bit.

article,aside,figure,footer,header,hgroup,nav,section {
 /* setup for browsers that don't yet recognize HTML5 
    block elements */
 display:block
}
p {
 /* add a bit of margin above and 
    below all paragraphs */
 margin: 0.5em 0em;
}
html {
 /* stretch body to fill extra browser height */
 height: 98%;
 /* define color for dead space on 
    left and right of page body */
 background-color: #D0D3A6;
}
body {
 /* stretch body to fill extra browser height */
 min-height: 98%;
 /* define content width */
 width:46em;
 /* center content in the browser window */
 margin: 0 auto;
 /* background color for body content */
 background-color: #FFFFFF;
 /* and a wee bit of padding for all 
    top-level elements in the body */
 padding: 0.5em 1.5em;
}
body > header {
 /* keep the header from being crowded */
 margin-bottom: 0.25em;
}
body > header > hgroup { 
 /* style the page's header */
 padding: 0.25em;
 margin-bottom: 0.5em;
 background-color: #BC9C73;
 text-align: center;
}
body > header > nav { 
 /* style the page's navigation content */
 background-color: #486997;
 /* define bottom border to force render of 
   child ul's bottom margin */
 border-bottom: 0.1em solid #486997;
}
body > header > nav a {
 /* style the page's navigation content */
 color: #FFFFFF;
 text-decoration: none;
}
body > header > nav ul { 
 /* style the page's navigation content */
 background-color: #688AB6;
 margin: 0em 0em 0.3em 0em;
 padding: 1em 0.75em 0em 0.75em;
}
body > header > nav ul li {
 /* style the page's navigation content */
 background-color: #486997;
 padding: 0.3em 1em;
 margin: 0em 0.15em;
 display: inline;
}
body > footer {
 /* render the footer in the center, below 
    all other content */
 text-align: center;
 clear: both;
}
h1 {
 text-transform: capitalize;
}
h1,h2 {
 font-size:medium;
 margin: 0.5em 0em 0.25em 0em;
}
div#main {
 /* float main content to the left */
 float: left;
 width: 74%;
}
div#sidebar {
 /* float sidebar content to the right */
 float: right;
 width: 24%;
}

body aside,
body section {
 /* keep content containers from feeling crowded */
 padding: 0.25em;
 margin: 0.25em 0em;
}

Well, that's certainly an improvement. But we can do even better by progressively enhancing the page with some additional CSS3 rules. Let's give the page some depth and texture.

/*  many of these rules generated with 
    the awesome http://css3generator.com/ or
    http://www.colorzilla.com/gradient-editor/ tools */

body { 
 /* round the corners of the body element's border */
 -moz-border-radius: 4px;
 border-radius: 4px; 
 
 /* apply inset box shadow to body element to 
    create the illusion of depth */
 -webkit-box-shadow: inset 2px 0px 25px #333333;
 -moz-box-shadow: inset 2px 0px 25px #333333;
 box-shadow: inset 2px 0px 25px #333333; 
}

h1, h2 {
 /* apply drop shadow to header text */
 text-shadow: 1px 1px 2px #333333;
 filter: dropshadow(color=#333333, offx=1, offy=1); 
}

body > header * { 
 /* by default, round the border corners of 
    all elements in the header */
 -moz-border-radius: 4px;
 border-radius: 4px; 
}

body > header > hgroup,
body > header > nav { 
 /* apply box shadows to top-level header containers 
    to create the illusion of depth */
 -webkit-box-shadow: 2px 4px 6px #333333;
 -moz-box-shadow: 2px 4px 6px #333333;
 box-shadow: 2px 4px 6px #333333; 
}

body > header > hgroup { 
 /* add a subtle gradient to header's background */
 background: -moz-linear-gradient(top, #BC9C73 0%, #D3BFA5 100%); /* firefox */
 background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#BC9C73), color-stop(100%,#D3BFA5)); /* webkit */
 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#BC9C73', endColorstr='#D3BFA5',GradientType=0 ); /* ie */
}

body > header > nav ul {
 /* "square" the dividing line between navigation 
    tabs and their background */
 -moz-border-radius-bottomright: 0px;
 -moz-border-radius-bottomleft: 0px;
 border-bottom-right-radius: 0px;
 border-bottom-left-radius: 0px; 
}

body > header > nav ul li {
 /* round the top corners of the navigation links */
 -moz-border-radius-topleft: 10px;
 -moz-border-radius-topright: 10px;
 -moz-border-radius-bottomright: 0px;
 -moz-border-radius-bottomleft: 0px;
 border-top-left-radius: 10px;
 border-top-right-radius: 10px;
 border-bottom-right-radius: 0px;
 border-bottom-left-radius: 0px; 

 /* add a gradient to the background of our 
    navigation links */
 background: -moz-linear-gradient(top, #c3d9ff 0%, #486997 37%, #486997 100%); /* firefox */
 background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c3d9ff), color-stop(37%,#486997), color-stop(100%,#486997)); /* webkit */
 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c3d9ff', endColorstr='#486997',GradientType=0 ); /* ie */
 
 /* apply a more drop shadow to navigation link text */
 text-shadow: 1px 2px 8px #ffffff;
 filter: dropshadow(color=#ffffff, offx=1, offy=2); 
}

body section,
body aside {
 /* round the corners of top-level semantic elements */
 -moz-border-radius: 4px;
 border-radius: 4px; 

 /* apply a gradient background "smear" 
    to top-level semantic elements */
 background: #FFFFFF; /* use white background if gradient not available*/
 background: -moz-linear-gradient(top, #D3BFA5 0%, #FFFFFF 33%); /* firefox */
 background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#D3BFA5), color-stop(33%,#FFFFFF)); /* webkit */
 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#D3BFA5', endColorstr='#FFFFFF',GradientType=0 ); /* ie */
}

Many of the CSS3 rules used above were generated with the awesome CSS3 Generator and ColorZilla Gradient Generator tools. I highly recommend checking them out!

Hello, HTML5

Hello, HTML5

This week I've been skimming Mark Pilgrim's HTML5: Up and Running book with a keen interest in the new semantic elements that are being formalized as part of the HTML 5 spec. There are some great new semantic elements being proposed to replace pervasive, unformalized web developer memes like ...

 <!-- This is _so_ 2008. -->
 <div id="header">
  <ul id="navigation"></ul>
 </div>
 <div id="content"></div>
  <div id="main"></div>
  <div id="sidebar"></div>
 </div>

Notice in the above markup that the semantic info about each <div>'s purpose is captured in its id attribute. This is totally valid markup and will produce a well organized document, but it does have some serious drawbacks. While such a id-as-semantic-messenger anti-pattern is easily understood by a human web developer, it's not easily parsed by machines.

So why, you may ask, should we care whether machines can understand the semantics of our web pages? Aren't web pages designed to be read and understood by humans? No. Not, all humans read web pages. People with visual impairments have the web read to them by screen readers.

Screen readers aren't that great. Yet. For example, whereas a human can easily and reliably find the main navigation content of a web page, screen readers don't yet support jumping straight to a page's main navigation content. Consider the myriad HTML4 variations that a screen reader would have to handle in order to support a jump-straight-to-navigation feature:

  • <ul id="navigation"></ul>
  • <ul id="nav"></ul>
  • <div id="navigation"></div>
  • <ul id="navigacion"></ul>
  • <ul id="menu_bar"></ul>
  • etc.

HTML5 to the rescue! Writing screen readers that can find the <nav> element in a HTML5 document will be much easier than coding to handle the tag soup detailed above. And <nav> is not the only new semantic element that will make it easier to write better screen readers. HTML5 also defines <header>, <footer>, <section> and <aside>.

That's great news. As a father of a visually impaired child, I'm hoping that future screen reader software can provide my daughter with web interactions that are as rich as those that I enjoy. With that vision of the future in mind, I'm embracing HTML5 and have authored a quick "Hello, World!" example of HTML5 semantic elements in action.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Hello, HTML5 Semantic Elements!</title>
  <!--[if lt IE 9]>
    <script 
      src="http://html5shiv.googlecode.com/svn/trunk/html5.js">
    </script>
  <![endif]-->
</head>

<body>

  <header>
    <hgroup>
      <h1>Lorem ipsum ...</h1>
      <h2>dolor sit amet, consectetur adipiscing.</h2>
    </hgroup>
    <nav>
      <ul>
        <li><a>Donec hendrerit</a></li>
        <li><a>Pellentesque eget turpis</a></li>
        <li><a>Quisque facilisis porttitor</a></li>
      </ul>
    </nav>
  </header>

  <div id="main">

    <section>
      <header>
        <h2>Morbi a posuere magna</h2>
      </header>
      <p>Etiam feugiat pellentesque dapibus...</p>
      <p>Phasellus ullamcorper condimentum urna...</p>
    </section>

    <section>
      <header>
        <h2>Donec posuere lobortis ipsum</h2>
      </header>
      <p>Cras tellus odio, facilisis nec porttitor...</p>
      <p>Donec blandit suscipit urna ac luctus...</p>
    </section>

  </div>

  <div id="sidebar">

    <aside>
      <header>
        <h2>Ut tincidunt tincidunt</h2>
      </header>
      <p>Suspendisse varius, lacus a egestas...</p>
    </aside>

    <aside>
      <header>
        <h2>Praesent massa sapien</h2>
      </header>
      <p>Phasellus porttitor auctor sapien at...</p>
    </aside>

  </div>

  <footer>
    <p>&copy; 2010 Dave Wingate</p>
  </footer>  

</body>

</html>

Sunday, November 28, 2010

Course Notes -- Design of Programming Languages (CS5318)

This week I'm revisiting some old course notes that I originally published on www.big-oh.net. I'm moving away from self-hosting content on that domain, migrating blog-style content into the cloud ... Blogger in this case.

Following are notes that I used to study for the Design of Programming Languages section of the Texas State University Computer Science graduate comprehensive examination.


Language Design Criteria

The sub-headings below catalog some of the most important language design criteria.

Efficiency

The efficiency of a programming language relates to the speed/cost of performing basic activities of a language's lifecycle. Many facets of a programming language can be evaluated with respect to efficiency.

  • Efficiency of Execution - Influenced by language features like recursion and dynamic memory allocation.
  • Efficiency in Translation - How many passes does the compiler need?
  • Efficiency in Implementation - Influenced by the number of features provided and by level of orthogonality.
  • Efficiency in Programming - Time to train programmers and time to solve problems in the language.
  • Efficiency in Maintenance - Largely determined by readability.
Regularity

The regularity of a language relates to the interaction of its features. A language's regularity can be further decomposed into the following characteristics.

  • Generality - A language is general if there are no special cases in the availability or use of the language's operators. An example of failed generality in the C language is that individual items can be compared with the "==" operator, but entire structs cannot be compared using that operator.
  • Orthogonality - The constructs of a language are orthogonal if they do not behave differently in different contexts and can be easily combined in all meaningful ways. An example of failed orthogonality in the C language is that local variables can only be defined at the beginning of the block.
  • Uniformity - In a uniform language, things that are similar should look similar and things that are different should look different. An example of failed uniformity in the C language is that the difference between "=" and "==" is confusing.
Simplicity

Simple languages have the following properties.

  • Simple languages have fewer features, which makes them easier to implement.
  • Simple languages may have increased implementation efficiency, but decreased programming efficiency and decreased expressiveness.

Abstraction

Abstractions hide unnecessary details, those that are only relevant to the internal implementation. For example, the String data type is an abstraction in that it hides the implementation details of storing and manipulating character data. Another example abstraction is that the "if" statement is an abstraction in that it eliminates the need to consider logic-based jump commands.

The table below describes a taxonomy of abstraction levels in programming languages.

Abstraction Level Data Control
Basic Variables as abstractions for memory locations. Variable assignment and jump statements.
Structured Arrays, records, structs, classes, lists, etc. Guarded commands.
Unit Packages, components, libraries, etc.
Parallel Threads, processes, tasks, etc.

Computational Paradigms

A single programming language may support one or more computational paradigms. The sub-headings below details some of the computational paradigms covered by the comprehensive exam.

Imperative

The imperative computational paradigm is closely tied to the structure of the von Neumann computer model.

  • A.k.a. procedural.
  • Examples include Fortran, C, Pascal and Algol
  • Characterized by sequenced instruction execution, loops, and variables that represent memory locations.
Functional

The functional computational paradigm structures programs in a manner that mirrors the structure of lambda-calculus.

  • A.k.a. applicative.
  • Examples include Lisp, Miranda and Scheme.
  • Reasoning about this type of programs is easier because it is based on recursive function theory.
  • Characterized by (recursive) function calls as the basis for program control. Instead of having variables that represent memory locations, this paradigm has function parameters that accept input values.
Logic

The logical computational paradigm is a higher-level paradigm that abstracts away the need to describe "what to do," requiring that the programmer describe only "what s/he wants."

  • A.k.a. declarative.
  • Examples include Prolog and SQL.
  • Characterized by variables that represent partial computations, which are inputs to Horn clause resolution.

Programming Language Levels

When writing a program in any language, errors can arise at many different levels:

  • Lexical - identifiers, operators, separators, comments
    // not a valid operator or identifier
    int x#1 = 2;
  • Context-Free Syntax - dictates the form of statements, functions, modules, etc.
    // missing parentheses violates 
    // if statement syntax
    if x == y { a=b; }
  • Context-Sensitive Syntax - type checking, forward references, variable declaration, etc.
    // duplicate variable declaration
    double a;
    ...
    int a; 
      
  • Dynamic Semantics - divide by zero, use of un-initialized variable, etc.
    double a = 0;
    double b = 12 / a;
      

Grammars

Definition

A grammar is defined by:

  • A finite set of non-terminal symbols.
  • A finite set of terminal symbols.
  • A single start symbol.
  • A finite set of production rules.
Context-Free Grammars

A Context-free grammar consists of a series of grammar rules that observe the form:

Non-terminal -> {terminals and non-terminals}

This type of grammar is context-free because each left-hand-side non-terminal can always be replaced by any right-hand-side choice, no matter where the non-terminal might appear.

Additionally, a context-free grammar also has a distinguished non-terminal called a start symbol. The language for the grammar is the set of all strings of terminals that can be derived from the start symbol.

By defining a programming language using a context-free grammar, the grammar also implicitly defines the steps that a parser must take to construct a parse tree for a string.

Attribute Grammars

Attribute grammars are an extension of context-free grammars. Because context-free grammars describe only the lexical and syntax levels of a language, they are unable to describe many features of modern programming languages. For example, context-free grammars are unable to enforce type checking. Attribute grammars provide the ability to enforce static semantic rules, like type checking.

An attribute grammar has these properties:

  • Each grammar symbol has a set of (inherited or synthesized) attributes.
  • Each grammar rule has a set of (semantic of predicate) functions, which are defined over the attributes of the symbols in the rule.