CSS For High-Performance Javascript UI

Gavin Doughtie

Google, Inc. and xdraw.org

(and a rant)

The Original Designer Tools

The Original Designer Tools

The Future

The Future

The Future

1998!

Maybe it's time to accept
that we're stuck with CSS

"I'm a coder not a designer"

"I'm a coder not a designer,
dammit!"

"I'm a coder not a designer,
dammit!"

Costs of Javascript

Costs of Javascript

Coding Considered Harmful

(Note: as of 7/2008, this only works in Firefox 3)

Easy!

     function drawCentered(ctx, marginLeft, top, boxWidth, text) {
        ctx.save();
        var textSize = ctx.mozMeasureText(text);
        var centerLeft = (boxWidth - textSize) / 2;
        ctx.translate(marginLeft + centerLeft, top);
        ctx.mozDrawText(text);
        ctx.restore();
      }
      function drawWarning(){
        var canvas = document.getElementById('canvasArea');
        var ctx = canvas.getContext('2d');
        var boxWidth = 400; var boxHeight = 200;
        var marginLeft = 20; var marginTop = 20;
        var strokeSize = 1; var fontSize = 20;
        ctx.strokeStyle = "#f00";
        // Draw Box
        ctx.fillStyle = "#ff0";
        ctx.fillRect(marginLeft + strokeSize,
                     marginTop + strokeSize, boxWidth, boxHeight);
        ctx.strokeRect(marginLeft, marginTop,
                     boxWidth + strokeSize, boxHeight + strokeSize);
        // Draw Text
        ctx.fillStyle = "#f00";
        ctx.mozTextStyle = fontSize + 'px Arial';
        var lineHeight = fontSize * 2;
        marginTop += lineHeight;
        drawCentered(ctx, marginLeft, marginTop, boxWidth,
                     'WARNING: Wishes Will Be');
        marginTop += lineHeight;
        drawCentered(ctx, marginLeft, marginTop, boxWidth,
                     'Taken Literally');
      }

The Web Declares!

The Web Declares!

<html>...</html>

Easier

<!DOCTYPE html> <html> <head> <title>warning sign</title> <style type="text/css"> .warning { width: 400px; height: 200px; margin: 20px; border: 1px solid red; font-size: 20px; color: red; background-color: yellow; text-align: center; font-family: arial; line-height: 40px; } </style> </head> <body> <div class="warning"> WARNING: Wishes Will Be <br/>Taken Literally </div> </body> </html>

Surrender To Win

You Don't Have To Code It All

CSS Fundamentals

Example 1: Flexible Image Callouts

(Click here, Gavin)

Example 1: Flexible Image Callouts

Example 1: Markup

<body> <div class="boxholder"> <img src="images/moonman.jpg"> <a href="#"><div id="hoverbox"> <div class="title">NASA</div></div></a> </div> </body>

Relative Measurement

body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  overflow: hidden;
}

img {
  width: 100%;
  height: 100%;
}

Relatively Absolutely

"Absolute" in relation to position:relative;

Relatively Absolutely

.boxholder {
  position: relative;
  width: 100%;
  height: 100%;
}

Relatively Absolutely

Relatively Absolutely

#hoverbox {
  position: absolute;
  left: 35%;
  top: 0;
  width: 33%;
  height: 59%;
  border: 3px solid #eee;
  /* required for IE8 */
  background: url(spacer.gif);
}

World's Greatest :hover

World's Greatest :hover

.title {
  display: none;
}
.title:hover {
  display: block;
}

World's Greatest :hover

.title {
  display: none;
}
.title:hover {
  display: block;
}

World's Greatest :hover

A whole universe of IE Pain

World's Greatest :hover

.title {
  display: none;
  /* IE6 hack */
  filter:alpha(opacity=1);
}
a:hover .title {
  display: block;
  /* IE6 hack */
  filter:alpha(opacity=100);
}

Example 2: Basic Floats

Click Here for the Floats

Example 2: Basic Floats

Example 3: Borders in 2 Dimensions

Example 3: Borders in 2 Dimensions

Example 3: Borders in 2 Dimensions

Example 3: Borders in 2 Dimensions

Example 3: Borders in 2 Dimensions

Example 3: Borders in 2 Dimensions

Show them this one...

Example 3: Markup

<div class="gridlayout"> <div class="top"> <div class="left">tl</div> <div class="middle">tm</div> <div class="right">tr</div> </div> <div class="center"> <div class="left">cl</div> <div class="middle">cm</div> <div class="right">cr</div> </div> <div class="bottom"> <div class="left">bl</div> <div class="middle">bm</div> <div class="right">br</div> </div> </div>

Absolute Positioning

.right {
 position: absolute;
 right: 0;
 top: 0;
 bottom: 0;
 width: 1em;
 background-color: orange;
}

Absolute Stretching

.right {
 position: absolute;
 right: 0;
 top: 0;
 bottom: 0;
 width: 1em;
 background-color: orange;
}

Example 4: When to Use Tables

table layout demo

Example 4: When to Use Tables

  <table>
  <tbody>
  <tr class="top">
    <td class="left">tl</td>
    <td class="middle">tm</td>
    <td class="right">tr</td>
  </tr>
  <tr class="center">
    <td class="left">cl</td>
    <td class="middle">cm</td>
    <td class="right">cr</td>
  </tr>
  <tr class="bottom">
    <td class="left">bl</td>
    <td class="middle">bm</td>
    <td class="right">br</td>
  </tr>
  </tbody>
  </table>

I Know, Tables Are Ugly

<div class="gridlayout">
  <div class="top">
    <div class="left">tl</div>
    <div class="middle">tm</div>
    <div class="right">tr</div>
  </div>
  <div class="center">
    <div class="left">cl</div>
    <div class="middle">cm</div>
    <div class="right">cr</div>
  </div>
  <div class="bottom">
    <div class="left">bl</div>
    <div class="middle">bm</div>
    <div class="right">br</div>
  </div>
</div>

Example 4: Styles

table {
  table-layout: fixed;
}

.center .middle {
  height: 100%;
  width: 100%;
}

.left, .right {
  width: 30px;
  height: 30px;
}

Example 4a: Sliding Doors

Example of sliding doors

Example 4b: Guess What
Always Works...

(what could he mean?)

Example 4b: Artwork

Corners:

Sides:

Top and Bottom

Example 5: Measurement Abuse

Image Resize Demo

Example 5: JS code

var images; // Filled in elsewhere
function setImageSizeViaJs(size) {
  for (var i = 0; i < images.length; ++i) {
    images[i].width = size;
    images[i].height = size;
  }
}

Example 5: Relative Measurements

<img src="blah.jpg" style="width: 1em; height: .75em;" />

Example 5: JS+CSS code

function setImageSizeViaStyle(size) {
  imagelist.style.fontSize = size + 'px';
}

Per-Browser CSS

.dj_safari h1 { color: blue; }
.dj_ie h1 { color: red; }

WebKit, the CSS Wonderland

Open this in webkit: No-script expanding list example.

Markup is content-only

<ul>
<li>
  <a href="#01">
    <span class="title">
       Mission Statement</span>
    <div class="short">
       Oh please click...</div>
    <div class="blah">
       Phosfluorescently...</div>
</a></li>
(etc.)
</ul>

Gradients and Rounding...

li a { 
  color: #000; width: 180px;
  display: block; padding: 0.25em;
  text-align: left;
  text-decoration: none;
  background-color: #eee;
  border: 1px solid #aaa;
  height: 20px; position: relative;
  
  background:
    -webkit-gradient(linear,
      left top, left bottom,
      from(#fff), to(#00abeb));
  -webkit-border-radius: 0.25em;
  -moz-border-radius: 0.25em;
}

Animation Declaration...

li a .blah { 
  width: 550px;
  height: 0;
  overflow: hidden;
  
  -webkit-transition-property: width, height;
  -webkit-transition-duration: 250ms;
  -webkit-transition-timing-function: default;
}

The "Event"

li a:visited .blah { 
  height: 160px;
  margin: 1em;
  text-align: left;
}

Webkit Transforms

In webkit, go here: Webkit Transforms

Webkit Transforms

<img id="theimage"
  src="images/moonman.jpg" 
  style="-webkit-transform: rotate(45deg)" 
  onclick="moveImage();">

Webkit Transforms: Animation

CSS

img {
  width: 50%;
  position: absolute;
  left: 1em;
  -webkit-transition-property: -webkit-tranform, left;
  -webkit-transition-duration: 500ms;
}

JS

function moveImage() {
  var i = document.getElementById('theimage');
  i.style.left = '200px';
  i.style.webkitTransform = 'rotate(0deg)';
}

Masking Images with SVG Shapes

In webkit, go here: Webkit SVG Masks

Masking Images with SVG Shapes

<img src="images/moonman.jpg"
 style="-webkit-mask-image:
 url(circle.svg)">

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle id="circlemask" cx="100" cy="100" r="100" stroke="black"
stroke-width="2" fill="red"/>
</svg>

Gecko's Pretty Cool Too

This currently only runs in ROC's paintserver build. Reflection example (ROC's paintserver build only)

Gecko's Pretty Cool Too

<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:svg="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
<body style="background:black;">
<div id="d">
  <iframe style="display:block; margin:0 auto; width:80%; height:400px;"
          src="basicfloats.html"/>
</div>
<svg:svg style="display:block; height:250px; width:100%;">
  <svg:foreignObject width="100%" height="100%" transform="matrix(1 0 0 -1 0 250)" mask="url(#m)">
    <div style="background:url(#d); background-position:bottom; width:100%; height:100%;"/>
  </svg:foreignObject>
  <svg:mask id="m" maskContentUnits="objectBoundingBox">
    <svg:rect width="1" height="1" fill="url(#g)"/>

    <svg:linearGradient id="g" gradientUnits="objectBoundingBox" x2="0" y2="1">
      <svg:stop stop-color="white" stop-opacity="0" offset="0"/>
      <svg:stop stop-color="white" offset="1"/>
    </svg:linearGradient>
  </svg:mask>
</svg:svg>
</body>
</html>

Gecko's Pretty Cool Too

<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:svg="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
<body style="background:black;">
<div id="d">
  <iframe style="display:block; margin:0 auto; width:80%; height:400px;"
          src="basicfloats.html"/>
</div>
<svg:svg style="display:block; height:250px; width:100%;">
  <svg:foreignObject width="100%" height="100%" transform="matrix(1 0 0 -1 0 250)" mask="url(#m)">
    <div style="background:url(#d); background-position:bottom; width:100%; height:100%;"/>
  </svg:foreignObject>
  <svg:mask id="m" maskContentUnits="objectBoundingBox">
    <svg:rect width="1" height="1" fill="url(#g)"/>

    <svg:linearGradient id="g" gradientUnits="objectBoundingBox" x2="0" y2="1">
      <svg:stop stop-color="white" stop-opacity="0" offset="0"/>
      <svg:stop stop-color="white" offset="1"/>
    </svg:linearGradient>
  </svg:mask>
</svg:svg>
</body>
</html>

Thank You

<rant>

<rant
opinions_of_employer=
"false">

"With browsers, you cut people off at the knees, but everyone's the same height."

-Alex Russell

Who's Fault is This?

Who's Fault is This?

?

Who's Fault is This?

Ours!

Browsers Now

YOUR Browser Stats

Maybe Like This

Or Even This

Be Compelling

Be Compelling

Be Compelling

Have Courage!

</rant>

(thanks again)