1. JavaScript speedups in Firefox 3.6

    This post was written by David Mandelin who works on Mozilla’s JavaScript team.

    Firefox 3.5 introduced TraceMonkey, our new JavaScript engine that traces loops and JIT compiles them to native (x86/ARM) code. Many JavaScript programs ran 3-4x faster in TraceMonkey compared to Firefox 3. (See our previous article for technical details.)

    For JavaScript performance in Firefox 3.6, we focused on the areas that we thought needed further improvement the most:

    • Some JavaScript code was not trace-compiled in Firefox 3.5. Tracing was disabled by default for Firefox UI JavaScript and add-on JavaScript, so those programs did not benefit from tracing. Also, many advanced JavaScript features were not trace-compiled. For Firefox 3.6, we wanted to trace more programs and more JS features.
    • Animations coded with JavaScript were often choppy because of garbage collection pauses. We wanted to improve GC performance to make pauses shorter and animations smoother.

    In this article, I’ll explain the most important JS performance improvements that come with Firefox 3.6. I’ll focus on listing what kinds of JS code get faster, including sample programs that show the improvements Fx3.6 makes over Fx3.5.

    JIT for Browser UI JavaScript

    Firefox runs JavaScript code in one of two contexts:content and chrome (no relation to Google Chrome). JavaScript that is part of web content runs in a content context. JavaScript that is part of the browser UI or browser add-ons runs in a chrome context and has extra privileges. For example, chrome JS can alter the main browser UI, but content JS is not allowed to.

    The TraceMonkey JIT can be enabled or disabled separately for content and chrome JS using about:config. Because bugs affecting chrome JS are a greater risk for security and reliability, in Firefox 3.5 we chose to disable the JIT for chrome JS by default. After extensive testing, we’ve decide to enable the JIT for chrome JS by default, something we did not have time to fully investigate for Fx3.5. Turning on the JIT for chrome should make the JS behind the Firefox UI and add-ons run faster. This difference is probably not very noticeable for general browser usage, because the UI was designed and coded to perform well with the older JS engines. The difference should be more noticeable for add-ons that do heavy JS computation.

    Option Fx3.5 Default Fx3.6 Default
    javascript.options.jit.chrome false true
    javascript.options.jit.content true true
    about:config options for the JIT

    Garbage Collector Performance

    JavaScript is a garbage-collected language, so periodically the JavaScript engine must reclaim unused memory. Our garbage collector (GC) pauses all JavaScript programs while it works. This is fine as long as the pauses are “short”. But if the pauses are even a little too long, they can make animations jerky. Animations need to run at 30-60 frames per second to look smooth, which means it should take no longer than 17-33 ms to render one frame. Thus, GC pauses longer than 40 ms cause jerkiness, while pauses under 10 ms should be almost unnoticeable. In Firefox 3.5, pause times were noticeably long, and JavaScript animations are increasingly common on the web, so reducing pause times was a major goal for JavaScript in Firefox 3.6.

    Demo: GC Pauses and Animation

    Demo.
    The spinning dial animation shown here illustrates pause times. Besides animating the dial, this demo creates one million 100-character strings per second, so it requires frequent GC. The frame delay meter gives the average time between frames in milliseconds. The estimated GC delay meter gives the average estimated GC delay, based on the assumption that if a frame has a delay of 1.7 times the average delay or more, then exactly one GC ran during that frame. (This procedure may not be valid for other browsers, so it is not valid for comparing different browsers. Note also that the GC time also depends on other live JavaScript sessions, so for a direct comparison of two browsers, have the same tabs open in each.) On my machine, I get an estimated GC delay of about 80 ms in Fx3.5, but only 30 ms in Fx3.6.

    But it’s a lot easier to see the difference by opening the demo in Fx3.5, watching it a bit, and then trying it in Fx3.6.
    In Fx3.5, I see frequent pauses and the animation looks noticeably jerky. In Fx3.6, it looks pretty smooth, and it’s hard for me even to tell exactly when the GC is running.

    How Fx3.6 does it better. We’ve made many improvements to the garbage collector and memory allocator. I want to give a little more technical details on the big two changes that really cut our pause times.

    First, we noticed that a large fraction of the pause time was spent calling free to reclaim the unused memory. We can’t do much to make freeing memory faster, but we realized we could do it on a separate thread. In Fx3.6, the main JS thread simply adds unused memory chunks to a queue, and another thread frees them during idle time or on a separate processor. This means machines with 2 or more cores will benefit more from this change. But even when one core, freeing might be delayed to an idle time when it will not affect scripts.

    Second, we knew that in Fx3.5 running GC clears out all the native code compiled by the JIT as well as some other caches that speed up JS. The reason is that the tracing JIT and GC did not know about each other, so if the GC ran, it might reclaim objects being used by a compiled trace. The result was that immediately after a GC, JS ran a bit slower as the caches and compiled traces were built back up. This would be experienced as either an extended GC pause or a brief hiccup of slow animation right after the GC pause. In Fx3.6, we taught the GC and the JIT to work together, and now the GC does not clear caches or wipe out native code, so it resumes running normally right after GC.

    Tracing More JavaScript Constructs

    In my article on TraceMonkey for the Fx3.5 release, I noted that certain code constructs, such as the arguments object, were not traced and did not get performance improvements from the JIT. A major goal for JS in Fx3.6 was to trace more stuff, so more programs can run faster. We do trace more stuff now, in particular:

    • DOM Properties. DOM objects are special and harder for the trace compiler to work with. For Fx3.5, we implemented tracing of DOM methods, but not DOM properties. Now we trace DOM properties (and other “native” C++ getters and setters) as well. We still do not trace scripted getters and setters.
    • Closures. Fx3.5 traced only a few operations involving closures (by which I mean functions that refer to variables defined in lexically enclosing functions). Fx3.6 can trace more programs that use closures. The main operation that is still not traced yet is creating an anonymous function that modifies closure variables. But calling such a function and actually writing to the closure variables are traced.
    • arguments. We now trace most common uses of the arguments keyword. “Exotic” uses, such as setting elements of arguments, are not traced.
    • switch. We have improved performance when tracing switch statements that use densely packed numeric case labels. These are particularly important for emulators and VMs.

    These improvements are particularly important for jQuery and Dromaeo, which heavily use arguments, closures, and the DOM. I suspect many other complex JavaScript applications will also benefit. For example, we recently heard from the author that this R-tree library performs much better in Fx3.6.

    Here is a pair of demos of new things we trace. The first sets a DOM property in a loop. The second calls a sum function implemented with arguments I get a speedup of about 2x for both of them in Fx3.6 vs. Fx3.5.

    Demo: Fx3.6 Tracing DOM properties and arguments


    DOM Property Set:

    Sum using arguments:

    String and RegExp Improvements

    Fx3.6 includes several improvements to string and regular expression performance. For example, the regexp JIT compiler now supports a larger class of regular expressions, including the ever-popular \w+. We also made some of our basic operations faster, like indexOf, match, and search. Finally, we made concatenating sequences of several strings inside a function (a common operation in building up HTML or other kinds of textual output) much faster.

    Technical aside on how we made string concatenation faster: The C++ function that concatenates two strings S1 and S2 does this: Allocate a buffer big enough to hold the result, then copy the characters of S1 and S2 into the buffer. To concatenate more than two strings, as in JS s + "foo" + t, Fx3.5 simply concatenates two at a time from left to right.

    Using the Fx3.5 algorithm, to concatenate N strings each of length K, we need to do N-1 memory allocations, and all but one of them are for temporary strings. Worse, the first two input strings are copied N-1 times, the next one is copied N-2 times, and so on. The total number of characters copied is K(N-1)(N+2)/2, which is O(N^2).

    Clearly, we can do a lot better. The minimum work we can do is to copy each input string exactly once to the output string, for a total of KN characters copied. Fx3.6 achieves this by detecting sequences of concatenation in JS programs and combining the entire sequence into one operation that uses the optimal algorithm.

    Here are a few string benchmarks you can try that are faster in Fx3.6:

    Demo: Fx3.6 String Operations


    /\w+/:

    indexOf('foo'):

    match('foo'):

    Build HTML:

    Final Thoughts and Next Steps

    We also made a lot of little improvements that don't fit into the big categories above. Most importantly, Adobe, Mozilla, Intel, Sun, and other contributors continue to improve nanojit, the compiler back-end used by TraceMonkey. We have improved its use of memory, made trace recording and compiling faster, and also improved the speed of the generated native code. A better nanojit gives a boost to all JS that runs in the JIT.

    There are two big items that didn't make the cut for Fx3.6, but will be in the next version of Firefox and are already available in nightly builds:

    • JITting recursion. Recursive code, like explicit looping code, is likely to be hot code, so it should be JITted. Nightly builds JIT directly recursive functions. Mutual recursion (g calls f calls g) is not traced yet.
    • AMD x64 nanojit backend. Nanojit now has a backend that generates AMD x64 code, which gives the possibility of better performance on that plaform.

    And if you try a nightly build, you'll find that many of these demos are already even faster than in Fx3.6!

  2. interactive file uploads with Drag and Drop, FileAPI and XMLHttpRequest

    In previous posts, we showed how to access a file through the input tag or through the Drag and Drop mechanism. In both cases, you can use XMLHttpRequest to upload the files and follow the upload progress.

    Demo

    If you’re running the latest beta of Firefox 3.6, check out our file upload demo.

    Uploading

    XMLHttpRequest will send a given file to the server as a binary array, so you first need to read the content of the file as a binary string, using the File API. Because both Drag and Drop and the input tag allow you to handle multiple files at once, you’ll need to create as many requests as there are files.

    var reader = new FileReader();
    reader.onload = function(e) {
      var bin = e.target.result;
      // bin is the binaryString
    };
    reader.readAsBinaryString(file);

    Once the file is read, send it to the server with XMLHttpRequest:

    var xhr = new XMLHttpRequest();
    xhr.open("POST", "upload.php");
    xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
    xhr.sendAsBinary(bin);

    You can choose to be notified when specific events, such as error, success, or abort, occur during the request (see the MDC documentation for more details).

    Following the Upload Progress

    The progress event provides the size of the uploaded portion of the binary content. This allows you to easily compute how much of the file has been uploaded.

    Here’s an example showing the percentage of the file that has been uploaded so far:

    xhr.upload.addEventListener("progress", function(e) {
      if (e.lengthComputable) {
        var percentage = Math.round((e.loaded * 100) / e.total);
        // do something
    }, false);
  3. file drag and drop in Firefox 3.6

    In a previous post, we showed you how to upload several files using the input element. In Firefox 3.6, you can let your users drag and drop files directly into your web page, without going through the file picker.

    Demo

    If you’re running the latest Firefox 3.6 beta, check out our interactive demo of drag and drop. It showcases two technologies: the Drag and Drop API and the File API.

    Drag and Drop Events

    To use drag and drop, you first need to tell the browser that a given element can handle dropped objects and will respond to a drop action, using the dragover and drop events.

    You also need to prevent the browser’s default behavior, which is to simply load the dropped object in the browser window.

    dropzone.addEventListener("dragover", function(event) {
      event.preventDefault();
    }, true);
    dropzone.addEventListener("drop", function(event) {
      event.preventDefault();
      // Ready to do something with the dropped object
    }, true);

    You may also want to use the dragenter and dragleave events to be notified when a drag session starts or stops.

    Your element is now ready to receive files with the drop event.

    Manipulating the Files

    On the drop event, you can access the files with the files property of the DataTransfer object:

    dropzone.addEventListener("drop", function(event) {
      event.preventDefault();
      // Ready to do something with the dropped object
      var allTheFiles = event.dataTransfer.files;
      alert("You've just dropped " + allTheFiles.length + " files");
    }, true);

    Once you’ve accessed the files, the File API lets you do much more, like parsing files as a binary array, or displaying a preview of an image by reading the file as a DataURL.

    Of course, you can still drag and drop data other than files (e.g. text, URLs, remote images …) using the drag and drop API.

  4. multiple file input in Firefox 3.6

    Firefox 3.6 supports multiple file input. This new capability allows you to get several files as input at once, using standard technologies. This is a big improvement, since you used to be constrained to one file at a time, or needed to use a third party (proprietary) application. This will be particularly useful, for example, for photo uploads.

    The input tag

    To let your user select a local file, use the input tag on your Web page. This will show the file picker to the user:

    <input type="file"/>

    In Firefox 3.6, the input tag has been expanded to support multiple files:

    <input type="file" multiple=""/>

    The user will still see the same file picker, but will be able to select more than one file.

    The form tag

    You can still use the classic form mechanism:

    <form method="post" action="upload.php" enctype="multipart/form-data">
      <input name='uploads[]' type="file" multiple=""/>
      <input type="submit" value="Send">
    </form>

    If the server side code is in PHP, don’t forget to make sure that the value of the name attribute has brackets. The brackets are not from the HTML specification, but are required to manipulate the result of the request as an array (see PHP documentation).

    Here’s an example, which goes through the file list and prints each file name:

    foreach ($_FILES['uploads']['name'] as $filename) {
        echo '<li>' . $filename . '</li>';
    }

    Using File API

    Firefox 3.6 also supports FileAPI. This allows you to do extra processing on the client slide before sending the files to the server. You can access the selected files with the files property of the input DOM element and then manipulate the files using the FileAPI.

    For example, here’s how to get the name of each file selected by the user. This is done on the client side, unlike the previous PHP example.

      var input = document.querySelector("input[type='file']");
      // You've selected input.files.length files
      for (var i = 0; i < input.files.length; i++) {
        // input.files[i] is a file object
        var li = document.createElement("li");
        li.innerHTML = input.files[i].name;
        ul.appendChild(li);
      }

    Demo

    See this mechanism in action in our multiple file input demo. You’ll need Firefox 3.6 (beta).

    Documentation

    To learn more about multiple file input, check out the documentation on MDC.

  5. Firefox 3.6 FileAPI demo: reading EXIF data from a local JPEG file

    Paul Rouget has put together a great demo of the new FileAPI we’re including in Firefox 3.6. It lets you drag a JPG from the desktop into the browser that includes EXIF data and it can extract the GPS coordinates in the image and then load the location of where the photo was taken, entirely from JavaScript.

    If you have the Firefox 3.6 beta, you can view the demo or you can just watch the video below.

  6. W3C FileAPI in Firefox 3.6

    Often, web applications will prompt the user to select a file, typically to upload to a server. Unless the web application makes use of a plugin, file selection occurs through an HTML input element, of the sort <input type="file"/>. Firefox 3.6 now supports much of the W3C File API, which specifies the ability to asynchronously read the selected file into memory, and perform operations on the file data within the web application (for example, to display a thumbnail preview of an image, before it is uploaded, or to look for ID3 tags within an MP3 file, or to look for EXIF data in JPEG files, all on the client side). This is a new API, and replaces the file API that was introduced in Firefox 3.

    It is important to note that even before the advent of the W3C File API draft (which only became a Working Draft in November 2009), Firefox 3 and later provide the ability to read files into memory synchronously but that capability should be considered deprecated in favor of the new implementation in Firefox 3.6 of the asynchronous File API. The deprecated API allowed you synchronously access a file:

    // After obtaining a handle to a file
    // access the file data
    var dataURL = file.getAsDataURL();
    img.src = dataURL;

    While Firefox 3.6 will continue to support code usage of the sort above, it should be considered deprecated since it reads files synchronously on the main thread. For large files, this could result in blocking on the result of the read, which isn’t desirable. Moreover, the file object itself provides a method to read from it, rather than having a separate reader object. These considerations informed the technical direction of the new File API in Firefox 3.6 (and the direction of the specification). The rest of this article is about the newly introduced File API.

    Accessing file selections

    Firefox 3.6 supports multiple file selections on an input element, and returns all the files selected using the FileList interface. Previous versions of Firefox only supported one selection of a file using the input element. Additionally, the FileList interface is also exposed to the HTML5 Drag and Drop API as a property of the DataTransfer interface. Users can drag and drop multiple files to a drop target within a web page as well.

    The following HTML spawns the standard file picker, with which you can select multiple files:

    <input id="inputFiles" type="file" multiple="" />

    Note that if you don’t use the multiple attribute, you only enable single file selection.

    You can work with all the selected files obtained either through the file picker (using the input element) or through the DataTransfer object by iterating through the FileList:

    var files = document.getElementById("inputFiles").files;
     
    // or, for a drag event e:
    // var dt = e.dataTransfer; var files = dt.files
     
    for (var i = 0; i < files.length; i++) {
      var file = files[i];
      handleFile(file);
     
    }

    Properties of files

    Once you obtain a reference to an individually selected file from a FileList, you get a File object, which has name, type, and size properties. Continuing with the code snippet above:

    function handleFile(file) {
        // RegExp for JPEG mime type
        var imageType = /image\/jpeg/;
     
        // Check if match
        if (!file.type.match(imageType)) {
            return false;
        }
       // Check if the picture exceeds set limit
       if(file.size > maxSize) {
          alert("Choose a smaller photo!");
          return false;
       }
      // Add file name to page
      var picData = document.createTextNode(file.name);
      dataGrid.appendChild(picData);
      return true;
    }

    The size attribute is the file’s size, in bytes. The name attribute is the file’s name, without path information. The type attribute is an ASCII-encoded string in lower case representing the media type of the file, expressed as an RFC2046 MIME type. The type attribute in particular is useful in sniffing file type, as in the example above, where the script determines if the file in question is a JPEG file. If Firefox 3.6 cannot determine the file’s type, it will return the empty string.

    Reading Files

    Firefox 3.6 and beyond support the FileReader object to read file data asynchronously into memory, using event callbacks to mark progress. The object is instantiated in the standard way:

    var binaryReader = new FileReader();

    Event handler attributes are used to work with the result of the file read operation. For very large files, it is possible to watch for progress events as the file is being read into memory (using the onprogress event handler attribute to set the event handler function). This is useful in scenarios where the drives in question may not be local to the hardware, or if the file in question is particularly big.

    The FileReader object supports three methods to read files into memory. Each allows programmatic access to the files data in a different format, though in practice only one read method should be called on a given FileReader object:

    • filereader.readAsBinaryString(file); will asynchronously return a binary string with each byte represented by an integer in the range [0..255]. This is useful for binary manipulations of a file’s data, for example to look for ID3 tags in an MP3 file, or to look for EXIF data in a JPEG image.
    • filereader.readAsText(file, encoding); will asynchronously return a string in the format solicited by the encoding parameter (for example encoding = "UTF-8"). This is useful for working with a text file, for example to parse an XML file.
    • filereader.readAsDataURL(file); will asynchronously return a Data URL. Firefox 3.6 allows large URLs, and so this feature is particularly useful when a URL could help display media content in a web page, for example for image data, video data, or audio data.

    An example helps tie this all together:

    if (files.length > 0) {
        if (!handleFile(files[0])) {
            invalid.style.visibility="visible";
            invalid.msg = "Select a JPEG Image";
         }
    }
     
    var binaryReader = new FileReader();
    binaryReader.onload = function(){
       var exif = findEXIFInJPG(binaryReader.result);
       if (!exif) {
          // ...set up conditions for lack of data
       }
       else {
        // ...write out exif data
       }
     
    binaryReader.onprogress = updateProgress;
    binaryReader.onerror = errorHandler;
     
    binaryReader.readAsBinaryString(file);
     
    function updateProgress(evt){
       // use lengthComputable, loaded, and total on ProgressEvent
       if (evt.lengthComputable) {
              var loaded = (evt.loaded / evt.total);
              if (loaded < 1) {
                // update progress meter
                progMeter.style.width = (loaded * 200) + "px";
              }
       }
    }
     
    function errorHandler(evt) {
      if(evt.target.error.code == evt.target.error.NOT_FOUND_ERR) {
       alert("File Not Found!");
      }
    }

    In order to work with binary data, the use of the charCodeAt function exposed on strings will be particularly useful. For instance, an utility of the sort:

    function getByteAt(file, idx) {
        return file.charCodeAt(idx);
    }

    allows extraction of the Unicode value of the character at the given index.

    An example of similar code in action in Firefox 3.6, including use of the readAsDataURL method to render an image, as well as binary analysis of a JPEG for EXIF detection (using the readAsBinaryString method), can be found in Paul Rouget’s great demo of the File API..

    A word on the specification

    The existence of a W3C public working draft of the File API holds the promise of other browsers implementing it shortly. Firefox 3.6′s implementation is fairly complete, but is missing some of the technology mentioned in the specification. Notably, the urn feature on the File object isn’t yet implemented, and neither is the ability to extract byte-ranges of files using the slice method. A synchronous way to read files isn’t yet implemented as part of Worker Threads. These features will come in future versions of Firefox.

    References

  7. css backgrounds in Firefox 3.6

    Firefox 3.6 allows you to do more with CSS backgrounds: you can use gradients, set a background size, and specify multiple backgrounds.

    Custom Background Size

    In Firefox 3.6, you can specify the size of a background image to scale it as a percentage of the element’s size, or to a specific length, using -moz-background-size.

    -moz-background-size:  <bg-size>[, <bg-size>]*

    Percentages. In this example, you can see the effect of setting a size using percentages. On the left, size is set to auto, which maintains the original size of the background image. In the center, size is set to 100%, which scales the background image to 100% of the area (horizontally), even if the original image was smaller than the background positioning area. On the right, size is set to 10%, which scales the image to 10% of the area. The background image is repeated by default.

    css_bgsize_autoto10_fxlogo

     .bg_example_left {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png);
      -moz-background-size: auto;
    }
     .bg_example_center {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png);
      -moz-background-size: 100%;
    }
     .bg_example_right {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png);
      -moz-background-size: 10%;
    }

    Here’s the same example (auto – 100% – 10%) using a different background image. In this case, the original is larger than the background area. As a result, specifying “auto” shows only a portion of the original, and you need to set a size of 100% to make the full image visible.

    css_bgsize_autoto10_flowers

    Horizontal and Vertical Scaling. It it possible to define a size for both horizontal and vertical scaling. Specifying only one size sets horizontal scaling (as in the examples above) and vertical defaults to “auto”. If a second size is specified, it is used for vertical scaling, as in the example below. On the left you can see an image with horizontal scaling of 100% and vertical defaulting to “auto”. On the right, horizontal is set to 100% and vertical is 30%, changing the original appearance of the image because of the change in proportions.

    css_bg_size_vert

      -moz-background-size: 100%;
      -moz-background-size: 100% 30%;

    Custom Size Demo. Try our interactive demo: select the size of a background on the fly. You’ll need the latest beta of Firefox 3.6.

    Multiple Backgrounds

    Firefox 3.6 also enables you to stack multiple backgrounds. This allows you to create cool effects by stacking a gradient on top of an image for example.

    Defining. To define multiple backgrounds, simply list them as follows, using the background CSS property:

    .foo {
      background: background1, background2, ..., backgroundN;
    }

    The order in which you list the backgrounds matters: the first in the list will appear as the top layer, the last one as the bottom layer.

    Setting Properties. For multiple backgrounds, you can set the same properties you would for a single background, such as background-position or background-repeat. Define each background’s behavior by specifying a value for each property. The values need to be listed in the order in which you initially listed the backgrounds.

    So if you defined:

      background: background1, background2, background3;

    List the values in the same order for each property:

      background-position: background1_position, background2_position, background3_position;
      background-repeat: background1_repeat, background2_repeat, background3_repeat;

    Example. Here’s how to stack three different backgrounds: the Firefox logo, a linear gradient, and an image with flowers. If you’re running Firefox 3.6 beta, you can turn on and off any or all of the three backgrounds in our interactive demo.

    css_multibg

     .multi_bg_example {
      background: url(http://demos.hacks.mozilla.org/openweb/resources/images/logos/firefox-48.png), -moz-linear-gradient(left, rgba(255, 255, 255, 0),  rgba(255, 255, 255, 1)), url(http://demos.hacks.mozilla.org/openweb/resources/images/patterns/flowers-pattern.jpg);
      background-repeat: no-repeat, no-repeat, repeat;
      background-position: bottom right, left, right;
    }
  8. pointer-events for HTML in Firefox 3.6

    The pointer-events CSS property has long been available as part of SVG as a way to control if a mouse event should be sent to the element directly underneath the mouse or passed through to an element underneath it. In Firefox 3.6 we’ve extended the property to allow it to apply to normal HTML content as well.

    For SVG you can set the pointer-events property to one of several values, but for HTML you can only set it to one of two values: auto or none.

    .foo {
      pointer-events: none;
    }

    When pointer-events is set to none, pointer events are passed through the target element and are instead sent to the element that is underneath it.

    .foo {
      pointer-events: auto;
    }

    When pointer-events is set to auto, pointer events are handled normally. That is, the element blocks the events from being passed down to a lower element.

    Here’s a real world example from Paul Rouget. You will need a Firefox 3.6 beta to see it in action.

    Click the pointer-events: none checkbox under the image to see it change.

    He’s replicated the tag list that’s on the front page of twitter.com. (Note: you have to not be logged in to see the tag list.) If you go and look at it on twitter you’ll notice that it fades off on the right hand side. This is done with a transparent, faded image that sits on top of the underlying box. The tags underneath are clickable links but the image blocks events from being sent to the ones underneath the fade.

    What Paul has done is show how you can use the pointer-events property to allow you to click on the underlying links even with a fade on top of it.

  9. building beautiful buttons with css gradients

    A special thanks to Ryan Doherty for building this demo and making it easy for me to turn it into a tutorial.

    In this demo we’ll walk through a simple use case for the new gradient capabilities coming in Firefox 3.6 (see related article). We’ll build a nice-looking embossed and beveled button using gradients and existing CSS properties. The button in question was developed for the next version of our Personas site.

    Using a CSS-based method to generate buttons is a huge upgrade for web site developers. It means you don’t have to regenerate images every time you change text, pages will load much faster because you don’t have to download separate images and it allows text to be easily localized. In this case it also makes the page better from an accessibility standpoint – the text contained in the <a href> can add context.

    You can see the final version of this demo, or follow along with the steps outlined here.

    Creating the Button

    A button is just a rectangular space with a link in it. We can create that with a very simple chunk of HTML:

      <a class="linear" href="http://getpersonas.com">
        <span>Get Personas for Firefox</span>
        <span class="info">It's free and installs in seconds</span>
      </a>

    This creates a paragraph element and sets a fixed width. The internal “button” is actually a simple <a> link that contains text.

    Once we have the width set on the button we need to force the <a> to act like a block element so that the text inside will flow as part of a single element instead of showing up as two distinct parts:

    display: block;

    We want to choose some nicer fonts and a nicer style:

    font-family: Helvetica, Arial, sans-serif;
    font-weight: bold;
    font-size: 138.5%;
     
    text-align: center;
    text-decoration: none;

    And add some padding around the text and set rounded corners:

    padding: 10px;
    -moz-border-radius: 10px;

    We set a border around the button and set a background color as a fallback for other browsers. (Except, of course, for IE. See the note below.)

    border: 1px solid #659635;
    background: #99ca28;

    We also want to set the color of the text and add a nice drop shadow to make the text look embossed onto the button:

    text-shadow: -1px -1px 2px #777777;
    color: #ffffff;

    Once we have that we can use the -moz-linear-gradient CSS property to define the gradient so that it has a nice bevel look at the top:

    background: -moz-linear-gradient(top, #CFE782 0%,
                                          #9BCB2A 2%,
                                          #5DA331 97%,
                                          #659635 100%);

    The syntax here is pretty simple. The “top” means that it starts at the top of the area and heads down to the bottom of the button. The rest of the syntax defines what are called “color stops.” These allow you define gradient transitions that actually transition across more than two colors. This is used in this case because the bevel effect requires a non-linear transition from one color to the next.

    In the syntax above, it defines a starting color (0%), an bevel effect (2%), most of the transition (97%) and the border color to finish (100%.) This creates the effect where it’s very light at the top as if there was a light source moving to a darker color near the bottom.

    IE Note:

    A pithy note about our good friend, Internet Explorer. While older versions of Firefox and Safari both handle the background: -moz-linear-gradient gracefully by not affecting background rendering when they run into a property they don’t know how to handle, IE just shows a white background. One possible work around for this is to include a later background: property for IE in a separate style sheet that’s loaded once this style sheet is loaded. There are probably other ways of handling this, but it’s worth noting that this is an issue.

  10. css gradients in Firefox 3.6

    Firefox 3.6 includes many CSS improvements. In this post we’re going to show you how to use CSS gradients.

    If you are running the latest beta of Firefox 3.6, you should check out our interactive demo and take a look at the corresponding code. Use the radio buttons to switch different style options on or off.

    Backgrounds with CSS Gradients

    Using CSS gradients in a background allows you to display smooth transitions between two or more specified colors without having to use images. This in turn reduces download time and bandwidth use, looks better while zooming, and lets you create a more flexible layout.

    Firefox 3.6 supports two kinds of CSS gradients: linear (-moz-linear-gradient) and radial (-moz-radial-gradient).

    Linear Gradients

    To create a linear gradient, you’ll need to set a starting point and a direction (or angle) for the gradient and to define the color stops.

     -moz-linear-gradient( [<point> || <angle>,]? <stop>, <stop> [, <stop>]* )

    Starting Point. The starting point works just like background position. You can set the horizontal and the vertical positions as a percentage, in pixels, or using left/center/right for horizontal, and top/center/bottom for vertical. Positions start from the top left corner. If you don’t specify the horizontal or the vertical position, it will default to center.

    For example, here’s a linear gradient that starts at the center (horizontal) and top (vertical), and goes from blue to white:

    basic_linear_bluetop

      .linear_gradient_square {
        width: 100px;
        height: 100px;
        border: 1px solid #333;
        background: -moz-linear-gradient(top, blue, white);
      }

    One that starts left (horizontal) and center (vertical):

    basic_linear_blueleft

        background: -moz-linear-gradient(left, blue, white);

    And a gradient starting left (horizontal) and top (vertical):

    basic_linear_bluetopleft

        background: -moz-linear-gradient(left top, blue, white);

    Angle. As you can see above, if you don’t specify an angle, it is defined automatically based on the start position. If you would like more control over the direction of the gradient, you can set the angle as well.

    For example, the following gradients have the same starting point of left center, but the one on the right hand-side also has an angle of 20 degrees.

    linear_gradient_angle

        background: -moz-linear-gradient(left 20deg, black, white);

    When specifying the angle, remember that is it the angle between a horizontal line and the gradient line, going counter-clockwise. So using 0deg will generate a left to right horizontal gradient, while 90deg will create a vertical gradient from the bottom to the top.

    linear_redangles

        background: -moz-linear-gradient(<angle>, red, white);

    Color Stops. In addition to start position and angle, you should specify color stops. Color stops are points along the gradient line that will have the specified color at the specified location (set as a percentage or length). The number of color stops is unlimited. If you use a percentage for the location, 0% represents the starting point, and 100% is the ending point, but values above and below those can be used to achieve the desired effect.

    Here’s a simple example with three color stops. Because no point is specified for the first and last colors, they will default to 0% and 100%.

    linear_colorstops

        background: -moz-linear-gradient(top, blue, white 80%, orange);

    Colors will be evenly spaced if no position is specified.

    linear_rainbow

        background: -moz-linear-gradient(left, red, orange, yellow, green, blue);

    Transparency. Gradients also support transparency. This can be useful, for example, when stacking multiple backgrounds. Here’s a combination of two backgrounds: one image and one linear gradient from white to transparent white.

    linear_multibg_transparent

    .multibackground_transparent {
        background: -moz-linear-gradient(right, rgba(255,255,255,0), rgba(255,255,255,1)), url(http://demos.hacks.mozilla.org/openweb/resources/images/patterns/flowers-pattern.jpg);
    }

    Radial Gradients

    The syntax for radial gradients is very similar to that of linear gradients:

     -moz-radial-gradient([<bg-position> || <angle>,]? [<shape> || <size>,]? <color-stop>, <color-stop>[, <color-stop>]*);

    In addition to the start position, the direction, and the colors, which you have already seen in linear gradients, radial gradients allow you to specify the gradient’s shape (circle or ellipse) and size (closest-side, closest-corner, farthest-side, farthest-corner, contain or cover).

    Color stops. Just like with linear gradients, you should define color stops along the gradient line. The following circles have the same color stops, but the gradient on the left defaults to evenly spaced colors, while the one on the right has a specific position for each color.

    radial_gradient_stop

     background: -moz-radial-gradient(red, yellow, #1E90FF);
     background: -moz-radial-gradient(red 5%, yellow 25%, #1E90FF 50%);

    Shape. Here you can see the difference between the two possible shapes, a circle (on the left) and an ellipse (on the right), both with a bottom left starting point:

    radial_circle_ellipse

     .radial_gradient_circle {
        background: -moz-radial-gradient(bottom left, circle, red, yellow, #1E90FF);
    }
     .radial_gradient_ellipse {
        background: -moz-radial-gradient(bottom left, ellipse, red, yellow, #1E90FF);
    }

    Size. The different options for size (closest-side, closest-corner, farthest-side, farthest-corner, contain or cover) refer to the point used to define the size of the circle or ellipse.

    Example: closest-side vs. farthest corner for an ellipse.
    The following two ellipses have different sizes. The one on the left is set by the distance from the start point (center) to the closest-side, while the one on the right is determined by the distance from the start point to the farthest corner.

    radial_ellipse_size

      background: -moz-radial-gradient(ellipse closest-side, red, yellow 10%, #1E90FF 50%, white);
      background: -moz-radial-gradient(ellipse farthest-corner, red, yellow 10%, #1E90FF 50%, white);

    Example: closest-side vs. farthest-side for a circle.
    The size of the circle on the left is determined by the distance between the start point (the center) and the closest side, while the one on the right is the distance between the start point and the farthest side.

    radial_circle_size

     background: -moz-radial-gradient(circle closest-side, red, yellow 10%, #1E90FF 50%, white);
     background: -moz-radial-gradient(circle farthest-side, red, yellow 10%, #1E90FF 50%, white);

    Example: contained circle.
    Here you can see the default circle on the left, and the version of the same gradient but contained on the right.

    radial_contain

     background: -moz-radial-gradient(red, yellow, #1E90FF);
     background: -moz-radial-gradient(contain, red, yellow, #1E90FF);

    Repeating Gradients

    If you would like to repeat a gradient, you should use -moz-repeating-linear-gradient and -moz-repeating-radial-gradient.

    In the examples below, four color stops are specified in each case, and are repeated indefinitely.

    repeating_gradients

     .repeating_radial_gradient_example {
        background: -moz-repeating-radial-gradient(black, black 5px, white 5px, white 10px);
    }
     .repeating_linear_gradient_example {
         background: -moz-repeating-linear-gradient(top left -45deg, red, red 5px, white 5px, white 10px);
    }

    Demo

    Check out our interactive demo of linear and radial gradients for more examples.

    Note that the gradient syntax has changed between Firefox 3.6 beta 1 and beta 2, so if you used gradients with beta 1, you may need to update your code.