Mozilla

CSS Articles

Sort by:

View:

  1. Introducing @counter-style

    Introduction

    The characters that indicate items in a list are called counters — they can be bullets or numbers. They are defined using the list-style-type CSS property. CSS1 introduced a list of predefined styles to be used as counter markers. The initial list was then slightly extended with addition of more predefined counter styles in CSS2.1. Even with 14 predefined counter styles, it still failed to address use cases from around the world.

    Now, the CSS Counter Styles Level 3 specification, which reached Candidate Recommendation last week, adds new predefined counter styles to the existing list that should address most common counter use cases.

    In addition to the new predefined styles, the spec also offers an open-ended solution for the needs of worldwide typography by introducing the @counter-style at-rule — which lets us define custom counter styles or even extend existing ones — and the symbols() function. The latter is a shorthand for defining inline styles and is useful when the fine-grained control that @counter-style offers is not needed.

    This article provides a guide to using the new counter features of CSS Level 3.

    @counter-style

    A @counter-style at-rule is identified by a name and defined with a set of descriptors. It takes a numerical counter value and converts it into a string or image representation. A custom counter style definition looks like this:

    @counter-style blacknwhite {
      system: cyclic;
      negative: "(" ")";
      prefix: "/";
      symbols: ◆ ◇;
      suffix: "/ ";
      range: 2 4;
      speak-as: "bullets";
    }

    The different available descriptors have the following meanings:

    1. system – the system descriptor lets the author specify an algorithm to convert the numerical counter value to a basic string representation. For example, the cyclic system cycles repeatedly through the list of symbols provided to create counter representations.
    2. negative – the negative descriptor provides the ability to specify additional symbols, such as a negative sign, to be appended/prepended to a counter representation if the counter value is negative. If only one symbol is specified, it will be added in front of the marker representation. A second value, if specified (as in the example below), will be added after the marker.
      @counter-style neg {
        system: numeric;
        symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
        negative: "(" ")";
      }

      The above counter style definition will wrap negative markers in a pair of parentheses, instead of preceding them with the minus sign.

    3. prefix – specifies a symbol that will be prepended to the final counter representation.
    4. suffix – specifies a symbol that will be appended to the final counter representation.The default value of the suffix descriptor is a full stop followed by a space. If you need to replace the full stop “.” with a parenthesis, you can specify the suffix descriptor:
      @counter-style decimal-parenthesis {
        system: numeric;
        symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
        suffix: ") ";
      }
    5. rangerange lets the author define a range of values over which a counter style is applicable. If a counter value falls outside the specified range, then the specified or default fallback style is used to represent that particular counter value, for example:
      @counter-style range-example {
        system: cyclic;
        symbols: A B C D;
        range:  4 8;
       }

      The above rule will apply the style only for counter values starting from 4 to 8. The fallback style, decimal, will be used for the rest of the markers.

    6. pad – as the name suggests, the pad descriptor lets the author specify a padding length when the counter representations need to be of a minimum length. For example, if you want the counters to start at 01 and go through 02, 03, 04, etc., then the following pad descriptor should be used:
      @counter-style decimal-new {
        system: numeric;
        symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
        pad: 2 "0";
      }

      (For a better way to achieve the same result, but without specifying the counter symbols, see the section below about extending existing systems.)

    7. fallback – the fallback specifies a style to fall back to if the specified system is unable to construct a counter representation or if a particular counter value falls outside the specified range.
    8. symbols and additive-symbols – specify the symbols that will be used to construct the counter representation. The symbols descriptor is used in most cases other than when the system specified is ‘additive.’ While symbols specifies individual symbols, the additive-symbols descriptor is composed of what are known as additive tuples – , which each consist of a symbol and a non-negative weight.Symbols specified can be strings, images in the form url(image-name) or identifiers. The below example uses images as symbols.
      @counter-style winners-list {
        system: fixed;
        symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg);
        suffix: " ";
      }
    9. speak-as – specifies how a counter value should be spoken by speech synthesizers such as screen readers. For example, the author can specify a marker symbol to be read out as a word, a number, or as an audio cue for a bullet point. The example below reads out the counter values as numbers.
      @counter-style circled-digits {
        system: fixed;
        symbols: ➀ ➁ ➂;
        suffix: ' ';
        speak-as: numbers;
      }

      You can then use a named style with list-style-type or with the counters() function as you normally would use a predefined counter style.

      ul {
        list-style-type: circled-digits;
      }

      On a supported browser, the counter style above will render lists with markers like this:

      @counter-style demo image

    The system descriptor

    The system descriptor takes one of the predefined algorithms, which describe how to convert a numerical counter value to its representation. The system descriptor can have values that are cyclic, numeric, alphabetic, symbolic, additive, fixed and extends.

    If the system specified is cyclic, it will cycle through the list of symbols provided. Once the end of the list is reached, it will loop back to the beginning and start over. The fixed system is similar, but once the list of symbols is exhausted, it will resort to the fallback style to represent the rest of the markers. The symbolic, numeric and alphabetic systems are similar to the above two, but with their own subtle differences.

    The additive system requires that the additive-symbols descriptor be specified instead of the symbols descriptor. additive-symbols takes a list of additive tuples. Each additive tuple consists of a symbol and its numerical weight. The additive system is used to represent “sign-value” numbering systems such as the Roman numerals.

    We can rewrite the Roman numerals as a @counter-style rule using the additive system like this:

    @counter-style custom-roman {
      system: additive;
      range: 1 100;
      additive-symbols: 100 C, 90 XC, 50 L, 40 XL, 10 X, 9 IX, 5 V, 4 IV, 1 I;
    }

    Extending existing or custom counter styles

    The extends system lets authors create custom counter styles based on existing ones. Authors can use the algorithm of another counter style, but alter its other aspects. If a @counter-style rule using the extends system has any unspecified descriptors, their values will be taken from the extended counter style specified.

    For example, if you want to define a new style which is similar to decimal, but has a string “Chapter ” in front of all the marker values, then rather than creating an entirely new style you can use the extends system to extend the  decimal style like this:

    @counter-style chapters {
      system: extends decimal;
      prefix: 'Chapter ';
    }

    Or, if you need the decimal style to start numbers from 01, 02, 03.. instead of 1, 2, 3.., you can simply specify the pad descriptor:

    @counter-style decimal-new {
      system: extends decimal;
      pad: 2 "0";
    }

    A counter style using the extends system should not specify the symbols and additive-symbols descriptors.

    See the reference page on MDN for details and usage examples of all system values.

    A shorthand – The symbols() function

    While a @counter-style at-rule lets you tailor a custom counter style, often such elaborate control is not needed. That is where the symbols() function comes in. symbols() lets you define inline counter styles as function properties. Since the counter styles defined in this way are nameless (anonymous), they can not be reused elsewhere in the stylesheet.

    An example anonymous counter style looks like this:

    ul {
        list-style-type: symbols(fixed url(one.svg) url(two.svg));
    }

    Even more predefined counter styles

    CSS Lists 3 vastly extends the number of predefined styles available. Along with the predefined styles such as decimal, disc, circle and square that existed before, additional styles such as hebrew, thai, gujarati, disclosure-open/close, etc. are also added to the predefined list. The full list of predefined styles enabled by the spec can be seen here.

    Browser support

    Support for @counter-style and the symbols() function along with the new predefined styles landed in Firefox 33. Google Chrome hasn’t implemented @counter-styles or the symbols() function yet, but most of the new numeric and alphabetic predefined styles have been implemented. There is no support in IE so far. Support has already landed in the latest releases of Firefox for Android and in the upcoming Firefox OS 2.1, which has support for @counter-style. Support for symbols() will land in Firefox OS 2.2.

    Examples

    Check out this demo page and see if @counter-style is supported in your favorite browsers.

  2. Exploring object-fit

    On web documents, a common problem concerns the display of different sized images (or videos) in the same place. Perhaps you are writing a dynamic gallery app that accepts user submissions. You can’t guarantee that everyone will upload images of exactly the same aspect ratio, so what do you do?

    Letting the aspect ratio distort to fit the containing replaced element nearly always looks horrible. And doing some kind of dynamic cropping or resizing on the fly each time might be more work than you have the capability to implement. (For instance, maybe you’re working on a CMS and don’t have permission to edit anything except the page content.)

    The CSS Image Values and Replaced Content module provides properties called object-fit — which solves such problems, and object-position — which sets the horizontal and vertical position of the content inside the element.

    These elements have decent support across modern browsers (with the exception of IE). In this article we’ll look at a few examples of how they can be used.

    Note: object-fit works with SVG content, but the same effect can also be achieved by setting the preserveAspectRatio="" attribute in the SVG itself.

    How do object-fit and object-position work?

    You can successfully apply object-fit to any replaced element, for example:

    img {
      height: 100px;
      width: 100px;
      object-fit: contain;
    }

    The five possible values of object-fit are as follows:

    1. contain: The content (e.g. the image) will be resized so that it is fully displayed with intrinsic aspect ratio preserved, but still fits inside the dimensions set for the element.
    2. fill: The content will expand to exactly fill the dimensions set for the element, even if this does break its aspect ratio.
    3. cover: Preserves the aspect ratio of the content, but alters the width and height so that the content completely covers the element. The smaller of the two is made to fit the element exactly, and the larger overflows the element and is cropped.
    4. none: Completely ignores any height or weight set on the element, and just uses the replaced element content’s intrinsic dimensions.
    5. scale-down: The content is sized as if none or contain were specified, whichever would result in a smaller replaced element size.

    object-position works in exactly the same way as background-position does for background images; for example:

    img {
      height: 100px;
      width: 100px;
      object-fit: contain;
      object-position: top 70px;
    }

    Percentages work, but they’re actually resolved against the excess available space — the difference between the element’s width & the replaced content’s final rendered width. So object-position: 50% 50% (the default value) will always exactly center the replaced element. Furthermore, object-position: 0% 0% always means align with top-left corner, object-position: 100% 100% *always* means align with bottom-right corner, etc.

    The keywords top, center, right, etc. are really just handy aliases for 0%, 50%, 100%, etc.

    Note: You can see some object position examples in our basic example page.

    The effects of the different object-fit values

    The following code examples show the effects of the different object-fit values.

    Letterboxing images with object-fit: contain

    Sometimes referred to as letter-boxing, there are times when you will want to preserve the aspect ratio of the images on a page, but get them to fit inside the same area. For example, you might have a content management system that allows you to upload products on an e-commerce site or images for an image gallery, with lots of different content authors. They may upload images in roughly the right size, but the dimensions are not always exact, and you want to fit each image into the same amount of space.

    Having images with the aspect ratio shifted usually looks horrible, so you can letterbox them instead with object-fit: contain (object-fit: contain example):

    img {
      width: 480px;
      height: 320px;
      background: black;
    }
     
    .contain {
    	object-fit: contain;
    }

    Cropping images with object-fit:cover

    A different solution is to maintain aspect ratio, but crop each image to the same size so it completely envelops the <img> element, with any overflow being hidden. This can be done easily with object-fit:cover (object-fit: cover example):

    .cover {
      object-fit: cover;
    }

    Overriding a video’s aspect ratio with object-fit: fill

    Going in the opposite direction, it is also possible to take a video and force it to change aspect ratio. Maybe some of your content editor’s videos have a broken aspect ratio, and you want to fix them all on the fly, in one easy fell swoop?

    Take the following video image:

    a video with a broken aspect ratioIf we embedded it into a page with this:

    <video controls="controls" src="windowsill.webm"
        width="426" height="240">
      …
    </video>

    It would look terrible: the video would appear letter-boxed, since the <video> element always tries to maintain the source file’s intrinsic aspect ratio. We could fix this by applying object-fit: fill (object-fit: fill example):

    .fill {
      object-fit: fill;
    }

    This overrides the video’s intrinsic aspect ratio, forcing it to completely fill the <video> element so it displays correctly.

    Interesting transition effects

    Combining object-fit and object-position with CSS transitions can lead to some pretty interesting effects for image or video galleries. For example:

    .none {
      width: 200px;
      height: 200px;
     
      overflow: hidden;
      object-fit: none;
      object-position: 25% 50%;
      transition: 1s width, 1s height;
    }
     
    .none:hover, .none:focus {
    	height: 350px;
    	width: 350px;
    }

    Only a small part of the image is shown, and the element grows to reveal more of the image when it is focused/hovered (object-fit: none example).

    This is because by setting object-fit: none on the <img>, we cause the content to completely ignore any width and height set earlier, and spill out of the sides of the element. We then use overflow: hidden to crop anything that spills out. A transition is then used to smoothly increase the size of the <img> element when it’s hovered/focused, which reveals more of the image.

    Gallery example

    To show a slightly more applied usage of object-fit, we have created a gallery example:

    an image gallery showing sixteen pictures in a four by four grid

    an image gallery showing one large image

    The 16 images are loaded via XHR, and inserted into the images as ObjectURLs.

    for(i = 1; i <= thumbs.length ; i++) {
      var requestObj = 'images/pic' + i + '.jpg';
      retrieveImage(requestObj,i-1);
    }
     
    function retrieveImage(requestObj,imageNo) {
      var request = new XMLHttpRequest();
      request.open('GET', requestObj, true);
      request.responseType = 'blob';
     
      request.onload = function() {
        var objectURL = URL.createObjectURL(request.response);
        thumbs[imageNo].setAttribute('src',objectURL);
        thumbs[imageNo].onclick = function() {
          ...
        }
      }
     
      request.send();
    }

    Each image in turn is given an onclick handler so that when clicked the images appear full size, filling the screen (the main image, initially set to display: none; in the CSS is given a class of blowup, which makes it display and fill the whole screen; the main image’s src is then set to the same object URL as the thumb that was clicked).

    thumbs[imageNo].onclick = function() {
      mainImg.setAttribute('src',objectURL);
      mainImg.className = 'blowup';
      for(i = 0; i < thumbs.length; i++) {
        thumbs[i].className = 'thumb darken';
      }
    }

    Clicking a full size image makes it disappear again.

    mainImg.onclick = function() {
      mainImg.className = 'main';
      for(i = 0; i < thumbs.length; i++) {
        thumbs[i].className = 'thumb';
      }
    }

    All the sizing is done with percentages so that the grid remains in proportion whatever the screen size.

    body > div {
      height: 25%;
    }
     
    .thumb {
      float: left;
      width: 25%;
      height: 100%;
      object-fit: cover;
    }

    Note: the thumbnails have all been given tabindex="0" to make them focusable by tabbing (you can make anything appear in the page’s tab order by setting on tabindex="0" on it), and the onclick handler that makes the full size images appear has been doubled up with an onfocus handler to provide basic keyboard accessibility:

    thumbs[imageNo].onfocus = function() {
      mainImg.setAttribute('src',objectURL);
      mainImg.className = 'blowup';
      for(i = 0; i < thumbs.length; i++) {
        thumbs[i].className = 'thumb darken';
      }
    }

    The clever parts come with the usage of object-fit:

    1. The thumbnails: These have object-fit: cover set on them so that all image thumbs will appear at the same size, at the proper aspect ratio, but cropped different amounts. This looks pretty decent, and creates a nice effect when you resize the window.
    2. The main image: This has object-fit: contain and object-position: center set on it, so that it will appear in full, at the correct aspect ratio and as big as it can be.
  3. Pseudo elements, promise inspection, raw headers, and much more – Firefox Developer Edition 36

    Firefox 36 was just uplifted to the Developer Edition channel, so let’s take a look at the most important Developer Tools changes in this release. We will also cover some changes from Firefox 35 since it was released shortly before the initial Developer Edition announcement. There is a lot to talk about, so let’s get right to it.

    Inspector

    You can now inspect ::before and ::after pseudo elements.  They behave like other elements in the markup tree and inspector sidebars. (35, development notes)

    before-after-inspection

    There is a new “Show DOM Properties” context menu item in the markup tree. (35, development notes, documentation about this feature on MDN)

    show-dom-properties

    The box model highlighter now works on remote targets, so there is a full-featured highlighter even when working with pages on Firefox for Android or apps on Firefox OS. (36, development notes, and technical documentation for building your own custom highlighter)

    Shadow DOM content is now visible in the markup tree; note that you will need to set dom.webcomponents.enabled to true to test this feature (36, development notes, and see bug 1053898 for more work in this space).

    We borrowed a useful feature from Firebug and are now allowing more paste options when right clicking a node in the markup tree.  (36, development notes, documentation about this feature on MDN)

    paste-options

    Some more changes to the Inspector included in Firefox 35 & 36:

    • Deleting a node now selects the previous sibling instead of the parent (36, development notes)
    • There is higher contrast for the currently hovered node in the markup view (36, development notes)
    • Hover over a CSS selector in the computed view to highlight all the nodes that match that selector on the page. (35, development notes)

    Debugger / Console

    DOM Promises are now inspectable. You can inspect the promises state and value at any moment. (36, development notes)

    promise-inspection

    The debugger now recognizes and works with eval’ed sources. (36, development notes)

    Eval’ed sources support the //# sourceURL=path.js syntax, which will make them appear as a normal file in the debugger and in stack traces reported by Error.prototype.stack. See this post: http://fitzgeraldnick.com/weblog/59/ for much more information. (36, development notes,  more development notes)

    Console statements now include the column number they originated from. (36, development notes)

    WebIDE

    You are now able to connect to Firefox for Android from the WebIDE.  See documentation for debugging firefox for android on MDN.  (36, development notes).

    We also made some changes to improve the user experience in the WebIDE:

    • Bring up developer tools by default when I select a runtime app / tab (35, development notes)
    • Re-select project on connect if last project is runtime app (35, development notes)
    • Auto-select and connect to last used runtime if available (35, development notes)
    • Font resizing (36, development notes)
    • You can now adding a hosted app project by entering the base URL (eg: “http://example.com”) instead of requiring the full path to the manifest.webapp file (35, development notes)

    Network Monitor

    We added a plain request/response headers view to make it easier to view and copy the raw headers on a request. (35, development notes)

    net-headers-raw

    Here is a list of all the bugs resolved for Firefox 35 and all the bugs resolved for Firefox 36.

    Do you have feedback, bug reports, feature requests, or questions? As always, you can comment here, add/vote for ideas on UserVoice or get in touch with the team at @FirefoxDevTools on Twitter.

  4. WebIDE, Storage inspector, jQuery events, iframe switcher + more – Firefox Developer Tools Episode 34

    A new set of Firefox Developer Tools features has just been uplifted to the Aurora channel. These features are available right now in Aurora, and will be in the Firefox 34 release in November. This release brings new tools (storage inspector, WebIDE), an updated profiler, and handy enhancements to the existing tools:

    WebIDE

    WebIDE, a new tool for in-browser app development, has been enabled by default in this release. WebIDE lets you create a new Firefox OS app (which is just a web app) from a template, or open up the code for an already created app. From there you can edit the app’s files. It’s one click to run the app in a simulator and one more to debug it with the developer tools. Open WebIDE from Firefox’s “Web Developer” menu. (docs)

    Storage inspector

    There’s a new panel that shows the data your page has stored in cookies, localStorage, sessionStorage, and IndexedDB, which was created mostly by Girish Shama. Enable the Storage panel by checking off Settings > “Default Developer Tools” > “Storage”. The panel is read-only right now, with editing ability planned for a future release. (docs) (development notes) (UserVoice request)

    storage inspector

    jQuery events

    The event listener popup in the Inspector now supports jQuery. This means the popup will display the function you attached with e.g. jQuery.on(), and not the jQuery wrapper function itself. See this post for more info and how to add support for your preferred framework. (development notes)

    JQuery events

    Iframe switcher

    Change the frame you’re debugging using the new frame selection menu. Selecting a frame will switch all of the tools to debug that iframe, including the Inspector, Console, and Debugger. Add the frame selection button by checking off Settings > “Available Toolbox Buttons” > “Select an iframe”. (docs) (development notes)(UserVoice request)

    iframe selection

    Updated profiler

    An updated JavaScript profiler appears in the new “Performance” tab (formerly the “Profiler” tab). New to the profiler are a frame rate timeline and categories for frames like “network” and “graphics”. (docs) (development notes)

    new profiler

    console.table()

    Add a call to console.table() anywhere in your JavaScript to log data to the console using a table-like display. Log any object, array, Map, or Set. Sort a column in the table by clicking on its header. (docs) (development notes)

    console.table

    Selector preview

    Hover over a CSS selector in the Inspector or Style Editor to highlight all the nodes that match that selector on the page. (development notes)

    selector previews

    Other mentions

    • Persistent split console – The split console (opened by pressing ESC) will now open with the tools if you had it open the last time the tools were closed. (development notes)
    • Web audio – AudioParam connections – the Web Audio Editor now displays connections from AudioNodes to AudioParams. (development notes)

    Special thanks to the 41 contributors that added all the features and fixes in this release.

    Comment here, shoot feedback to @FirefoxDevTools on Twitter, or propose changes on the Developer Tools feedback channel. If you’d like to help out, check out the guide to getting involved.

  5. Single Div Drawings with CSS

    Why A Single Div?

    In May of 2013 I attended CSSConf and saw Lea Verou speak about the humble border-radius. It was an eye-opening talk and I realized there was much about CSS behavior I did not fully understand. This reminded me of my time as a fine arts student where I was constantly pushed to become a master of my chosen medium. As a web designer, CSS is my medium and so I challenged myself to learn all I could about it and to explore and experiment with its limits.

    But why a single div?

    When I was learning to paint, my class did these color mixing exercises where we created the many colors of the spectrum from only the three primary colors: red, yellow, and blue. The purpose of the exercise is to learn the behavior of the medium and the constraints show us the power of combination. You can certainly buy green paint, but you can also create green from blue and yellow. Restricting your available options forces you to re-evaluate the tools you already have.

    I decided to start a CSS drawing project, every few days illustrating something new with only CSS. To further challenge and explore what CSS is capable of, I gave myself the constraint of using only a single div in the markup. Instead of buying green paint (or adding another div), I’d need to stretch and combine CSS properties to achieve my goals.

    The Toolkit

    With only a single div and browser-supported CSS properties, it may seem like the tools are too limited. I found it’s not always what you have to work with, but how you look at them.

    Pseudo elements

    With one div in the HTML, I actually have three elements to work with because of CSS pseudo classes. So with div, div:before, and div:after, we can get something like this:

    pseudo elements

      div { background: red; }
      div:before { background: yellow; }
      div:after { background: blue; }

    It helps to think about these three elements as things that can come in sequence and as three stackable layers. So in my mind, it would usually look more like this:

    pseudo elements as layers

    Shapes

    With CSS and one element, we are afforded three basic shape types. We can use width and height properties to create squares/rectangles, border-radius to create circles/ellipses, and border to create triangles/trapezoids.

    css shapes

    There are others we can create with CSS, but most things can be simplified to some combination of these shapes. And these are the easiest to create and manipulate.

    Multiples of the same shape

    With multiple box-shadows, we can create many versions of the same shape in varying size, color, and blur. Offsetting them on the x- and y-axes gives us almost endless multiples.

    multiple box-shadows

    div {
        box-shadow: 170px 0 10px yellow,
                    330px 0 0 -20px blue,
                    330px 5px 5px -20px black;
    }

    We can even give our box-shadows box-shadows. Pay attention to the order they are declared. Again, It’s helpful to think of them as layers.

    Gradients

    Gradients can be used to add shading and depth by implying a light source. This makes the simple, flat shapes feel more realistic. Combining multiple background-images allows us to use many, layered gradients to achieve more complex shading and even more shapes.

    gradients

    div {
        background-image: linear-gradient(to right, gray, white, gray, black);
    }
     
    div:after {
        background-image: radial-gradient(circle, yellow 50%, transparent 50%),
                          linear-gradient(to right, blue, red);
    }

    Visualizing

    The most difficult part is visualizing how to piece these parts into a whole recognizable drawing. As much as I focus on the technical aspects of the drawings, this part of the process is critical. To help with this, I’ll often look at a photograph of the subject and break it up visually into pieces. Everything is a shape and everything is a color. I simplify the overall picture into smaller shapes or blocks of color I know can (or suspect can) be achieved with CSS.

    Demos

    Let’s take a closer look at two drawings and break down some of the pieces that make up the larger pictures. First up is the green crayon.

    A crayon is made up of two primary shapes: the rectangular body and the triangular drawing tip.

    crayon shapes

    I had to guarantee the following things to capture a realistic image:

    • the different color of the paper wrapper
    • the printed graphics and words on the wrapper
    • the shading that shows the roundness of the crayon
    • the glossiness that shows roundness and a light source

    So first, I created the main body of the crayon with the div and a background color, top-to-bottom gradient, and box-shadow to show some dimension:

    crayon body

    (Note, I’m using a mixin of black(a) and white(a) here in place of rgba)

    div {
        background: #237449;
        background-image: linear-gradient(to bottom,
                                      transparent 62%,
                                      black(.3) 100%);
        box-shadow: 2px 2px 3px black(.3);
    }

    Then I added a left-to-right linear-gradient to create the wrapper. It has an alpha value of .6 so some of that previous gradient shows through.

    crayon wrapper

    div {
        background-image: linear-gradient(to right,
                                      transparent 12px,
                                      rgba(41,237,133,.6) 12px,
                                      rgba(41,237,133,.6) 235px,
                                      transparent 235px);
    }

    Next I used the same left-to-right gradient technique to create the printed stripes on the crayon.

    crayon printing

    div {
        background-image: linear-gradient(to right,
                                      transparent 25px,
                                      black(.6) 25px,
                                      black(.6) 30px,
                                      transparent 30px,
                                      transparent 35px,
                                      black(.6) 35px,
                                      black(.6) 40px,
                                      transparent 40px,
                                      transparent 210px,
                                      black(.6) 210px,
                                      black(.6) 215px,
                                      transparent 215px,
                                      transparent 220px,
                                      black(.6) 220px,
                                      black(.6) 225px,
                                      transparent 225px);
    }

    And for the printed ellipse, a radial-gradient works great!

    crayon printing

    div {
        background-image: radial-gradient(ellipse at top,
                                      black(.6) 50px,
                                      transparent 54px);
    }

    I have it broken up to demonstrate each piece, but keep in mind the background-image would actually look like this:

    div {
                          // ellipse printed on wrapper
        background-image: radial-gradient(ellipse at top,
                                      black(.6) 50px,
                                      transparent 54px),
                          // printed stripes
                          linear-gradient(to right,
                                      transparent 25px,
                                      black(.6) 25px,
                                      black(.6) 30px,
                                      transparent 30px,
                                      transparent 35px,
                                      black(.6) 35px,
                                      black(.6) 40px,
                                      transparent 40px,
                                      transparent 210px,
                                      black(.6) 210px,
                                      black(.6) 215px,
                                      transparent 215px,
                                      transparent 220px,
                                      black(.6) 220px,
                                      black(.6) 225px,
                                      transparent 225px),
                          // wrapper
                          linear-gradient(to right,
                                      transparent 12px,
                                      rgba(41,237,133,.6) 12px,
                                      rgba(41,237,133,.6) 235px,
                                      transparent 235px),
                          // crayon body shading
                          linear-gradient(to bottom,
                                      transparent 62%,
                                      black(.3) 100%)
    }

    So after completing the div, I moved on to the :before pseudo element to create the crayon’s triangular tip. Using solid and transparent borders, I made a triangle and positioned it next to the div I just drew.

    triangle crayon tip

    div:before {
        height: 10px;
        border-right: 48px solid #237449;
        border-bottom: 13px solid transparent;
        border-top: 13px solid transparent;
    }

    It looks a little flat next to the crayon’s body, but it will be fixed with the :after pseudo element. With this, I added a top-to-bottom linear-gradient to create a reflective gloss effect that spans the width of the crayon.

    crayon gloss

    div:after {
        background-image: linear-gradient(to bottom,
                                        white(0) 12px,
                                        white(.2) 17px,
                                        white(.2) 19px,
                                        white(0) 24px);
    }

    This adds even more dimension and realism and helps with that flat triangle. As a finishing touch, I added some text content to the :after and positioned it as another printed element on the crayon’s wrapper.

    crayon color label

    div:after {
        content: 'green';
        font-family: Arial, sans-serif;
        font-size: 12px;
        font-weight: bold;
        color: black(.3);
        text-align: right;
        padding-right: 47px;
        padding-top: 17px;
    }

    And that’s it!

    Let’s take a look at another one

    The crayon is a good example of using background-image and gradients to produce realistic results. Here’s an example that shows the power of multiple box-shadows: a single div camera.

    Here’s the body of the camera, created with background-image and border-image.

    camera body

    Here’s a gif illustrating the :before pseudo element (the black rectangle) and the many details created with its box-shadows.

    camera rectangle

    div:before {
        background: #333;
        box-shadow: 0 0 0 2px #eee,
                    -1px -1px 1px 3px #333,
                    -95px 6px 0 0 #ccc,
                    30px 3px 0 12px #ccc,
                    -18px 37px 0 46px #ccc,
     
                    -96px -6px 0 -6px #555,
                    -96px -9px 0 -6px #ddd,
     
                    -155px -10px 1px 3px #888,
                    -165px -10px 1px 3px #999,
                    -170px -10px 1px 3px #666,
                    -162px -8px 0 5px #555,
     
                    85px -4px 1px -3px #ccc,
                    79px -4px 1px -3px #888,
                    82px 1px 0 -4px #555;
    }

    Similarly, here’s the :after (the grey circle) and its several box-shadow details.

    camera circle

    div:after {
        background: linear-gradient(45deg, #ccc 40%, #ddd 100%);
        border-radius: 50%;
        box-shadow: 0 3px 2px #999,
                    1px -2px 0 white,
                    -1px -3px 2px #555,
                    0 0 0 15px #c2c2c2,
                    0 -2px 0 15px white,
                    -2px -5px 1px 17px #666,
                    0 10px 10px 15px black(.3),
     
                    -90px -51px 1px -43px #aaa,
                    -90px -50px 1px -40px #888,
                    -90px -51px 0 -34px #ccc,
                    -90px -50px 0 -30px #aaa,
                    -90px -48px 1px -28px black(.2),
     
                    -124px -73px 1px -48px #eee,
                    -125px -72px 0 -46px #666,
                    -85px -73px 1px -48px #eee,
                    -86px -72px 0 -46px #666,
                    42px -82px 1px -48px #eee,
                    41px -81px 0 -46px #777,
                    67px -73px 1px -48px #eee,
                    66px -72px 0 -46px #666,
     
                    -46px -86px 1px -45px #444,
                    -44px -87px 0 -38px #333,
                    -44px -86px 0 -37px #ccc,
                    -44px -85px 0 -34px #999,
     
                    14px -89px 1px -48px #eee,
                    12px -84px 1px -48px #999,
                    23px -85px 0 -47px #444,
                    23px -87px 0 -46px #888;
    }

    A little crazy, but as you can see, multiple box-shadows can add a lot of detail to a single div drawing.

    Biggest challenges

    Two of the biggest obstacles I came across were limitations around triangle shapes and the natural behavior of gradients.

    The trouble with triangles

    Because triangles are created using borders, it limits how much I can do with them. Adding gradients with border-image apply to all the borders, not just one side. Box-shadows apply to the shape of the box, not the triangle shape the border creates, so creating multiple triangle shapes can be difficult. Here’s an example of what that looks like:

    trouble with triangles

    div {
        border-left: 80px solid transparent;
        border-right: 80px solid transparent;
        border-bottom: 80px solid red;
    }
     
    div:before {
        border-left: 80px solid transparent;
        border-right: 80px solid transparent;
        border-bottom: 80px solid red;
        border-image: linear-gradient(to right, red, blue);
    }
     
    div:after {
        border-left: 80px solid transparent;
        border-right: 80px solid transparent;
        border-bottom: 80px solid red;
        box-shadow: 5px 5px 5px gray;
    }

    Layering gradients

    With gradients, their natural behavior is to fill the entire background. This can get a little tricky when layering multiple gradients on top of each other. It takes some extra time to think through transparency, z-index, and understanding what will and won’t be visible. By using this technique effectively, our drawings can have surprising detail.

    The Tardis is a good example of showing and hiding gradients to create a detailed picture. Here’s the drawing mid-process that shows some of the top-to-bottom gradients that span the entire width of the container.

    single div tardis in-process

    Using left-to-right and right-to-left gradients, I was able to cover parts of the gradient and leave some parts exposed.

    single div tardis in-process

    The resulting drawing appears to have many shapes making up the front facade of the Tardis, but it’s strategically layered linear-gradients. Sometimes you have to fake it.

    See them in action

    One awesome thing that popped up because of this project is a really cool and useful Chrome browser extension by Rafael Carício called CSS Gradient Inspector. It extends the developer tools to inspect and toggle on/off each element’s gradients as if they were layers. (It’s very helpful with everyday projects, too.)

    I’m super excited to see designers and developers experimenting and riffing on these drawings with animations and JavaScript functionality. Check out the site and play around with the CSS yourself at a.singlediv.com or on GitHub!

  6. Live Editing Sass and Less in the Firefox Developer Tools

    Sass and Less are expressive languages that compile into CSS. If you’re using Sass or Less to generate your CSS, you might want to debug the source that you authored and not the generated CSS. Luckily you can now do this in the Firefox 29 developer tools using source maps.

    The Firefox developer tools use source maps to show the line number of rules in the original source, and let you edit original sources in the Style Editor. Here’s how to use the feature:

    1. Generate the source map

    When compiling a source to CSS, use the option to generate a sourcemap for each style sheet. To do this you’ll need Sass 3.3+ or Less 1.5+.

    Sass

    sass index.scss:index.css --sourcemap

    Less

    lessc index.less index.css --source-map

    This will create a .css.map source map file for each CSS file, and add a comment to the end of your CSS file with the location of the sourcemap: /*# sourceMappingURL=index.css.map */. The devtools will use this source map to map locations in the CSS style sheet to locations in the original source.

    2. Enable source maps in developer tools

    Right-click anywhere on the inspector’s rule view or in the Style Editor to get a context menu. Check off the Show original sources option:

    Enabling source maps in devtools

    Now CSS rule links will show the location in the original file, and clicking these links will take you to the source in the Style Editor:

    Original source showing in Style Editor

    3. Set up file watching

    You can edit original source files in Style Editor tool, but order to see the changes apply to the page, you’ll have to watch for changes to your preprocessed source and regenerate the CSS file each time it changes. To set watching up:

    Sass

    sass index.scss:index.css --sourcemap --watch

    Less

    For Less, you’ll have to set up another service to do the watching, like grunt.

    4. Save the original source

    Save the original source to your local file system by hitting the Save link or Cmd/Ctrl-S:

    Saving source to disk

    Saving source to disk

    The devtools will infer the location of the generated CSS file locally and watch that file for changes to update the live style sheet on the page.

    Now when you edit an original source and save it, the page’s style will update and you’ll get immediate feedback on your Sass or Less changes.

    The source has to be saved to disk and file watching set up in order for style changes to take effect.

  7. HTML5, CSS3, and the Bookmarklet that Shook the Web

    On Valentine’s Day last year we released a bookmarklet that went viral riding the popularity of the Harlem Shake meme. On the anniversary of its release we’d like to take a moment look back at the technical nuts and bolts of the bookmarklet as a case study in applying HTML5. In fact, the HTML, JavaScript, and CSS we used wouldn’t have worked on a single browser a few years ago. What follows is a technical discussion on how we took advantage of recent browser developments to shake up the web.

    Background

    Last year the Harlem Shake meme forced itself on to nearly every screen under the sun and, like everyone else, we had joked about doing our office version of the video. After tossing around a few bad video ideas, Ishan half-jokingly suggested a bookmarklet that made a web page do the Harlem Shake. Omar and Hari immediately jumped on the ingenuity of his idea and built a prototype within an hour that had the entire office LOLing. After pulling a classic all nighter we released it on February 14th, declaring “Happy Valentine’s Day, Internet! Behold, the Harlem Shake Bookmarklet”.

    Pretty soon it was picked up by news outlets like TechCrunch and HuffingtonPost, and our traffic skyrocketed. Meanwhile the bookmarklet offered a new avenue of expression in the watch-then-remix cycle that is the lifeblood of a viral meme like the Harlem Shake. Instead of creating a video of people dancing, developers could now remix this symbiotic meme in code. Startups like PivotDesk incorporated the bookmarklet into their websites, and HSMaker used the code to build a Harlem-Shake-As-A-Service website. Eventually, YouTube even built their own version as an easter egg on their site.

    So, how does it work?

    Once you click the Harlem Shake bookmark, a snippet of JS is evaluated on the webpage, just as you’d see by entering javascript:alert(“Hi MozHacks!”); in your address bar. This JavaScript will play the Harlem Shake audio, “shake” DOM nodes (according to timing events attached to the audio), and remove all DOM changes afterward.

    How did we attach the audio to the page and get the timing for the shakes just right?

    HTML5’s extensive audio support made this implementation fairly easy. All that was required was inserting an <audio> tag with the src pointed to the Harlem_Shake.ogg file. Once inserted into the DOM, the file would begin downloading, and playback begins once enough of the file has been buffered.

    HTML5 timed audio events allow us to know exactly when playback begins, updates, and ends. We attach a listener to the audio node which evaluates some JS once the audio reaches certain time. The first node starts shaking once the song is beyond 0.5s. Then, at 15.5s, we flash the screen and begin shaking all of the nodes. At 28.5s, we slow down the animations, and once the audio has ended, we stop all animations and clean up the DOM.

    audioTag.addEventListener("timeupdate", function() {
      var time = audioTag.currentTime,
          nodes = allShakeableNodes,
          len = nodes.length, i;
     
      // song started, start shaking first item
      if(time >= 0.5 && !harlem) {
        harlem = true;
        shakeFirst(firstNode);
      }
     
      // everyone else joins the party
      if(time >= 15.5 && !shake) {
        shake = true;
        stopShakeAll();
        flashScreen();
        for (i = 0; i < len; i++) {
          shakeOther(nodes[i]);
        }
      }
     
      // slow motion at the end
      if(audioTag.currentTime >= 28.4 && !slowmo) {
        slowmo = true;
        shakeSlowAll();
      }
    }, true);
     
    audioTag.addEventListener("ended", function() {
      stopShakeAll();
      removeAddedFiles();
    }, true);

    How did we choose which parts of the page to shake?

    We wrote a few helpers to calculate the rendered size of a given node, determine whether the node is visible on the page, and whether its size is within some (rather arbitrary) bounds:

    var MIN_HEIGHT = 30; // pixels
    var MIN_WIDTH = 30;
    var MAX_HEIGHT = 350;
    var MAX_WIDTH = 350;
     
    function size(node) {
      return {
        height: node.offsetHeight,
        width: node.offsetWidth
      };
    }
    function withinBounds(node) {
      var nodeFrame = size(node);
      return (nodeFrame.height > MIN_HEIGHT &&
              nodeFrame.height < MAX_HEIGHT &&
              nodeFrame.width > MIN_WIDTH &&
              nodeFrame.width < MAX_WIDTH);
    }
    // only calculate the viewport height and scroll position once
    var viewport = viewPortHeight();
    var scrollPosition = scrollY();
    function isVisible(node) {
      var y = posY(node);
      return (y >= scrollPosition && y <= (viewport + scrollPosition));
    }

    We got a lot of questions about how the bookmarklet was uncannily good at iniating the shake on logos and salient parts of the page. It turns out this was the luck of using very simple heuristics. All nodes are collected (via document.getElementsByTagName(“*”)) and we loop over them twice:

    1. On the first iteration, we stop once we find a single node that is within the bounds and visible on the page. We then start playing the audio with just this node shaking. Since elements are searched in the order they appear in the DOM (~ the order on the page), the logo is selected with surprising consistency.
    2. After inserting the audio, we have ~15 seconds to loop through all nodes to identify all shakeable nodes. These nodes get stored in an array, so that once the time comes, we can shake them.
    // get first shakeable node
    var allNodes = document.getElementsByTagName("*"), len = allNodes.length, i, thisNode;
    var firstNode = null;
    for (i = 0; i < len; i++) {
      thisNode = allNodes[i];
      if (withinBounds(thisNode)) {
        if(isVisible(thisNode)) {
          firstNode = thisNode;
          break;
        }
      }
    }
     
    if (thisNode === null) {
      console.warn("Could not find a node of the right size. Please try a different page.");
      return;
    }
     
    addCSS();
     
    playSong();
     
    var allShakeableNodes = [];
     
    // get all shakeable nodes
    for (i = 0; i < len; i++) {
      thisNode = allNodes[i];
      if (withinBounds(thisNode)) {
        allShakeableNodes.push(thisNode);
      }
    }

    How did we make the shake animations not lame?

    We utilized and tweaked Animate.css’s library to speed up the process, its light and easy to use with great results.

    First, all selected nodes gets a base class ‘harlem_shake_me’ that defines animation parameters for duration and how it should apply the styles.

    .mw-harlem_shake_me {
      -webkit-animation-duration: .4s;
         -moz-animation-duration: .4s;
           -o-animation-duration: .4s;
              animation-duration: .4s;
      -webkit-animation-fill-mode: both;
         -moz-animation-fill-mode: both;
           -o-animation-fill-mode: both;
              animation-fill-mode: both;
    }

    The second set of classes that defines the animation’s behavior are randomly picked and assigned to various nodes.

    @-webkit-keyframes swing {
      20%, 40%, 60%, 80%, 100% { -webkit-transform-origin: top center; }
      20% { -webkit-transform: rotate(15deg); }
      40% { -webkit-transform: rotate(-10deg); }
      60% { -webkit-transform: rotate(5deg); }
      80% { -webkit-transform: rotate(-5deg); }
      100% { -webkit-transform: rotate(0deg); }
    }
     
    @-moz-keyframes swing {
      20% { -moz-transform: rotate(15deg); }
      40% { -moz-transform: rotate(-10deg); }
      60% { -moz-transform: rotate(5deg); }
      80% { -moz-transform: rotate(-5deg); }
      100% { -moz-transform: rotate(0deg); }
    }
     
    @-o-keyframes swing {
      20% { -o-transform: rotate(15deg); }
      40% { -o-transform: rotate(-10deg); }
      60% { -o-transform: rotate(5deg); }
      80% { -o-transform: rotate(-5deg); }
      100% { -o-transform: rotate(0deg); }
    }
     
    @keyframes swing {
      20% { transform: rotate(15deg); }
      40% { transform: rotate(-10deg); }
      60% { transform: rotate(5deg); }
      80% { transform: rotate(-5deg); }
      100% { transform: rotate(0deg); }
    }
     
    .swing, .im_drunk {
      -webkit-transform-origin: top center;
      -moz-transform-origin: top center;
      -o-transform-origin: top center;
      transform-origin: top center;
      -webkit-animation-name: swing;
      -moz-animation-name: swing;
      -o-animation-name: swing;
      animation-name: swing;
    }

    Shake it like a polaroid picture

    What started a joke ended up turning into its own mini-phenomenon. The world has moved on from the Harlem Shake meme but the bookmarklet is still inspiring developers to get creative with HTML5.

    If you want to see the full source code or have suggestions, feel free to contribute to the Github repo!

  8. Application Layout with CSS3 Flexible Box Module

    It has become very easy to create fluid application layouts thanks to the CSS3 Flexible Box Layout Module. In this article we are going to implement a simple application layout, which fills the whole screen, resizes with the browser window and comes with the additional bonus of a draggable splitter.

    Instead of the classic <div> elements let’s also use some HTML5 structural tags. This will not only make the code more semantic, but also more convenient to work with, since we can directly address the elements with a CSS type selector without having to rely on id attributes or parent-child relationships.

    Take a look at the complete demo to see how it works.

    First step: Add Vertical Boxes

    We start with only three tags (<header>, <main> and <footer>) in the body.

    <!DOCTYPE html>
    <html>
    <head>
        <title>CSS3 Application Layout</title>
    </head>
     
    <body>
    <header></header>
    <main></main>
    <footer></footer>
    </body>
    </html>

    Let’s add the CSS to make these three elements fill the space vertically. This is achieved by setting the CSS display property of the <body> to flex and the flex-direction property to column. This tells the browser to lay out the body’s children (<header>, <main> and <footer>) as vertical flexible boxes.

    How this available space is distributed can be controlled with the flex shorthand property. You can read about it on MDN. In this application layout though, we don’t want the size to shrink or expand proportionally. Instead the <header> and the <footer> element should have a fixed height, whereas the <main> should just fill the remaining space by setting its flex property to auto.

    html, body {
        height: 100%;
        width: 100%;
        padding: 0;
        margin: 0;
    }
     
    body {
        display: flex;
        flex-direction: column;
    }
     
    header {
        height: 75px;
    }
     
    main {
        flex: auto;
    }
     
    footer {
        height: 25px;
    }

    Show demo

    Second Step: Horizontal Boxes

    Let’s add three more elements (<nav>, <article> and <aside>) inside the <main> element. But this time we want them to fill the space inside the <main> element horizontally instead of vertically.

    <body>
    <header></header>
    <main>
        <nav></nav>
        <article></article>
        <aside></aside>
    </main>
    <footer></footer>
    </body>

    This is achieved by setting the display property of the <main> element also to flex, but the flex-direction property to row (this is the default). The <nav> and <aside> element should have a fixed width, while the <article> should just fill the remaining space: this is achieved in the same kind of manner as before:

    main {
        display: flex;
        flex-direction: row;
        flex: auto;
    }
     
    nav {
        width: 150px;
    }
     
    article {
        flex: auto;
    }
     
    aside {
        width: 50px;
    }

    Show demo

    Thats all. Resize your browser window and enjoy the flexible application layout.

    Next step: CSS Refinements

    But wait. When there is a lot of content, an element can become smaller than specified and also scrollbars can appear.

    Therefore, we need to add a min-width property to all elements where we added a width property. We also should set the overflow property of the <body> and the <main> element to hidden as well as the overflow-y of <article> and <aside> to auto to only show scrollbars where we want them.

    body {
    	overflow: hidden;
    	display: flex;
    	flex-direction: column;
    }
     
    header {
    	height: 75px;
    	min-height: 75px;
    }
     
    footer {
    	height: 25px;
    	min-height: 25px;
    }
     
    main {
    	display: flex;
    	flex-direction: row;
    	flex: auto;
    	border: solid grey;
    	border-width: 1px 0;
    	overflow: hidden;
    }
     
    nav {
    	width: 150px;
    	min-width: 150px;
    }
     
    article {
    	border: solid grey;
    	border-width: 0 0 0 1px;
    	flex: auto;
    	overflow-x: hidden;
    	overflow-y: auto;
    }
     
    aside {
    	width: 50px;
    	min-width: 50px;
    	overflow-x: hidden;
    	overflow-y: auto;
    }

    Note: This does probably not work in Safari yet. You might be able to get it to work by using the -webkit- prefix.

    Final Step: Throw a little JavaScript into the Mix

    As the final step, we want the user to be able to resize the <aside> element when dragging it with the mouse. For that we add a <div> element as a splitter, which will serve as the drag handle.

    <body>
    <header></header>
    <main>
        <nav></nav>
        <article></article>
        <div class="splitter"></div>
        <aside></aside>
    </main>
    <footer></footer>
    </body>

    We set the width of the handle to 4px and give the cursor attribute a value of col-resize, to show the user that this element can be resized East-West.

    .splitter {
        border-left: 1px solid grey;
        width: 4px;
        min-width: 4px;
        cursor: col-resize;
    }

    All what’s left now is to add a little JavaScript, that enables moving the splitter.

    var w = window, d = document, splitter;
     
    splitter = {
        lastX: 0,
        leftEl: null,
        rightEl: null,
     
        init: function(handler, leftEl, rightEl) {
            var self = this;
     
            this.leftEl = leftEl;
            this.rightEl = rightEl;
     
            handler.addEventListener('mousedown', function(evt) {
                evt.preventDefault();    /* prevent text selection */
     
                self.lastX = evt.clientX;
     
                w.addEventListener('mousemove', self.drag);
                w.addEventListener('mouseup', self.endDrag);
            });
        },
     
        drag: function(evt) {
            var wL, wR, wDiff = evt.clientX - splitter.lastX;
     
            wL = d.defaultView.getComputedStyle(splitter.leftEl, '').getPropertyValue('width');
            wR = d.defaultView.getComputedStyle(splitter.rightEl, '').getPropertyValue('width');
            wL = parseInt(wL, 10) + wDiff;
            wR = parseInt(wR, 10) - wDiff;
            splitter.leftEl.style.width = wL + 'px';
            splitter.rightEl.style.width = wR + 'px';
     
            splitter.lastX = evt.clientX;
        },
     
        endDrag: function() {
            w.removeEventListener('mousemove', splitter.drag);
            w.removeEventListener('mouseup', splitter.endDrag);
        }
    };
     
    splitter.init(d.getElementsByClassName('splitter')[0], d.getElementsByTagName('article')[0], d.getElementsByTagName('aside')[0]);

    Note: For some reason the resizing doesn’t work in IE11 (, Safari?) or Chrome 31. It seems that it has something to do with the display: flex; property value.

  9. CSS Variables in Firefox Nightly

    As reported by Cameron McCormack, Firefox Nightly (version 29) now supports CSS variables. You can get a quick overview in this short screencast:

    You can define variables in a context with a var- prefix and then implement them using the var() instruction. For example:

    :root {
      var-companyblue: #369;
      var-lighterblue: powderblue;
    }
     
    h1 {
      color: var(companyblue);
    }
    h2 {
      color: var(lighterblue);
    }
    <h1>Header on page</h1>
    <h2>Subheader on page</h2>

    This defines the two variables companyblue and lighterblue for the root element of the document which results in (you can try it here using Firefox Nightly):

    Variables are scoped, which means you can overwrite them:

    :root {
      var-companyblue: #369;
      var-lighterblue: powderblue;
    }
    .partnerbadge {
      var-companyblue: #036;
      var-lighterblue: #cfc;
    }
     
    h1 {
      color: var(companyblue);
    }
    h2 {
      color: var(lighterblue);
    }
    <h1>Header on page</h1>
    <h2>Subheader on page</h2>
     
    <div class="partnerbadge">
      <h1>Header on page</h1>
      <h2>Subheader on page</h2>
    </div>

    Using these settings, headings inside an element with a class of partnerbadge will now get the other blue settings:

    Variables can be any value you want to define and you can use them like any other value, for example inside a calc() calculation. You can also reset them to other values, for example inside a media query. This example shows many of these possibilities.

    :root {
      var-companyblue: #369;
      var-lighterblue: powderblue;
      var-largemargin: 20px;
      var-smallmargin: calc(var(largemargin) / 2);
      var-borderstyle: 5px solid #000;
      var-headersize: 24px;
    }
    .partnerbadge {
      var-companyblue: #036;
      var-lighterblue: #369;
      var-headersize: calc(var(headersize)/2);
      transition: 0.5s;
    }
     
    @media (max-width: 400px) {
      .partnerbadge {
         var-borderstyle: none;
         background: #eee;
      }
    }
     
    /* Applying the variables */
    body {font-family: 'open sans', sans-serif;}
     
    h1 {
      color: var(companyblue);
      margin: var(largemargin) 0;
      font-size: var(headersize);
    }
    h2 {
      color: var(lighterblue);
      margin: var(smallmargin) 0;
      font-size: calc(var(headersize) - 5px);
    }
     
    .partnerbadge {
      padding: var(smallmargin) 10px;
      border: var(borderstyle);
    }

    Try resizing the window to less than 400 pixels to see the mediaQuery change in action.

    An initial implementation of CSS Variables has just landed in Firefox Nightly, which is currently at version 29 and after the February 3 merge, in Firefox Aurora. There are still a few parts of the specification which still need to be supported before the can go into the release cycle of Firefox Beta and Firefox. Cameron has the details on that:

    The only part of the specification that has not yet been implemented is the CSSVariableMap part, which provides an object that behaves like an ECMAScript Map, with get, set and other methods, to get the values of variables on a CSSStyleDeclaration. Note however that you can still get at them in the DOM by using the getPropertyValue and setProperty methods, as long as you use the full property names such as "var-theme-colour-1".

    The work for this feature was done in bug 773296, and my thanks to David Baron for doing the reviews there and to Emmanuele Bassi who did some initial work on the implementation. If you encounter any problems using the feature, please file a bug!

    For now, have fun playing with CSS variables in Nightly and tell us about issues you find.

  10. CSS Length Explained

    When styling a web site with CSS you might have realised that an inch on a screen is not an actual inch, and a pixel is not necessarily an actual pixel. Have you ever figured out how to represent the speed of light in CSS pixels? In this post, we will explore the definition of CSS length units starting by understanding some of the physical units with the same name, in the style of C.G.P. Grey[1].

    The industrial inch (in)

    People who live in places where the inch is a common measure are already familiar with the physical unit. For the rest of us living in places using the metric system, since 1933, the “industrial inch” has been defined as mathematical equivalent of 2.54 centimeters, or 0.0254 metres.

    The device pixel

    Computer screens display things in pixels. The single physical “light blob” on the display, capable of displaying the full color independent of it’s neighbour is called a pixel (picture element). In this post, we refer to the physical pixel on the screen as “device pixel” (not to be confused with CSS pixel which will be explained later on).

    Display pixel density, dots per inch (DPI), or pixels per inch (ppi)

    The physical dimension of a device pixel on a specific device can be derived from the display pixel density given by the device manufacturer, usually in dots per inch (DPI), or pixels per inch (PPI). Both units are essentially talking about the same thing when they refer to a screen display, where DPI is the commonly-used-but-incorrect unit and PPI is the more-accurate-but-no-one-cares one. The physical dimension of a device pixel is simply the inverse number of it’s DPI.

    The MacBook Air (2011) I am currently using comes with a 125 DPI display, so

    (width or height of one device pixel) = 1/125 inch = 0.008 inch = 0.02032 cm

    Obviously this is a number too small to be printed on the specification, so the DPI stays.

    The CSS pixel (px)

    The dimension of a CSS pixel can be roughly regarded as a size to be seen comfortably by the naked human eye, not too small so you’d have to squint, and not big enough for you to see pixelation. Instead of consulting your ophthalmologist on the definition of “seen comfortably”, the W3C CSS specification gives us a recommend reference:

    The reference pixel is the visual angle of one pixel on a device with a pixel density of 96 DPI and a distance from the reader of an arm’s length.

    The proper dimension of a CSS pixel is actually dependent on the distance between you and the display. With the exception of Google Glass (which mounts on your head), people usually find their own unique comfortable distance, dependent on their eyesight, for a particular device. Given the fact we have no way to tell whether the user is visually impaired, what concerns us is simply typical viewing distance for the given device form factor — e.g., a mobile phone is usually held closer, and a laptop is usually used on a desk or a lap. Thus, the “viewing distance” of mobile phones is shorter than the one of laptops, or desktop computers.

    The viewing distance

    As previously mentioned, the viewing distance varies from person to person and from device to device, which is why we must categorise devices into form factors. The recommended reference viewing distance (“an arm’s length”) and the reference pixel density (“96 DPI”) is actually historical; it is a testimony of the way people during the late-20th century usually accessed the web:

    The first computer that runs the web. From Wikipedia: WWW

    The first computer that runs the web. From Wikipedia: WWW.

    For day-to-day devices of the 21st century, we have different reference recommendations:

    Baseline pixel density

    Width/height of one CSS pixel

    Viewing distance

    A 20th century PC with CRT display

    96 DPI

    ~0.2646 mm (1/96in)

    28 in (71.12cm)

    Modern laptop with LCD[2]

    125 DPI

    0.2032 mm (1/125in)

    21.5 in (54.61cm)

    Smartphones/Tablets[3]

    160 DPI

    ~0.159mm (1/160 in)

    16.8in (42.672cm)

    From this table, it’s pretty easy to see that as the pixel density increases and size of a CSS pixel gets smaller, muggles like you and me usually need to hold the device closer to comfortably see what’s on the device screen.

    With that, we established a basic fact in the world of CSS: a CSS pixel will be displayed in different physical dimensions but it will always be displayed in the correct size in which the viewer will find comfortable. By leveraging the principle, we can safely set the basic dimensions (e.g. base font size) to a fixed pixel size, independent of device form factors.

    CSS inch (in)

    On a computer screen, a CSS inch has nothing to do with the physical inch. Instead, it is being redefined to be exactly equal to 96 CSS pixels. This has resulted in an awkward situation, where you can never reliably draw an accurate ruler on the screen with basic CSS units[4]. Yet this gives us what’s intended: elements sized in CSS units will always be displayed across devices in a way where the user will feel comfortable.

    As a side note, if the user prints out the page on a piece of paper, browsers will map the CSS inch to the physical inch. You can reliably draw an accurate ruler with CSS and print it out. (make sure you’d turn off “scale to fit” in the printer settings!)

    Device pixel ratio (DPPX)

    As we step into the future (where is my flying car?), many of the smartphones nowadays are shipped with high-density displays. In order to make sure that CSS pixels are sized consistently across every device that accesses the web (i.e. everything with a screen and network connection), device manufacturers had to map multiple device pixels to one CSS pixel to make up for it’s relative bigger physical size. The ratio of the dimension of CSS pixel relative to device pixels is the device pixel ratio (DPPX).

    Let’s take iPhone 4 as the most famous example. It comes with a 326 DPI display. According to our table above, as a smartphone, it’s typical viewing distance is 16.8 inches and it’s baseline pixel density is 160 DPI. To create one CSS pixel, Apple chose to set the device pixel ratio to 2, which effectively makes iOS Safari display web pages in the same way as it would on a 163 DPI phone.

    Before we move on, take a look back on the numbers above. We can actually do better by not setting device pixel ratio to 2 but to 326/160 = 2.0375, and make a CSS pixel exactly the same compared to the reference dimensions. Unfortunately, such ratio will result in an unintended consequence: as each CSS pixel is not being displayed by whole device pixels, the browser would have to make some efforts to anti-alias all the bitmap images, borders, etc. since almost always they are defined as whole CSS pixels. It’s hard for browsers to utilize 2.0375 device pixels to draw your 1 CSS pixel-wide border: it’s way more easier to do it if the ratio is simply 2.

    Incidentally, 163 DPI happens to be the pixel density of the previous generation of the iPhone, so the web will work the same way without having developers to do any special “upgrades” to their websites.

    Device manufacturers usually choose 1.5, or 2, or other whole numbers as the DPPX value. Occasionally, some devices decided not to play nice and shipped with something like 1.325 DPPX; as web developers, we should probably ignore those devices.

    Firefox OS, initially being a mobile phone operating system, implemented DPPX calculation in this way. The actual DPPX will be determined by the manufacturer of each shipping device.

    CSS point (pt)

    Point is a commonly used unit that came from the typography industry, as the unit for metal typesetting. As the world gradually moved from letterpress printing to desktop publishing, a “PostScript point” was then redefined as 1/72 inches. CSS follows the same convention and mapped 1 CSS point to 1/72 CSS inches, and 96/72 CSS pixels.

    You can easily see that just like a CSS inch, on a device display, CSS point has little to do with the traditional unit. Its size only matches it’s desktop publishing counterpart when we actually print out the web page.

    CSS pica (pc), CSS centimeter (cm), CSS millimeter (mm)

    Just like CSS inch, while their relative relationships are kept, their basic size on the screen have been redefined by CSS pixel, instead of the standard SI unit (metre), which is defined by the speed of light, a universal constant.

    We could literally redefine the speed of light in CSS; it is 1,133,073,857,007.87 CSS pixels per second[5] — relativity in CSS makes light travel a bit slower on devices with smaller form factors than traditional PCs, from our perspective, looking into the screen from the real world.

    The viewport meta tag

    Though the smartphone is handy in the palm of your hand and its guaranteed that CSS pixels will be displayed in a size comfortable to users, a device capable of showing only a part of a fixed-width desktop website is not going to be very useful. It would be equally not useful if the phone violated the CSS unit rules and pretended it to be something else.

    The introduction of the viewport meta tag brought the best of both worlds to mobile devices by giving the control of page scaling to both users and web developers. You could design a mobile layout, and opt out of viewport scaling, or, you could leave your website made for desktop browsers as-is and have the mobile browser scale down the page for you and the user. As always, detailed descriptions and usage can be found on Mozilla Developer Network.

    Conclusion

    Browser vendors, while being in competition, recognize the effort of maintaining the stability of the Web platform and coordinate their feature sets through a standard organization. Features and APIs exposed will be carefully tested for their usefulness across all scenarios, before declaring their suitability as a standard. The definition of CSS pixel has one of those since the beginning. New features introduced must maintain backward-compatibility instead of changing the old behavior[6], so many of them (device pixels, viewport meta tag, etc.) are being introduced as extra layers of complexity. Old web pages that use standardized features, thus have a built-in “forward-compatibility”.

    With that in mind, Mozilla, together with our partners, nurture and defend the Open Web — the unique platform that we all cherish.


    [1] Well, not actually, cause we are not going to make a video about it. I won’t mind if C.G.P. Grey actually made a video about this!

    [2] Appears to be common values for laptops[citation needed].

    [3] The typical value is documented here as a “mdpi” Android device.

    [4] With one exception: the non-standard CSS unit mozmm gives you the ability to do so provided that Firefox knows the pixel density it runs on. This is out of scope of our topic there.

    [5] 299,792,458 metres per second ÷ 0.0254 meters per inch x 96 pixels per inch

    [6] There was a brief period of time where people tried to come up with an entirely new standard that breaks backward compatibility (*cough* xHTML *cough*), but that’s a story for another time.