Mozilla

CSS Articles

Sort by:

View:

  1. Advanced animations in Aurora with CSS3 Animations

    Firefox 4 came with CSS3 Transitions (ability to animate CSS properties from an initial value to a final one). In Firefox Aurora, we are experimenting with CSS3 Animations: a more powerful way to animate your content with CSS.

    Defining the animation

    The first thing is to define the intermediary CSS values of the properties to be animated, what is called keyframes in the specification. Users of Adobe Flash authoring tools should be familiar with this concept.

    Applying an animation

    While Transitions trigger implicitly when property values change, animations are explicitly executed when the animation properties are applied.

    More properties

    The specification defines other animation properties that opens a broad range of possibilities:

    • with animation-timing-function it is possible to take advantage of easings to make animations feel more natural (see demo below)
    • animation-direction: alternate; is the auto-reverse of CSS3 Animations. See how it is used to create the loader below.
    • without animation-fill-mode: forwards;, the properties will be set back to their initial values at the end of the animation
    • and guess what setting animation-play-state to paused would do…

    Demo!

    You should be using Firefox Aurora, Chrome or Safari 5 to see those demo.
    animated translations

    zero-image, gracefully degrading loader

    a complex animated scene
    View Madmanimation with a compatible browser, or watch a screencast of the animation.

    You’ve already used CSS3 animations? Let us know in the comment below or submit your demo in the Studio.

  2. MDN Learning: A place to ratchet your Web development skills

    If you’re looking to improve your Web development skills, we have compiled some great resources from around the Web to help every level of developer dig into their favorite open Web technologies. Our new MDN Learning space serves as a starting point for anyone interested in learning more about Web development. While there is already awesome documentation on MDN, not everyone knows how to find it — or other great tutorials and examples scattered around the Web. There is just so much content out there, we felt it was time to create a central place developers can go to quickly find the best resources.

    MDN Learning

    Our initial set of pages focus on documentation, tutorials, and other content for learning HTML, CSS and JavaScript. We will continue to add new content, including MDN Learning pages for topics like video, audio, webGL, etc. We also plan to use this new space to share more information about our collaboration with other organizations and projects that are developing open models around education, like P2PU’s School of Webcraft.

    This launch of MDN Learning is just the beginning of what we hope will become a permanent place on MDN for everything related to educating people about Web development and the resources available to them on not just MDN, but around the Web. We look forward to feedback and suggestions on how we can improve on this first step towards expanding MDN to cater to those getting started with developing for the Web.

  3. Promoting the use of new web technologies in Lithuania

    Last week around 2500 developers, designers, entrepreneurs and managers came to Vilnius, Lithuania to attend the fifth Login conference. Speakers included people from Nokia, Wired, Flattr.com (run by the founder of the Pirate Bay), Tate Modern and Amnesty international and the conference covered everything from viral video over web security and privacy up to bleeding edge web development practices.

    My job for Mozilla was to deliver the final keynote to remind people what they heard in the two days and to get them excited to play with the new toys we talked about. Here are the slides and the extensive notes of the talk. A video will be available soon and we will publish it here when it is out.

    Slides of the closing keynote “Building a better web with open, new technologies”

    You can also see and download an annotated version on Slideshare.

    Talk Notes

    Today I will talk about exciting new open technologies and how you can use them to change the web for better and make a name for yourself at the same time.

    I am Chris Heilmann, I work as the principal evangelist for Mozilla and I concentrate on HTML5 and the open web. I am a developer evangelist and if you don’t know what that is check out developer-evangelism.com to learn all about it.

    I am a film buff – I don’t watch TV, I watch movies instead. And I love quirky movies. One of them I devoured lately was “The Hudsucker Proxy” by the Coen brothers. In this movie we get introduced to Norville Barnes, an business school graduate going to New York to find fame and fortune as an entrepreneur – only to end up as a lowly clerk in the mail room of a company. Norville, however, has ideas and a complete and utter lack of skill telling people about them. His pitch for his great idea is showing people a piece of paper with a ring on it saying “You know, for kids”. Norville gets a chance when the Boss of the company retires – by jumping out of the window. The other stakeholders find his will and realise that they are to make the company stock public which entices them to make sure the stock plummets beforehand. To make that happen they want to hire a complete idiot as CEO – and that is Norville.

    Norville gets the chance to build his invention which turns out to be the hula hoop. The company spends a lot of time with an advertising campaign and it fails immensely – nobody wants to buy a hula hoop. When a shop owner throws them out in the street and a kid starts using it in front of a school everything changes. The hula hoop becomes a massive success.

    So what does that have to do with this conference?

    The hula hoop is a great example of a product that should not need any marketing but works by seeing other people use it and needs one person to show how much fun it is to use it.

    Using new and cool things should not need any marketing…

    And this is what modern web technologies are. It is a total no-brainer to upgrade the technologies that drive the web. But instead of just giving them to the people who care about them we wait for big players to do it for us.

    There is no point in thinking about amazing technologies and waiting for magic to happen. A lot of the things we thought about are not really clever if you look at them closely.

    Just jump in and join the ride!

    Well, I am here today to tell you that you can and should use all the new tech you can get your hands on – for the sake of the web and for the sake of your companies.

    Aim for the long goal…

    Supporting new technology based on standards means that you are in it for the long term. You want to build something cool and new but you also want to make it maintainable in the future. The technologies are not hard to learn – CSS, JavaScript and HTML have been around for ever. The great news nowadays is that today we can build amazing things with them.

    Use the whole stack

    As entrepreneurs and new developers I think it is our duty to embrace new technologies and bring them to the main market. Old and settled companies do not have that chance. So take a stand and step into the circle and start moving.

    HTML5 provides us with much richer forms than ever before. We have Autocomplete controls, colour pickers, URL, phone and email fields that tap into the contacts DB of our smartphones and date pickers. Each of these also come with browser validation built-in which makes it much easier to build a great experience.

    Finding a visitor’s location is as simple as 3 lines of JavaScript – and using free databases like Yahoo’s GeoPlanet you can turn this for example into an address and pre-fill a form for the user with a “find me” button. Wouldn’t that be useful?

    With local and offline storage I can make my application work even when the visitor is on the go. Being without connectivity shouldn’t be the end of your application – simple tell the user you are offline and store the data locally until you can sync again. Local storage can also be used to cache information for the user that doesn’t have to be loaded from your server over and over again.

    Using SVG and Canvas we can paint on the web. We can build immensely rich interactive graphs and we can create games that until now where only available in Flash or Silverlight. D3 is a great library to turn any data in the document into an interactive graph. Libraries like d3.js can help you there a lot.

    CSS3 allows styling to go beyond adding colours, dimensions and fonts. You can build interfaces that resize according to the available screen, do transformations and create shadows and gradients.

    Using native video and audio you can interact with the document in a very simple manner. You can overlay videos and react to the time of the current video. In this example I’ve built the Indiana Jones maps by overlaying a video over an animated map. You can use this technology to simply build interactive video tutorials.

    You can easily build your own video players that have functionality that none of them had before – here for example I wrote a video player that allows you to zoom and rotate videos.

    Using Canvas and SVG together with video you can dynamically analyse the video data and react with it. In this demo we find the white parts of a video and use it as anchor points for injecting content.

    By using touch gestures and device orientation you can make your products much easier to use for humans – the games industry blossomed the last few years exactly because of that.

    WebGL allows you to use real 3D models natively in the browser. Check out the amazing Body Browser example by Google.

    Messaging and Workers

    Using Websockets for messaging between your site and the computers you can build real-time applications that scale up to thousands of users. Worker threads means that you can calculate intensely with JavaScript without slowing down the interface.

    Be greedy and aim for the best experience.

    Whilst in the past a HTML version of a certain system was a fallback for a Flash site when it comes to beautiful and rich experiences right now we don’t need to hide any longer. It is time to take the new technologies and build beautiful experiences with them.

    Through the looking glass…

    The great thing about using open web technologies is that you are fully in the open. Everybody can see what you are doing. This sounds scary but in the tech world is actually a big bonus. Debugging a product is much easier when there is no compilation necessary. As an extra bonus open systems also ensure that you attract talent. If your product features newest and coolest technology you will find it a much less arduous job to hire developers. Geeks love to be part of something cool and new. If you open up your source code – even better.

    Give your tech people a voice

    The next big step to being open is to trust your techies. Instead of hiding your technology skills have a blog with your achievements where you talk about your people and how they work. This shows that you care about your tech as much as your money.

    Of course there are problems!

    Nothing works immediately without any issues. There is no point pretending that this is the case. Not everything you use will fit. There are browser differences and support issues with the technologies we have right now. Embedding audio and video should be easy in HTML5 – it should be as simple as pointing to a video to add it to a document. Copyright and licensing differences across different browsers makes it necessary to have the video in 3 different formats though.

    You can’t expect everybody to have the newest browsers. IE6 is still around and a thorn in the side of any developer. However, it is dwindling and Microsoft is actively fighting the issue.

    Use things to help you out

    The work on the specifications is totally open and anyone can take part. You can see HTML5 as a debate club right now, and you are invited to state your case. There is lots of free up-to date documentation available on the web for you – for example on HTML5 Doctor or even a full book Dive into HTML5 by Mark Pilgrim.

    Modernizr is a JavaScript to embed in your products that tests for the support of all the new technology. It adds classes on the HTML element for you to read out and react to. HTML boilerplate is a copy and paste start to use HTML5 in your projects – it includes Modernizr and resets the CSS and gives you the correct server settings.

    Vid.ly is a service by encoding.com that converts video into all the necessary formats and creates a single URL to point your video elements to. And vid.ly doesn’t only create them for browsers – it also supports every handheld device and games console. It even creates videos that are smaller or larger in file size according to the end user’s connection speed.

    Appmator packs an HTML5 web site into a Google Application with one click.

    Build.phonegap.com converts HTML5 applications to native code for all kind of devices in the cloud for you.

    Be part of the evolution

    HTML5 and new technologies should not only be for geeks and people who write all of their products by hand. We should strive for building products that allows us to build with new tech and move things to the browser that until now are still very much desktop jobs. There are some great examples about this already out there.

    • Popcorn and Butter allows you to sync video content with web content and send it as a presentation format to contacts.
    • Aviary is an online HTML5 image editor.
    • Scribd scrapes PDFs and Flash documents and makes them readable in HTML for iPads.
    • Diagramo is an HTML5 editor for flowcharts and diagrams.
    • Slideshare uses websockets for chats and webcasting.

    Don’t pretend new tech doesn’t involve you – let’s work together on this – you know – for a better web!

  4. 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!

  5. 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.

  6. 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.

  7. 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.

  8. 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.

  9. 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.

  10. 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)