Mozilla

CSS Articles

Sort by:

View:

  1. Firefox 4 Demos: Awesome CSS3 Planetarium

    O hai pixel lovers! Check out this gorgeous CSS3 demo: Planetarium, by the LittleWorkshop team (@glecollinet & @whatthefranck).

    planetarium

    Screencast:

    Youtube link.

    Gorgeous Animations

    The principal feature show-cased in this demo is CSS3 Transitions. The animation between the welcome-screen and the planet-screen, and the animation between the different planets are powered by transitions. But there are many little effects in this demo. Take a look at the Twitter button, the ruler, the credit page or the back button. These effects are CSS3 Transitions too.

    Another interesting detail. Next to the planet, you have some different animations. The way the animations is played depends on if you’re coming from the left, the right or from the home screen.

    Try it yourself: Click on the planet Earth, from the home screen. See the text “falling” from the top? Now, go to Mars, and come back to Earth. Now the text is “flying” from the right. Designers will love that :)

    Beautiful fonts

    @font-face allows you to use your own font for creative design. Combined with text-shadow and font-feature-settings, you can accurately forge and style your typographic content.

    Your turn!

    These are features you can use today.
    This demo works perfectly in Firefox 4, Safari and Chrome. Also, Transitions and font-face are easily degradable. Go. Check out the source code, read the documention, and if you’re proud of your code, feel free to submit a demo!

  2. Zooming and rotating for video in HTML5 and CSS3

    The source of the code examples in this post is available on GitHub and you can see the demo in action.

    There are dozens of video players that allow you to do all the normal things with videos: play, pause, jump to a certain time and so on. More advanced ones also allow you to fast forward and reverse the video and support subtitles.

    One thing I haven’t found yet though is zooming and rotation of a video. Granted, an edge use case, but sometimes it is cool to be able to zoom into a detail like a blooper (boom mic in the background) or an easter egg (check for the term “A 113″ in every Pixar movie – an homage to the classroom most of the original Pixar cast learned their trade in).

    Rotation might come in handy when you recorded your video in portrait instead of landscape on your camera and you don’t want to re-encode it before you put it on the web.

    The HTML5 video tag allows you to style the video with CSS and CSS3 transforms allow both for scaling and for rotation. So let’s put those together.

    Embedding a video is as simple as this (see this in action on the demo page):

    <video controls>
      <source src="http://www.archive.org/download/AnimatedMechanicalArtPiecesAtMit/P1120973_512kb.mp4" type="video/mp4">         
      <source src="http://www.archive.org/download/AnimatedMechanicalArtPiecesAtMit/P1120973.ogv" type="video/ogg">
      <p>Your browser doesn't support the HTML5 video tag it seems. 
         You can see this video as part of a collection <a href="http://www.archive.org/download/AnimatedMechanicalArtPiecesAtMit/">at archive.org</a>.</p>         
    </video>

    Now, to scale this video you can use CSS3 transform:scale:

    Scaling a video with CSS3 transformations

    video{
      display:block;
      width:400px;
      height:300px;
    }
    video.scale2{
      -moz-transform:scale(1.5);
      -webkit-transform:scale(1.5);
      -o-transform:scale(1.5);
      -ms-transform:scale(1.5);
      transform:scale(1.5);
    }

    You can rotate with CSS3 transform:rotate:

    Rotate a video with CSS3 transformations

    video{
      -moz-transform:rotate(20deg);
      -webkit-transform:rotate(20deg);
      -o-transform:rotate(20deg);
      -ms-transform:rotate(20deg);
      transform:rotate(20deg);
    }

    And you can do both:

    Rotate and scale a video with CSS3 transformations

    video{
      -moz-transform:scale(1.5) rotate(20deg);
      -webkit-transform:scale(1.5) rotate(20deg);
      -o-transform:scale(1.5) rotate(20deg);
      -ms-transform:scale(1.5) rotate(20deg);
      transform:scale(1.5) rotate(20deg);
    }

    Now, this doesn’t make much sense though as it changes the dimension of the video (in the demo page I needed to change the margin for each video accordingly). To really provide a “zoom” functionality, we’d need to keep the original size and cut off the parts we don’t need. We could do this using a CANVAS element, but why go that far when a simple DIV does the job for us?

    All we need to do to keep the space is nest our videos in a DIV with the class stage:

    <div class="stage"><video controls>
      <source src="http://www.archive.org/download/AnimatedMechanicalArtPiecesAtMit/P1120973_512kb.mp4" type="video/mp4">         
      <source src="http://www.archive.org/download/AnimatedMechanicalArtPiecesAtMit/P1120973.ogv" type="video/ogg">         
      <p>Your browser doesn't support the HTML5 video tag it seems. 
         You can see this video as part of a collection <a href="http://www.archive.org/download/AnimatedMechanicalArtPiecesAtMit/">at archive.org</a>.</p>         
    </video></div>

    The CSS to make the cropping work is the following:

    .stage{
      width:400px;
      height:300px;
      position:relative;
    }
    video{
      width:400px;
      height:300px;
      position:absolute;
      top:0;
      left:0;
    }

    Absolutely positioned elements are taken out of the normal flow of the document. If you put an absolutely positioned element inside one that is relatively positioned, its top and left values are relative to the other element. In other words: the video now covers the stage completely.

    If we rotate the video we still have triangular spaces showing like in this example:

    Positioning a video absolutely in a relative container

    .demostage{
      width:400px;
      height:300px;
      position:relative;
    }
    .demovideo{
      position:absolute;
      top:0;
      left:0;
      -moz-transform:rotate(20deg);
      -webkit-transform:rotate(20deg);
      -o-transform:rotate(20deg);
      -ms-transform:rotate(20deg);
      transform:rotate(20deg);
      width:400px;
      height:300px;
    }

    To work around this, we must add a overflow:hidden to the stage DIV:

    Setting overflow:hidden on the stage hides the overlapping parts of the video

    .demostage{
      width:400px;
      height:300px;
      position:relative;
      overflow:hidden;
    }
    .demovideo{
      position:absolute;
      top:0;
      left:0;
      -moz-transform:rotate(20deg);
      -webkit-transform:rotate(20deg);
      -o-transform:rotate(20deg);
      -ms-transform:rotate(20deg);
      transform:rotate(20deg);
      width:400px;
      height:300px;
    }

    In order to provide a zoom and rotate functionality, we need to use JavaScript and buttons for the end user. The first hurdle here is – as you probably already realised from the CSS – browser differences in the syntax. Therefore we need to detect which of the transformations the current browser supports. The safest way is to ask the browser:

    var properties = ['transform', 'WebkitTransform', 'MozTransform',
                      'msTransform', 'OTransform'];
    var prop = properties[0];
    for(var i=0,j=properties.length;i<j;i++){
      if(typeof v.style[properties[i]] !== 'undefined'){
        prop = properties[i];
        break;
      }
    }

    Once this runs we can set a transformation with the following JavaScript syntax:

    var zoom = 1.5;
    var rotate = 20;
    v.style[prop]='rotate('+rotate+'deg) scale('+zoom+')';

    Of course it doesn’t make much sense to rotate the controls with the video. Therefore you need to provide your own. You can use any of the aforementioned players for that or roll your own. To demonstrate, I just built one with a single button allowing you to play and pause the video:

    The full source is available on GitHub, read the comments to see what is going on here.

    Just a quick example of what you can do with open technologies.

  3. A call for quality HTML5 demo markup

    HTML5 is a necessary evolution to make the web better. Before the HTML5 specs were created we used (and still use) a hacked together bunch of systems meant for describing and linking documents to create applications. We use generic elements to simulate rich interaction modules used in desktop development and we make assumptions as to what the user agent (browser) can do for the end user.

    The good thing about this mess is that it taught us over the last few years to be paranoid in our development approach – we realised that in order to deliver working, accessible, maintainable and scalable systems we have to be professional and intelligent in our decisions and especially in our planning and architecting.

    The trouble is that with the excitement around the cool new HTML5 things to play with a lot of these principles get lost and discarded as outdated. They aren’t – part of the mess that the web is in is that in 1999 a lot of people discarded everything else and instead worked only on the new hotness that was Internet Explorer 6 and DHTML. Let’s not repeat that mistake.

    The two faces of HTML5 enthusiasm

    Right now there are two things to get really excited about in HTML5: the richer, more meaningful semantics of new elements and the APIs that give us deep access into the workings of the browser and the operating system. The former allows us to build much richer interfaces and the latter allows us to build much more complex applications.

    All of this comes with the awesome of view source (or check in development tools) for debugging. You can advocate HTML5 by writing clean and useful markup. You can kill it by treating the markup as a second class citizen which is only there to serve the script.

    The markup enthusiasts are very happy about HTML5 and make it easy for people to upgrade – lots of cool new blog templates and boilerplate HTML templates are being built and polyfills created to allow using the new features and not leave behind outdated browsers.

    On the app development side of things it looks much different and that is just sad. My only possible explanation is that people who come from desktop environments now tackle the HTML5 APIs without ever having to care about markup. The pragmatism of HTML5 allows a much more forgiving syntax than XHTML but it shouldn’t mean that we can just re-apply all the bad mistakes that held us back when it comes to maintenance for years.

    During my career as a web developer I realised a few things make a lot of sense when building web apps:

    • If there is an element for a certain task – use that one. It is very likely that the element comes with accessibility and interaction features for free that you would otherwise have to simulate.
    • Separate CSS, JavaScript and HTML – which means it is easy to refactor your code without having to change all of them. It also means you can work in parallel with others instead of breaking each other’s code
    • Never rely on markup or content – as sooner or later some editing tool will come into place that messes with everything you created

    This means a lot of things:

    • For starters it means that inline styles are simply evil as they override any settings you have in your style sheets. Only use them when this is exactly what you need to do or when you calculate them dynamically.
    • The same applies to inline scripting. If you have an onclick="foo()" somewhere in your HTML and foo() changes to bar() you have to rename it in every HTML document (of course nowadays it is one template, but it still means hunting down a reference you might miss)
    • If instead of using a native HTML element for a certain job you use SPANs and DIVs you’ll have to add classes to make them look and work – and simulate the keyboard accessibility, too.
    • You can’t rely on the text value of any element. A <button>edit</button> using the “edit” as the trigger for certain functionality would have to have the JS localised, too when you create the German <button>bearbeiten</button>.

    Bla bla bla… C’mon Chris, it isn’t that bad!

    The above best practices have been mentioned for years and a lot of people get sick of seeing them repeated. After all, this is intelligent development and standard practice in backend technologies. I came across a lot of “creative” uses lately though when doing a view-source on HTML5 demos – specifically the ones in the HTML5 advent calendar. And here is my yield of what people do.

    Simulating a navigation list

    One of the first things I encountered was a painting tool that had a gallery of created graphics as a background. Now, to me this would be a simple list:

    <ul>
      <li>
        <a href="{link}">
          <img src="{src}" alt="{title}">
        </a>
      </li>
      [...]
    </ul>

    The markup I found though was this:

    <div id="sky">
      <div class="skyTile" style="{calculated styles};display:block">
        <img class="skyThumb" src="{src}" style="{generated styles}">
        <img src="images/thumb_dropShadow.png" 
             class="skyThumbShadow" 
             style="{generated styles}">
      </div>
      [...]
    </div>

    This, of course is generated by the backend. My first gripe is the dropshadow image, after all this is an HTML5 showcase – just use CSS3. We also have the three instances of generated styles and double classes. Granted, an extra class gives you a handle to all images instead of tiles, so why not. But as there is no real link around the image, the click handler has to read the url from somewhere. There is a lot of unnecessary back and forth between DOM and scripting here which does slow down the whole demo. Seeing that this is also the main navigation from the entry page to the editor this could be a list inside a nav element. A list groups these items together, a bunch of DIVs doesn’t (screen readers for example tell you how many items there are in a list).

    Another list I found was supposed to be links to refresh the app and have a hierarchy but instead was a flat list with classes to define hierarchy and group:

    <ul id="mitems">
      <li class="hedtop">Simple</li>
      <li class="mol">{name}</li>
      [... repeated ...]
      <li class="hed">{parent name}</li>
      <li class="mol">{name}</li>
      [... repeated ...]
    </ul>

    This could be OK, granted you also shift keyboard focus, but why not:

    <nav>
    <ul id="mitems">
      <li>{parent name}
        <ul>
          <li><a href="{url}">{name}</a></li>
          [... repeated ...]
        </ul>
      </li>
      [... repeated ...]
    </ul>
    </nav>

    This would give you styling hooks and functionality for free. Links and buttons are great to trigger functionality – but it seems that is too easy.

    Click (probably) here for functionality

    If I build a button for an application to trigger a certain functionality this is the markup:

    <button type="button" class="edit">Edit</button>

    Buttons are what trigger functionality – both a backend script or a JavaScript. They are keyboard accessible, have a disabled state and sensible out-of-the-box styling that nowadays can be completely overwritten. The class can be the definition of what the button should do – instead of the text which will change. You could use an ID but a class allows to repeat buttons (for example on the top and the bottom of a results list).

    The buttons I found though were slightly different:

    <div id="homeButtonPanel">
      <div class="homeButton" id="drawHomeButton" 
           style="display: block;">
        <p>Start Drawing</p>
      </div>
      <div class="homeButton" id="viewHomeButton" 
           style="display: block;">
        <p>View the Mural</p>
      </div>
    </div>
     
    <div id="controlPanel" style="display: block;">
    <div class="titleButton"><p>{title}</p></div>
      <div class="mainMenu">
        <div class="mainButton mainSelected" id="drawButton">
          <p>Draw</p>
          <div id="inkDisplay">
            <div id="inkMeter" style="width: 94px;">
            </div>
          </div>
        </div>
        <div class="menuContainer">
          <div class="menuButton drawMenuButton" id="behaviorsButton"
               style="display: block; opacity: 1;">
            <p>Gesture<br>Behaviors</p>
          </div>
        </div>
        <div class="menuContainer">
          <div class="menuButton drawMenuButton" id="artworkButton" 
               style="display: block; opacity: 1;">
            <p>Artwork</p>
          </div>
        </div>
        <div class="menuContainer">
          <div class="menuButton drawMenuButton" id="resetButton" 
               style="display: block; opacity: 1;">
            <p>Reset</p>
          </div>
        </div>
        <div class="menuContainer">
          <div class="menuButton drawMenuButton" id="undoButton" 
               style="display: block; opacity: 1;">
            <p>Undo</p>
          </div>
        </div>
        <div class="menuContainer">
          <div class="menuButton drawMenuButton" id="saveButton" 
               style="display: block; opacity: 1;">
            <p>Save</p>
          </div>
        </div>
      </div>
      <div class="mainMenu">
        <div class="mainButton" id="viewButton"><p>View</p></div>
      </div>
      <div class="mainMenu">
        <div class="secondaryButton" id="helpButton"><p>Help</p></div>
      </div>
      <div class="mainMenu">
        <div class="mainShare shareButtonSmall" id="mainTwitterButton">
          <img alt="twitter" src="images/twitter_icon.png" 
               style="opacity: 0.6;">
        </div>
        <div class="mainShare shareButtonLarge" id="mainFacebookButton">
          <img alt="facebook" src="images/facebook_icon.png">
        </div>
        <div class="mainShare shareButtonSmall" id="mainEmailButton">
          <img alt="email" src="images/email_icon.png" style="opacity: 0.6;">
        </div>
      </div>
    </div>

    So instead of using a nested list with classes for each button and the hierarchy in the nesting we have a lot of classes and a hand-rolled DIV construct. Instead of making buttons really disabled we rely on opacity and there is quite a mix of inline images and background images (if all were background images, they could be one sprite!). Keyboard navigation will have to be written for this and if you were to add a button you’d have to come up with another ID.

    HTML5 actually has a construct for this. There is a menu element with command child elements. These are in use in Chrome’s side bar for example and should be what we use. If you want to make it work for everyone, a nested list with button elements is what to go for.

    The overly complex DIV construct is quite used though – this was another example:

    <div class="uiScreen" id="startScreen">
      <div class="panelBackground" id="mainResumeButton" style="display: none;">
        <div class="largeUIButton" id="resumeButton">Resume Game</div>
      </div>
      <div class="panelBackground" id="mainStartButton">
        <div class="largeUIButton" id="startButton">Start Game</div>
      </div>		
      <div class="panelBackground" id="mainHelpButton">
        <div class="largeUIButton" id="helpButton">Help</div>
      </div>
      <div class="panelBackground" id="mainHighscoreButton">
        <div class="largeUIButton" id="highscoreButton">High Scores</div>
      </div>
    </div>

    When in doubt – add an ID and class to everything.

    Other buttons I encountered were actually links pointing to javascript:// using an inline style to indicate hierarchy:

    <ul class="navlist">
      <li><a id="play" href="javascript://" 
             style="display: inline;">Play</a></li>    
      <li><a id="pause" href="javascript://">Pause</a></li>
      <li style="padding-left: 2px;">Effects:</li>
      <li><a id="bw" href="javascript://">Bw</a></li>
      <li><a id="outline" href="javascript://">Outline</a></li>
      <li><a id="color" href="javascript://">Color</a></li>
      <li><a id="invert" href="javascript://">Invert</a></li>
      <li><a id="matrix" href="javascript://">Matrix</a></li>
      <li><a id="old" href="javascript://">Old</a></li>
    </ul>

    Talking of inline – here’s a great example of a tool generating a lot of code that could be replaced by a single event handler and event delegation:

    <div id="tools">
      <span onmouseout="buttonOut(1)" onmouseover="buttonOver(1)"
            onclick="buttonClicked(1)" id="button1" class="button">
        <img alt="" src="image/button/1.png">
      </span>
      <span onmouseout="buttonOut(2)" onmouseover="buttonOver(2)"
            onclick="buttonClicked(2)" id="button2" class="button">
            <img alt="" src="image/button/2.png">
      </span>
     
      [...repeated 20 times...]
     
    <div id="toolsSeparator">&nbsp;</div>
      <a title="" id="toolbarButtonSave" class="toolbarButton"
         href="javascript:saveCanvas()">
        <img alt="" src="image/save.png">
      </a>
      <a title="New" id="toolbarButtonNew" class="toolbarButton"
         href="javascript:newCanvas()">
        <img alt="New" src="image/new.png"></a>
      <!--[if !IE]><![IGNORE[--><!--[IGNORE[]]-->
      <a id="toolbarButtonMenu" class="toolbarButton"
         onmouseout="closeMenuDelay()" onmouseover="showMenuHover()"
         href="javascript:showMenu()">
        <img alt="&gt;" src="image/menu.png">
      </a>
      <div onmouseout="closeMenuDelay()" onmouseover="overMenu()" id="menu">
        <a class="saveMenu" onmouseout="closeMenuDelay()" 
           onmouseover="overMenu()" href="javascript:saveCanvas()">
          save normal
        </a>
        <a class="saveMenu" onmouseout="closeMenuDelay()" 
           onmouseover="overMenu()" href="javascript:saveCanvasHi()">
          save high quality
          <span class="footnote">&nbsp; (rename to *.png)</span>
        </a>
        <a onmouseout="closeMenuDelay()" onmouseover="overMenu()"
           href="javascript:showAbout()">
          about...
        </a>
        <a class="lastMenu" target="_top" onmouseout="closeMenuDelay()"
           onmouseover="overMenu()" 
           href="{url}">
          <span class="footnote">
            <em>elsewhere:&nbsp;</em>
          </span>
          <em>a sound memory game</em>
        </a>
      </div>
      <!--<![endif]-->
    </div>

    Notice that if the images for the button couldn’t be loaded for one reason or another (or you can’t see them at all) this application is very confusing indeed – no alternative text for the images and no text content to fall back to. I am also very much sure that the in and out handlers trigger visual effects CSS could handle better.

    Reasons and effects

    I know there are probably good reasons for all of this, and I am sure I will also do things wrongly when I am rushed or want to get things out quickly. What we have to understand though is that right now we have a responsibility to show the best of breed demos we can.

    We cannot preach the open web and technologies and view-source over closed systems and at the same time forget the things we learnt in the last decade. Some of these things I found look like code Frontpage or Dreamweaver could have produced in the 90ies and resulted in a lot of badly performing, hard to maintain products that either still annoy people who have to use them or get replaced every 2 years.

    We have a mandate to educate the new developers coming to the web. Unlearning something is much harder than learning it – so let’s not start with bloat and quick fixes that work but forget to advocate clean code and thinking about the impact your product has on the end users (thinking accessibility) and the poor sods that will have to maintain your product when you are gone. We are not here to advocate effects and products, we are here to promote the tools that allow anyone to easily build something cool that is also easy to understand.

    HTML5 is about evolving the web as a platform – we also need to evolve with it and take more responsibility. We have app and we have markup enthusiasts. Let’s make them work together to build things that are great functionality and clean semantics.

  4. Spirit of Indiana (Jones) – syncing HTML5 Video with Maps

    I’ve always been a big fan of the travel/flight sequences in the Indiana Jones movies and judging by the amount of copy attempts on YouTube I am not alone in this. As I don’t own any video editing software I thought it should be possible to create the same effect with web technologies and Google Maps and lo and behold it is:

    See the demo online

    You can download the animation demo for yourself and try it out locally – all you need is a browser that supports HTML5 video. I know – the music is not quite the same as in the movies, but at least this one is not copyright infringing and it came from the heart (5 minutes in a meeting room in the Mozilla office).

    So how was this done and what are problems that needed solving? Here’s how and what.

    Step 1: Find the movie and get it to the right format

    That was the easy part. Archive.org has a lot of awesome public domain movies available for you and they are already in the formats needed to use in an HTML5 video element. In this case, I took the short movie of Charles Lindbergh taking off for his record breaking flight from New York to fly to Paris in 1927.

    Step 2: Displaying the video

    Using the video is pretty simple:

    <div id="stage">
      <video>
        <source src="http://www.archive.org/download/
    CharlesLindbergTakesOff/CharlesLindbergTakesOff_512kb.mp4" 
    type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
        <source src="http://www.archive.org/download/
    CharlesLindbergTakesOff/CharlesLindbergTakesOff.ogv"
     type='video/ogg; codecs="theora, vorbis"'> 
      </video>
    </div>

    The MP4 format will be used by Webkit based browsers and the Ogg version by Firefox and others. As we want to control the video we omit the controls attribute on the video element – instead we create a button to play the video with JavaScript:

    window.addEventListener('load', 
      function() {
        var stage = document.getElementById('stage');
        var v = document.getElementsByTagName('video')[0];
        but = document.createElement('button');
        but.innerHTML = 'Click to see Lindbergh\'s flight';
        stage.appendChild(but);
        but.addEventListener('click',function(e) {
          v.play();
          e.preventDefault();
        },false);
      }, 
    false);

    As the video is markup we can do whatever we please with it – the power of open technologies. For example as we will do here we can set its opacity in CSS and put in on top of a map.

    Step 3: Create the map path animation

    Talking of which, let’s get that moving path done. Google Earth has an API to do that, but it needs a special plugin. Google Maps allows you to paint paths on maps (which actually are SVG, another open standard). Put that in a recursive function and you get the desired effect:

    Animated Google Maps path synced with HTML5 video

    In essence, what I did was take the latitude and longitude of the start and end points and calculate as many points in between the two as I need for the duration of the animation. I store the points in an array called pos and then paint a path from the start to the current point and move the map centre to this point on every iteration.

    spirit.draw = function(){
      var path = new google.maps.Polyline({
            path: [startpos,pos[now]],
            strokeColor: "#c00",
            strokeOpacity: .7,
            strokeWeight: 10
      });
      path.setMap(map);
      map.panTo(pos[now])
      now = now + 1;
      if(now < animationend-1){
        setTimeout(spirit.draw,200);
      }
    }

    Check the highly commented source of the map example for the details. Now, we could use this kind of animation and play the video over it – the problem though is that they may get out of sync. When the movie stalls (as it frequently does on this hotel wireless connection) we don’t want the animation to keep moving, right?

    Step 4: Syncing video and the map movement

    Instead of having two sources of timing information we have to limit ourselves to one source of truth. This is the time stamp of the currently playing movie.

    By the way – you might have noticed that I wrapped the map code in a tilesloaded event handler. This is another safeguard for keeping things in sync. I found that on slow connections the tile loading can delay the whole interface immensely (because of all the subdomain lookups), so I make the whole interface dependent on the loading of the map and only proceed when the tiles have finished loading. As the tilesloaded event also fires when the map pans we need to use a boolean to stop it from starting the effect several times:

    google.maps.event.addListener(map,'tilesloaded',function(){
      if(played === false){
        // [...other code...]
        played = true;
      }
    });

    You can read the current timestamp of a video with video.currentTime and whilst the movie is playing it constantly fires an event called timeupdate. As the event fires a lot we need to throttle it somehow. The trick here is to only take the full seconds and increase a counter when a new second is reached. You can see the timestamp and the second interval firing in the video syncing demo:

    HTML5 video with timestamp

    var now = 0;
    v.addEventListener('timeupdate',function(o){
      log.innerHTML = v.currentTime; /* logging the real timestamp */
      var full = parseInt(v.currentTime);
      if(full >= now) {
        seqlog.innerHTML = now;  /* logging the seconds firing */
        now = now + 1;
      }
    },false);

    That way the movie can lag in between and the sequence still stays in sync. Check the source of this demo on Github.

    Putting it all together

    And that was about it – all I had to do is to set the movie’s opacity at a certain time stamp, start the sound at another and show and hide the copyright complaint at another. As we rely on the timestamp for the other effects we needed a boolean switch to avoid repeated firing:

    v.addEventListener('timeupdate',function(o){
      full = parseInt(v.currentTime);
      if(full === now-1){
        mapelm.style.opacity = .8;
        v.style.opacity = .4;
      }
      if(full === animationstart+1 && audioplay === false){
        a.play();
        audioplay = true;
      }
      if(full === animationstart+2 && hidden === true){
        drmbedamned.style.display = 'block';
        hidden = false;
      }
      if(full === animationstart+3 && hidden === false){
        drmbedamned.style.display = 'none';
        hidden = true;
      }
      if(full >= now) {
        path = new google.maps.Polyline({
            path: [startpos,pos[full]],
            strokeColor: "#c00",
            strokeOpacity: .7,
            strokeWeight: 10
        });
        path.setMap(map);
        map.panTo(pos[full])
        now = now + 1;
      }
    },false);

    Another event we needed to subscribe to was the movie ending so we can stop the music and start to roll the credits:

    v.addEventListener('ended',function(o){
      a.pause();
      spirit.credslist.parentNode.style.display = 'block';
      spirit.creds();
    },false)

    As the theme is too short for the whole animation we need to loop it. This can be done by testing for the ended event and rolling back the time to 0:

    a.addEventListener('ended', function(o) {
      a.currentTime = 0;
    },false);

    Summary

    And there you have it – Indiana Jones style maps using open services and open technologies. A workaround for the copyrighted audio (recorded, edited and converted with the free Audacity sound editor) and using Google’s Web Fonts as graphics.

    You can now take this and change it for even more awesome:

    • Replace Google Maps with Openstreetmap to avoid going over the limit
    • Add a slight curve to the path from NYC to Paris to make it more accurate (but then again the time is not accurate either – it took charles a tad longer)
    • Use a static map and paint the path with Canvas to speed up and smoothen the animation

    Why not have a go – it is free and fun to play.

  5. Firefox 4: OpenType font feature support

    When @font-face support was introduced in Firefox 3.5, web authors were suddenly given a way of dramatically enhancing the typography used on their sites.  With all major browsers slated to soon support WOFF fonts offered by many font vendors, the range of fonts available on the web is far wider than it was just two years ago.




    The OpenType format has long provided font designers ways of including a rich set of variations in their fonts, from ligatures and swashes to small caps and tabular figures. The OpenType specification describes these features, identifying each with a unique feature tag but they have typically only been available to those using professional publishing applications such as Adobe InDesign. When glyphs are selected for a particular sequence of characters and positioned for rendering, these features affect both glyph selection and positioning. Firefox currently renders using a font’s default feature settings; it would be much more interesting to provide web authors with a way of controlling these font features via CSS.

    Included among the many new features in Firefox 4 is the next step, support for controlling OpenType font features directly via CSS.  The -moz-font-feature-settings CSS property permits control over kerning, ligatures, alternates, real small caps and stylistic sets to name just a few.

    The CSS3 Fonts specification contains a number of new subproperties of font-variant.  These will eventually provide much better author control over font features but for Firefox 4 only the low-level -moz-font-feature-settings CSS property is supported.  With this authors can enable and disable OpenType font features directly:

    .altstyles {
      /* format: feature-tag=[0,1] with 0 to disable, 1 to enable */
      /* dlig = discretionary ligatures, ss01 = stylistic set 1 */
      -moz-font-feature-settings: "dlig=1,ss01=1";
    }

    For reference, a complete list of registered OpenType features can be found here. The folks at FontFont provide a nice visual guide to OpenType features.

    Ligatures and Contextual Alternates

    Font designers often include simple ligatures and kerning data in their fonts but some go beyond these and spend a lot of time creating special ligatures and contextual alternate glyphs to enhance a given design. The Bello Pro script font from Underware is a brush-like design that includes many special ligatures (click image to view):

    Note the special ligatures for “and” and “by”, the use of all small caps and the use of alternate glyphs to enhance the script connection between the letters in “Smooching”.  Only font styling is used here, all the text can be selected and copied, there are no images used on the example page.

    Number styles

    Using Minion Pro from Adobe, available via Typekit, the example below illustrates the use of tabular, monospaced number forms to display columns of data in a way that’s easy to read and analyze.  When proportional numbers are used, the width of large figures with the same number of digits will vary. Normally this would require using a different, monospaced font.  But with OpenType fonts that provide number formatting features, authors can use a single font without giving up the readibility of large data sets (click image to view):

    Fonts may use either tabular or proportional number forms by default; providing access to these features allows authors to use both proportional figures for inline text and tabular figures for tabular data without the need to switch fonts.

    Automatic fractions

    Recipes for American dishes often use fractional amounts.  These can easily be rendered using the automatic fraction feature in OpenType (click image to view):

    Each of the fractions above is written in simple text form, (e.g. 2 1/2), no special Unicode codepoints are used.  For fonts that support automatic fractions, an OpenType layout engine will automatically generate fractional forms for numbers separated by a slash.  These are typically limited to simple fractions, for more complex math expressions markup languages like MathML should be used instead.

    Language sensitivity

    Many languages often use a common script and over time differences in usage naturally arise.  Serbian, Macedonian and Bulgarian all use the Cyrillic script but with slightly different glyph forms for some common characters.  OpenType fonts support the ability to specify script-specific and language-specific glyph handling so given the correct lang attribute in the markup of a page, Firefox 4 can now render text in a language-specific way (click image to view):

    Arbitrary features

    OpenType defines font feature support using an underlying set of primitives. This allows font designers the ability to create their own features, either for a specialized purpose or as a general feature to be included in a future version of the OpenType specification.  Since the syntax of -moz-font-feature-settings allows for the use of arbitrary feature tags, these can be accessed via CSS.

    In the example below, font designer Erik van Blokland of LettError uses a custom designed set of feature properties to create an interesting animation effect when hovering over text on the page (click image to view):

    HarfBuzz, an OpenType shaping engine

    The process of selecting and positioning glyphs used to display text runs has in the past always been done via platform libraries such as Uniscribe on Windows and CoreText on OSX.  To assure more robust and consistent text rendering across platforms, Firefox 4 will use the open source HarfBuzz OpenType shaping engine on all platforms. In the future this will allow us to integrate support for complex Indic and Southeast Asian scripts that have often been ignored or supported inconsistently in the past.

    A Note About Typekit Use

    All of the Adobe fonts available via the Typekit webfont service provide access to the full range of OpenType features found in the original fonts.  But to access those features you’ll need to explicitly enable “All Characters” under the “Language Support” category in the kit editor dialog before publishing.

    Other examples

    (Updated from a blog post last year):

    Update: the content of the examples is now editable! Edit the text of each example to experiment with the different font features.

  6. Firefox 4: Drawing arbitrary elements as backgrounds with -moz-element


    This is a guest post by Markus Stange. Markus usually works on the Firefox Mac theme implementation, but this time he went on a small side trip through the Gecko layout engine in order to implement -moz-element.

    In Firefox Beta 4 we’re introducing a new extension to the CSS background-image property: the ability to draw arbitrary elements as backgrounds using -moz-element(#elementID).

    <p id="myBackground1" style="background: darkorange; color: white;  width: 300px; height: 40px;">
      This element will be used as a background.
    </p>
    <p style="background: -moz-element(#myBackground1); padding: 20px 10px; font-weight: bold;">
      This box uses #myBackground1 as its background!
    </p>



    A -moz-element() image works just like a normal url() image. That means it’s subject to all the familiar background properties like background-position, background-repeat, and even background-size.

    Using background-size you can create a thumbnail of the referenced element, for example:

    <ul id="thumbnails">
      <li style="background-image: -moz-element(#slide-0)"></li>
      <li style="background-image: -moz-element(#slide-1)"></li>
      <li style="background-image: -moz-element(#slide-2)"></li>
      <li style="background-image: -moz-element(#slide-3)"></li>
    </ul>
    #thumbnails li {
      width: 160px;
      height: 120px;
      background-repeat: no-repeat;
      background-size: contain;
    }



    There are three things to keep in mind about -moz-element:

    1. It’s live: whenever something happens in the referenced element, the -moz-element background image will be updated. It will also show things like text selection or blinking carets.

    2. It’s purely visual. That means you can’t “click through” to the original element. That’s by design.

    3. It works with any HTML element. Even with <iframe>



      <video>



      … and <canvas>.



    Canvas-as-background is in fact useful for some applications. For example, if you’re applying sepia tone to CSS background images in the browser, you now no longer have to convert the processed canvas image into a data URI. Instead, you can just set the canvas itself as the background image.

    Using a canvas as a background image is supported by Webkit, too, using -webkit-canvas().

    Painting loops

    A quick note on recursive references: If you try to paint an element that is already being painted via -moz-element, a painting loop will be detected and prevented. So you’ll need to think of a different way of drawing your Sierpinski carpets.

    Hiding the Referenced Element

    Sometimes you don’t want the original referenced element to be visible, only the -moz-element background image. So what do you do? You can’t just set display: none or visibility: hidden on the element, because then there’s nothing to draw in the -moz-element background image either – it will be transparent.

    Instead, you need to prevent the element from being rendered on the screen without really hiding it. One way of doing that is to wrap it with another element that has height: 0; overflow: hidden; set on it.

    There are three types of elements that are exempt from this rule: images, canvases and videos. These kinds of elements can have display: none and still be used in -moz-element. In fact, they don’t even need to be in the DOM.

    New DOM API:
    document.mozSetImageElement

    We added a new method to the document object: document.mozSetImageElement(<elementID>, <element>).

    Consider this piece of code:

    var slide5 = document.getElementById("slide-5");
    document.mozSetImageElement("current-slide", slide5);

    Now all elements with background-image: -moz-element(#current-slide) will draw the element with the ID slide-5, even if there is a real element with the ID current-slide!

    Calling document.mozSetImageElement("current-slide", null) will stop the override.

    This API can be handy in a variety of use cases. I already alluded to one of them in the previous section: with mozSetImageElement you can use canvas and image elements that aren’t part of the DOM tree.

    var img = new Image();
    img.src = "my_image.png";
    document.mozSetImageElement("image", img);
     
    var canvas = document.createElement("canvas");
    canvas.width = canvas.height = 100;
    var ctx = canvas.getContext("2d");
    // ... draw into ctx ...
    document.mozSetImageElement("canvas", canvas);

    View Demo

    Another scenario that benefits from mozSetImageElement involves JavaScript utility libraries. You might have a function like this:

    var runningNumber = 0;
    function addReflectionToElement(reflectedElement) {
      var referenceID = "reflected-element-" + runningNumber++;
      var reflection = document.createElement("div");
      reflection.className = "reflection";
      reflection.style.backgroundImage =
        "-moz-element(#" + referenceID + ")";
      document.mozSetImageElement(referenceID, reflectedElement);
      // ... insert reflection into the DOM ...
    }

    This way you can minimize the impact of your utility function because you don’t have to manipulate the ID of the element that was passed in.

    Finally, mozSetImageElement also allows you to reference elements from other documents, for example from inside iframes – obeying same origin restrictions, of course.

    -moz-element for SVG paint servers: patterns and gradients

    If you’ve ever written any SVG by hand you’re familiar with the concept of paint servers: those are the things you can use in your fill and stroke attributes when you don’t just want a single solid color. Now you can use them on HTML elements, too, using -moz-element:

    <p style="background: -moz-element(#pattern),
                          -moz-element(#gradient);
              padding: 10px; color: white">
      This element has both types of SVG paint servers
      in its background: a pattern and a gradient.
    </p>
     
    <svg height="0">
      <linearGradient id="gradient" x2="0" y2="1">
        <stop stop-color="black" offset="0%"/>
        <stop stop-color="red" offset="100%"/>
      </linearGradient>
      <pattern id="pattern" patternUnits="userSpaceOnUse"
               width="60" height="60">
        <circle fill="black" fill-opacity="0.5"
                cx="30" cy="30" r="10"/>
      </pattern>
    </svg>


    Note that we didn’t even have to use XHTML in order to be able to embed SVG thanks to our new HTML5 parser.

    This feature overlaps the functionality of CSS gradients and SVG images, but is very useful in some situations, such as animations. For example, say you want to create a progress bar with an animated gradient like this:

    You could do this with a CSS gradient and some JavaScript that periodically updates the background-position property. But you could also use an SVG gradient that’s animated with SMIL, requiring no JavaScript whatsoever:

    <div style="background: -moz-element(#animated-gradient);">
    </div>
     
    <svg height="0">
     
      <linearGradient id="animated-gradient" spreadMethod="reflect"
                      gradientUnits="userSpaceOnUse"
                      x1="16" x2="24" y2="0">
        <animate attributeName="x1" values="16; 0" dur="350ms"
                 repeatCount="indefinite"/>
        <animate attributeName="x2" values="24; 8" dur="350ms"
                 repeatCount="indefinite"/>
     
        <stop stop-color="#0F0" offset="0"/>
        <stop stop-color="#0D0" offset="100%"/>
      </linearGradient>
     
    </svg>

    View Demo

    The same could be achieved with CSS animations, but as long as they’re not implemented in Gecko you can use this.

    Support for SVG as a CSS background (bug 276431) will be added soon.

    Also, here’s a CSS + SVG Pacman for you.

    Applications

    I have two more suggestions for -moz-element usage:

    Reflections

    What is a reflection?

    #reflection {
      /* It's a copy of the original element... */
      background: -moz-element(#reflected-element)
                  bottom left no-repeat;
     
      /* ... turned upside down ... */
      -moz-transform: scaleY(-1);
     
      /* ... with a gradual fade-out effect towards the bottom. */
      mask: url(#reflection-mask);
    }



    Because we can apply arbitrary styles to the reflection, we can produce effects like animated water ripples.

    Fancy Slide Transitions

    In this demo I’d like to have a slideshow transition that looks like the upper half of the previous slide gets folded down to reveal the next slide:

    How would you implement this? You’ll obviously need to use some kind of transform, but on what element? The upper half of the slide needs to have a different transform than the lower half, so you can’t just set the transform on the slide itself.

    I ended up creating four new elements: #previousUpper, #previousLower, #nextUpper and #nextLower. I put them into a separate container called #transition which is only made visible while a transition is in progress. Then I gave them the right size and assigned the corresponding subimage of the previous / next slides to them using background-image: -moz-element(#previous/nextSlide) and the right background-position. And finally I set the transform on these helper elements.

    The code for it gets quite complex, though, so I’ll just direct you to the finished demo.

    More?

    My ideas for -moz-element demos have run out for the moment, but there’s bound to be more stuff one can do with it. Now it’s your turn!

    Credits

    Most of the credit here should go to Robert O’Callahan who cooked up the initial implementation back in 2008. After his initial experiments he had to work on more important things, though, so his patches lay dormant for about a year until he started a newsgroup thread to work out the right API in July 2009. Shortly after that, Ryo Kawaguchi revived roc’s work and spent the last weeks of his internship at Mozilla on it. Another year later I made the patch ready for review and drove it through the final stages until checkin.

    The same warnings as for mozRequestAnimationFrame apply: -moz-element and document.mozSetImageElement are experimental APIs. We do not guarantee to support them forever, and we wouldn’t evangelize sites to depend on them. We’ve implemented them so that people can experiment with them and we can collect feedback. We’ll propose it as a standard (minus the moz prefix, obviously), and author feedback on our implementation will help us make a better standard.

  7. Firefox 4 Beta 2 is here – Welcome CSS3 transitions

    As we have explained before, Mozilla is now making more frequent updates to our beta program. So here it is, Firefox Beta 2 has just been released, 3 weeks after Beta 1.

    Firefox 4 Beta 1 already brought a large amount of new features (see the Beta 1 feature list). So what’s new for web developers in this beta?

    Performance & CSS3 Transitions

    The two major features for web developers with this release are Performance improvements and CSS3 Transitions on CSS3 Transforms.

    This video is hosted by Youtube and uses the HTML5 video tag if you have enabled it (see here). Youtube video here.

    Performance: In this new Beta, Firefox comes with a new page building mechanism: Retained Layers. This mechanism provides noticeable faster speed for web pages with dynamic content, and scrolling is much smoother. Also, we’re still experimenting with hardware acceleration: using the GPU to render and build some parts of the web page.

    CSS3 Transitions on transforms: The major change for web developers is probably CSS3 Transitions on CSS3 Transformations.

    CSS3 Transitions provide a way to animate changes to CSS properties, instead of having the changes take effect instantly. See the documentation for details.

    This feature was available in Firefox 4 Beta 1, but in this new Beta, you can use Transitions on Transformation.

    A CSS3 Transformation allows you to define a Transformation (scale, translate, skew) on any HTML element. And you can animate this transformation with the transitions.

    See this box? Move your mouse over it, and its position transform: rotate(5deg); will transform transform: rotate(350deg) scale(1.4) rotate(-30deg); through a smooth animation.
    #victim {
      background-color: yellow;
      color: black;
     
      transition-duration: 1s;
      transform: rotate(10deg);
     
      /* Prefixes */
     
      -moz-transition-duration: 1s;
      -moz-transform: rotate(5deg);
     
      -webkit-transition-duration: 1s;
      -webkit-transform: rotate(10deg);
     
      -o-transition-duration: 1s;
      -o-transform: rotate(10deg);
    }
    #victim:hover {
      background-color: red;
      color: white;
     
      transform:  rotate(350deg) scale(1.4) rotate(-30deg);
     
      /* Prefixes */
     
      -moz-transform:  rotate(350deg) scale(1.4) rotate(-30deg);
      -webkit-transform:  rotate(350deg) scale(1.4) rotate(-30deg);
      -o-transform:  rotate(350deg) scale(1.4) rotate(-30deg);
    }

    CSS 3 Transitions are supported by Webkit-based browsers (Safari and Chrome), Opera and now Firefox as well. Degradation (if not supported) is graceful (no animation, but the style is still applied). Therefore, you can start using it right away.

    Demos

    I’ve written a couple of demos to show both CSS3 Transitions on Transforms and hardware acceleration (See the video above for screencasts).

    This demo shows 5 videos. The videos are Black&White in the thumbnails (using a SVG Filter) and colorful when real size (click on them). The “whirly” effect is done with CSS Transitions. Move you mouse over the video, you’ll see a question mark (?) button. Click on it to have the details about the video and to see another SVG Filter applied (feGaussianBlur).
    This page shows 2 videos. The top left video is a round video (thanks to SVG clip-path) with SVG controls. The main video is clickable (magnifies the video). The text on top of the video is clickable as well, to send it to the background using CSS Transitions.
    This page is a simple list of images, video and canvas elements. Clicking on an element will apply a CSS Transform to the page itself with a transition. White elements are clickable (play video or bring a WebGL object). I encourage you to use a hardware accelerated and a WebGL capable browser. For Firefox on Windows, you should enable Direct2D.

    Credits

    Creative Commons videos:

    The multicolor cloud effect (MIT License)

  8. Firefox 4: CSS3 calc()

    This article describes the CSS3 calc() value. This feature hasn’t landed yet in any Firefox tree but work to implement it is underway.

    Firefox will support the CSS calc() value, which lets you compute a length value using an arithmetic expression. This means you can use it to define the sizes of divs, the values of margins, the widths of borders, and so forth.

    Here is an example of a layout which would be tricky to setup without the calc() function:

    /*
    * Two divs aligned, split up by a 1em margin
    */
    #a {
      width:75%;
      margin-right: 1em;
    }
    #b {
      width: -moz-calc(25% - 1em);
    }

    This example makes sure an input text field won’t overlap its parent:

    input {
      padding:2px;
      border:1px solid black;
      display:block;
      width: -moz-calc(100% - 2 * 3px);
    }

    One particularly powerful feature of the calc() function that you can combine different units in the same computation:

    width: -moz-calc(3px + 50%/3 - 3em + 1rem);

    The current implementation supports the +, -, *, /, mod, min, and max operators.

    We’ll also support the min() and max() functions, which could be used like this:

    div {
      height: -moz-min(36pt, 2em);
      width: -moz-max(50%, 18px);
    }

    For more details, see:

  9. Firefox 4: -moz-any() selector grouping

    This is a re-post from David Baron’s blog. This feature has landed in Mozilla Central (trunk) and only available with a Firefox Nightly Build for the time being.

    Last night I landed support for :-moz-any() selector grouping. This allows providing alternatives between combinators, rather than having to repeat the entire selector for once piece that’s different. For example, it allowed replacing this rule in our user-agent style sheet:

    /* 3 deep (or more) unordered lists use a square */
    ol ol ul,     ol ul ul,     ol menu ul,     ol dir ul,
    ol ol menu,   ol ul menu,   ol menu menu,   ol dir menu,
    ol ol dir,    ol ul dir,    ol menu dir,    ol dir dir,
    ul ol ul,     ul ul ul,     ul menu ul,     ul dir ul,
    ul ol menu,   ul ul menu,   ul menu menu,   ul dir menu,
    ul ol dir,    ul ul dir,    ul menu dir,    ul dir dir,
    menu ol ul,   menu ul ul,   menu menu ul,   menu dir ul,
    menu ol menu, menu ul menu, menu menu menu, menu dir menu,
    menu ol dir,  menu ul dir,  menu menu dir,  menu dir dir,
    dir ol ul,    dir ul ul,    dir menu ul,    dir dir ul,
    dir ol menu,  dir ul menu,  dir menu menu,  dir dir menu,
    dir ol dir,   dir ul dir,   dir menu dir,   dir dir dir {
      list-style-type: square;
    }

    with this one:

    /* 3 deep (or more) unordered lists use a square */
    :-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) ul,
    :-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) menu,
    :-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) dir {
      list-style-type: square;
    }

    In theory, I could even have used:

    /* 3 deep (or more) unordered lists use a square */
    :-moz-any(ol, ul, menu, dir) :-moz-any(ol, ul, menu, dir) :-moz-any(ul, menu, dir) {
      list-style-type: square;
    }

    but this would have been slower since it no longer falls into the tag bucket. (If :-moz-any() turns out to be popular, we could add extra code so it’s just as fast, but I haven’t done so yet.)

    :-moz-any() is allowed to contain selectors with multiple simple selectors (using the css3-selectors definition of simple selectors, not the CSS 2.1 definition), but it is not allowed to contain combinators or pseudo-elements. So you can write :-moz-any(p.warning.new, p.error, div#topnotice) or :-moz-any(:link, :visited).external:-moz-any(:active, :focus), but you can’t put “div p” or “div > p or “:first-letter” inside :-moz-any().

    This has a -moz- prefix for two reasons. First, it’s just a proposal, and hasn’t made its way into any specification. And second, it isn’t quite ready for prime-time, though, since it doesn’t yet handle specificity correctly.

    Note: This will be extremely valuable in an HTML5 context when it comes to sections and headings. Since section, article, aside, and nav can be nested, doing something like styling all h1 elements at different depths could be extremely complex.

    /* Level 0 */
    h1 {
      font-size: 30px;
    }
    /* Level 1 */
    section h1, article h1, aside h1, nav h1 {
      font-size: 25px;
    }
    /* Level 2 */
    section section h1, section article h1, section aside h1, section nav h1,
    article section h1, article article h1, article aside h1, article nav h1,
    aside section h1, aside article h1, aside aside h1, aside nav h1,
    nav section h1, nav article h1, nav aside h1, nav nav h1, {
      font-size: 20px;
    }
    /* Level 3 */
    /* ... don't even think about it*/

    With -moz-any():

    /* Level 0 */
    h1 {
      font-size: 30px;
    }
    /* Level 1 */
    -moz-any(section, article, aside, nav) h1 {
      font-size: 25px;
    }
    /* Level 2 */
    -moz-any(section, article, aside, nav)
    -moz-any(section, article, aside, nav) h1 {
      font-size: 20px;
    }
    /* Level 3 */
    -moz-any(section, article, aside, nav)
    -moz-any(section, article, aside, nav)
    -moz-any(section, article, aside, nav) h1 {
      font-size: 15px;
    }
  10. The CSS 3 Flexible Box Model

    This article about the Flexible Box Layout was written by Jérémie Patonnier, French open Web enthusiast.

    The flexible box model

    CSS 3 introduces a brand new box model in addition of the traditional box model from CSS 1 and 2. The flexible box model determines the way boxes are distributed inside other boxes and the way they share the available space.

    You can see the specification here.

    This box model is similar to the one used by XUL (the user interface language used by Firefox). Some others languages use similar box models such as XAML or GladeXML.

    Usually the flexible box model is exactly what you need if you want to create fluid layouts which adapt themselves to the size of the browser window or elastic layouts which adapt themselves to the font size.

    In this article, all my examples are based on the following HTML code:

    <body>
      <div id="box1">1</div>
      <div id="box2">2</div>
      <div id="box3">3</div>
    </body>

    Distributing boxes: so what?

    By default, the traditional CSS box model distributes boxes vertically depending on the HTML flow. With the flexible box model, it’s possible to specify the order explicitly. You can even reverse it. To switch to the flexible box model, set the property display to the value box (or inline-box) on a box which has child boxes.

    display: box;

    Horizontal or vertical distribution

    The box-orient property lets you specify the distribution axis. vertical and horizontal values define how boxes are displayed. Other values (inline-axis and block-axis) have the same effect, but also let you define the baseline alignment itself (basically the boxes are treated like “inline” boxes).

    body{
      display: box;
      box-orient: horizontal;
    }

    Reversed distribution

    The property box-direction allows you to set the order in which the boxes appear. By default–when you simply specify the distribution axis–the boxes follow the HTML flow and are distributed from top to bottom if you are using a vertical axis and from left to right if you are using a horizontal axis. By setting box-direction to reverse, you can reverse the boxes’ distribution order. It acts as if you actually reversed the order of the elements in the HTML.

    Be careful with this property because it changes the way some other properties work, which can produce some unexpected behavior.

    body {
      display: box;
      box-orient: vertical;
      box-direction: reverse;
    }

    Explicit distribution

    The property box-ordinal-group lets you specify the order in which the boxes will be distributed. This is the ultimate customization opportunity, because you can define the order you want, regardless of the HTML flow order. Those groups are defined by a number starting at 1 (which is the default value). So the box model will first distribute those groups, then all the boxes inside each group. The distribution occurs from the lowest value (the group numbered 1) to the highest (the groups numbered 2 and above).

    body {
      display: box;
      box-orient: vertical;
      box-direction : reverse;
    }
    #box1 {
      box-ordinal-group: 2;
    }
    #box2 {
      box-ordinal-group: 2;
    }
    #box3 {
      box-ordinal-group: 1;
    }

    And what about flexibility?

    If changing the natural HTML flow order is huge, the real fun begins when you start to deal with the available space.

    Box sizing

    By default, a box is not flexible. It becomes flexible only if it has the property box-flex with a value of at least 1.

    If a box is not flexible, it will be as wide as possible to make its content visible without any overflow. Its size can be forced with the properties width and height (or their min-*, and max-* alternatives).

    If a box is flexible, its size will be computed as follows:

    1. The explicit size declarations (width, height, min-* and max-*)
    2. The size of the parent box and all the remaining available inner space.

    So, if the boxes haven’t any size declarations, their sizes will fully depend on their parent box’s size. It will work like this: the size of box is equal to the size of its parent multiplied by the value of the its box-flex property divided by the sum of all the box-flex properties values of all boxes included in its parent.

    On the other hand, if one or more boxes have an explicit size statements, the size of all those boxes is computed and all the flexible boxes share the remaining available space on the same principle as above.

    It probably sounds a bit tricky, but with some examples it will become easier.

    All boxes are flexible

    In the next example, box 1 is twice the size of box 2 and box 2 has the same size as box 3. It looks the same as using percentages to set the boxes’ sizes. But there is a big difference. If you add a box, you don’t need to recalculate its size. With the flexible box model, each time you add a box, all the others automatically shrink to make room for the new one.

    body {
      display: box;
      box-orient: horizontal;
    }
    #box1 {
      box-flex: 2;
    }
    #box2 {
      box-flex: 1;
    }
    #box3 {
      box-flex: 1;
    }

    Some boxes have a fixed size

    In the next example, box 3, which is not flexible, is 160px in width. In this case, there’s 240px of free space available for boxes 1 and 2. So, box 1 will be 160px in width (240px x 2/3) and box 2 will be 80px in width (240px x 1/3). If you wish, you can make box 3 flexible as well. In this case the way the size of this box is computed will be almost the same as with the property min-width.

    body {
      display: box;
      box-orient: horizontal;
      width: 400px;
    }
    #box1 {
      box-flex: 2;
    }
    #box2 {
      box-flex: 1;
    }
    #box3 {
      width: 160px;
    }

    Managing overflow

    Because we can mix flexible boxes, inflexible boxes, and flexible boxes which have preset sizes, It’s possible for the sum of all the boxes’ sizes to be larger or smaller than the parent box size. So you can have too much space or not enough.

    I have too much space available; what do I do?

    The available space gets distributed depending on the properties box-align and box-pack

    The property box-pack manages the way the space is distributed on the horizontal axis and can have one of four possible values: start, end, justify, or center

    1. start: All the boxes are on the left side of the parent box and all the remaining space is on the right side.
    2. end: All the boxes are on the right and the remaining space is on the left
    3. justify: The available space is divided evenly in-between each boxes
    4. center: The available space is divided evenly on each side of the parent box

    The property box-align manages the way the space is distributed on the vertical axis and can have one of five values: start, end, center, baseline, and stretch

    1. start: The top edge of each box is placed along the top of the parent box and all the remaining space is placed below.
    2. end: The bottom edge of each box is placed along the bottom of the parent box and all the remaining space is placed above.
    3. center: The available space is divided evenly and placed half above and half below.
    4. baseline: All children are placed with their baselines aligned and the remaining space is placed before or after as necessary (This is a simplification about how this value really works, but you see the point).
    5. stretch: The height of each boxes is adjusted to fit the parent box height

    A warning about how those properties work: they are strongly influenced by the use of the properties box-orient and box-direction. They can cause some unexpected behavior (for example, the behavior of values start and end could be fully reversed). I hope that once the specification is finalized, we’ll have more information about how those properties work together.

    body {
      display: box;
      box-orient: horizontal;
      /* The content of the body is horizontally centered */
      box-pack: center;
      /* and vertically as well ... \o/ */
      box-align: center;
      width: 100%;
      height : 100%;
    }

    What happens if I don’t have enough space?

    Just like with the traditional box model, the overflow property lets you to define the way it’s managed. No surprise here.

    However, you must be careful here too. Indeed, the use of the properties box-orient and box-direction can mess it up. For example, you can see elements overflowed to the right instead of the left or to the top instead of the bottom. Take the time to experiment before trying to use it on a big project or you could go mad.

    You can also avoid overflow by making the boxes run over multiple lines (or columns, depending on the orientation) by setting the property box-lines to multiple.

    Okay, cool, but does it work in real life?

    Yes it does! Both Gecko and WebKit have vendor-prefixed implementations of a box model (Note: The current state of the specification does not reflect Mozilla’s or WebKit’s implementation). This means that Firefox, Safari, Chrome, and any browsers that use one of those rendering engines are able to use the features described in this article. If you use one of those awesome browsers, here is a little demo of the flexible box model in action.

    If you’re not using a browser implementing a box model, this screenshot shows you what it looks like:

    To conclude

    You can start to use this box model to layout your HTML documents with modern web browsers. Be careful though, it’s the really first iteration of a W3C Working Draft. There will certainly be some changes. Anyway, the implementations available in Gecko and Webkit are extremely consistent and mature, so if there are changes, they should not be that troublesome.

    This box model is a very easy and simple way to solve some usual problems in web design (form layout, page footers, vertical centering, disassociation of visual flow from HTML flow, etc.). I strongly suggest you become familiar with it because it could become a standard tool for web designers in the near future (if Microsoft decides to include it in IE, it could become so very fast).

    What is already available is a good start to play with. But at this point, the way the traditional box model and the flexible box model interact is not very clear (for example, it’s impossible to use position:relative with the properties left or top on a box which uses the property box-ordinal-group). This will be improved, but don’t be surprised if your work habits are somewhat undermined. Another tricky point: the way all the properties relative to this new box model interact can be sometimes really confusing. This should remind you of the day you discovered the float property. ;)

    For further information