Why Typography

This is the first of a series of articles on Typography and the potential of text on the web

Over the past few months I’ve rekindled my interest in typography; how it works in print and how it works online. I’m also working through two typography books that are very relevant to both typographic work and overall front end design and development. Responsive Typography by Jason Pamental, On web typography by Jason Santa Maria and Professional Web Typography by Donny Truong.

But it wasn’t until fluent that I got a better idea of why typography is important.I got the chance to talk with both Eric Meyer, one of my early web design influences, and Jason Pamental, the author of Responsive Typography and a very good presenter.

What I got out of multiple presentations about CSS, typography and new technologies coming and going away (sadly) is that the basics are still important. With that in mind I’ll look at typography through a series of exercises.

The first thing to learn is that all typefaces are different. What works for the typefaces I chose may or may not work for the typefaces you choose for your projects. Where possible I’ll show the typefaces used in this page against other typefaces (most likely from the ‘web safe’ font set.)

Why worry about typography on the web?

Universal Typography — Tim Brown

I love the web and I’ve been working on digital content for almost 20 years. While I agree with the universality and accessibility requirements for the web (it should be accessible by anyone anywhere, regardless of disability or network connection) the content doesn’t have to be boring or plain

Whether we are reading a paper book or a web page or a iBook or Kindle ebook, typography still matters and it’s still an important part of the design process.

For the longest time I’ve heard that the web is not print and that we shouldn’t look at books as sources for web design inspiration. This may be true: the web is not print. But we’re getting to the point where CSS on its own or a combination of CSS and Javascript will gives a large part of what we see in print in a way that won’t look terrible in older browsers, when the user access it with assistive technology, or when CSS and Javascript are disabled.

I started taking a serious look at typography about 3 years ago. I’m not an expect and I’m most definitely not a professional but I’m learning and the more I learn the more I think we can use the full range of web technologies to enhance the text and the reading experience for our users.

I’m also including several things such as CSS Transitions and Animations that, while not directly related to typography, still affect the way text appears on screen.

Responsive SVG graphics

One of the most intriguing things I’ve learned about SVG over the last few months is that we can run CSS, including media queries, inside the SVG file itself so the queries will modify the internal content of the files will change based on the queries inside the svg.

Getting started

See the Pen SVG basic example by Carlos Araya (@caraya) on CodePen.2039

The CSS for the SVG graphic is embedded in the SVG file itself. We copied the SVG file’s XML content directly in the pen, but there’s no reason why the content cannot be saved in a text file with a .svg extension.

Because SVG is an XML vocabulary we need to take some protective measures, particularly with our CSS. You will see < ![CDATA[]]> element surrounding the CSS inside our tag. This is an XML artifact that renders all its content as character data instead of markup. We do this to prevent any possibility of illegal XML characters inside our CSS from messing up the content.

Simple changes

See the Pen SVG with Media Queries by Carlos Araya (@caraya) on CodePen.2039

For our example, we’ll add ID attributes to all elements. Since we are working in an individual SVG file we don’t need to worry about weight or specificity, we can just do it.

After we add color to our content we create two media queries.

  1. The first one will trigger when the width is smaller than 600px and it will hide the circle by setting its display property to none.
  2. The second one will trigger when the screen becomes smaller than 320px and it will hide the rectangle by setting its display property to none, leaving only the start visible in our SVG image.
@media (max-width: 600px) { /* 1 */
  #circle1 {
    display: none;
  }
}

@media (max-width: 320px { /* 2 */
  #rectangle1: {
    display: none;
  }
}

We can get more sophisticated by performing multiple actions within each media query. This allows to play with with both animations, different media query types that I wouldn’t normally use and animations where they are appropriate.

<div class='container'>
  <?xml version="1.0" encoding="iso-8859-1" ?>
  <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
  <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">

    <defs>
      <style>
              #rectangle1 {
                fill: #f00;
              }

              #circle1 {
                fill: #00f;
              }

              #star1 {
                fill: #0f0;
                transform:  rotate(0deg);
              }

              /* Media Queries */
              @media (max-width: 1000px) { /* 1 */
                #circle1 {
                  display: none;
                }
              }

              @media (max-width: 800px) { /* 2 */
                #circle1 {
                  display: block;
                  fill: #f0f;
                }

                #rectangle1: {
                  display: none;
                }

                #star1 {
                    display: #663399; /* rebeccapurple */
                    animation: animationFrames ease-out 2s;
                    animation-iteration-count: 2;
                    transform-origin: 0 0 ;
                  }

                  @keyframes animationFrames{
                    0% {
                      transform:  rotate(0deg);
                    }
                    99% {
                      transform:  rotate(180deg);
                    }
                    100% {
                      transform: roatete(0deg);
                    }
                  }
                }
      </style>
    </defs>

    <rect x="61.768" y="61.768" transform="matrix(0.7071 0.7071 -0.7071 0.7071 150 -62.1321)" width="176.464" height="176.464" id='rectangle1' />

    <circle cx="150" cy="148" r="96" id='circle1' />

    <polygon points="150, 16.914 176.961, 99.892 264.208, 99.892 193.624, 151.174 220.585, 234.151 150, 182.869 79.415, 234.151 106.376, 151.174 35.792, 99.892 123.039, 99.892 " id='star1' />

  </svg>

</div>

We’ll take the same image as we used in the example before and both change colors and perhaps move them around when we hit the different breakpoints. In the Codepen above we do the following things:

  1. In addition to the color for the #star1 element’s fill we make sure that we rotate it to 0 degrees by default
  2. When the browser is 1000 pixels or smaller we hide the circle element
  3. When the browser is 800 pixels or smaller we do the following:
  4. We display #circle1 again (it was hidden in the previous query) and we change its color to #f0f
  5. We take the #star1 element, change its color to #663399 and set up animation attributes: animation tells the user agent what animation, what animation type and for how long we want to use the animation
  6. Definition for the animation steps references in step 5. We define each frame as what percentage of the animation we want that specific action to work on. In this case we defined 3 frames but we can define additional frames to make the animation smoother
#star1 { /* 1 */
  fill: #0f0;
  transform:  rotate(0deg);
}

/* Media Queries */
@media (max-width: 1000px) { /* 2 */
  #circle1 {
    display: none;
  }
}

@media (max-width: 800px) { /* 3 */
  #circle1 { /* 4 */
    display: block;
    fill: #f0f;
  }

  #rectangle1: {
    display: none;
  }

  #star1 { /* 5 */
    display: #663399; /* rebeccapurple */
    animation: animationFrames ease-out 2s;
    transform-origin: 50% 50% ;
  }

  @keyframes animationFrames{ /* 6 */
    0% {
      transform:  rotate(0deg);
    }
    99% {
      transform:  rotate(180deg);
    }
    100% {
      transform: rotate(0deg);
    }
  }
}

The one shortcoming of our image as currently implemented is that there are not enough steps for a smooth 360 degree transition. We could add more steps and make each step more gradual, something like this:

  @keyframes animationFrames{ /* 6 */
    0% {
      transform:  rotate(0deg);
    }
    25% {
      transform:  rotate(90deg);
    }
    50% {
      transform:  rotate(180deg);
    }
    75% {
      transform:  rotate(270deg);
    }
    100% {
      transform: rotate(0deg);
    }
  }

You can use the same techniques to completely change the appearance of your SVG graphic based on size or any query type you can use Media Queries with. The good news is that Media Queries Level 4 provides a much larger feature set for you to work with.

For example, we can modify our SVG content based on whether we’re working with monochrome displays by using a query like this:

@media (monochrome) {
  /* Rules for monochrome displays go here */
}

Support in browsers or readers

CSS animations should work in all modern browsers that support SVG (all modern browsers from IE9 onwards according to caniuse.com).

When I first looked at CSS animations in e-readers I got scared that epub3 didn’t support SVG animations but then I realized that it’s SVG-only animations not CSS animations applied to SVG.

As with all the techniques I’ve discussed here test all your content in your target devices

Conclusion

We can leverage a lot of the CSS tools and specifications inside of SVG files. This is not the only way to do it… We can take the CSS outside of the SVG and incorporate it with the CSS selectors and rules in the rest of our document. This adds our SVG CSS to the list of potential problems of specificity and you’ll have to do a lot more work to make sure the cascade works for your design.

Either way it’s a very interesting technique to add interactivity to your content in the open web.

Books as (web) apps

Books as applications

What would it take to make our books in to applications for the web? In this article we’ll explore what is an application, what is a web application, why it now makes sense to turn our books in to web applications.

What is an application? What is a web application?

Application software (an application) is a set of one or more programs designed to permit the user to perform a group of coordinated functions, tasks, or activities. Application software cannot run on itself but is dependent on system software to execute. Examples of an application include a word processor, a spreadsheet design and management system, an aeronautical flight simulator, a console game, a drawing, painting, and illustrating system, or a library management system. [1]

From Wikipedia

A web application or web app is any software that runs in a web browser. It is created in a browser-supported programming language (such as the combination of JavaScript, HTML and CSS) and relies on a web browser to render the application.[1][2][3]

Web applications are popular due to the ubiquity of web browsers, and the convenience of using a web browser as a client, sometimes called a thin client. The ability to update and maintain web applications without distributing and installing software on potentially thousands of client computers is a key reason for their popularity, as is the inherent support for cross-platform compatibility. Common web applications include webmail, online retail sales, online auctions, wikis and many other functions.

From Wikipedia

Open Web versus OS-specific Apps

It hasn’t been long since browser (Chrome and Firefox) and Operating System Vendors (Microsoft) allow web content to live in the OS as applications subject to packaging and usage restrictions.

I’ve chosen to remain platform neutral as much as possible.

The idea is that we’ll use ‘The Web’ as out application environment where both mobile and desktop users can use the same content. The moment we introduce OS specific features we invite what I call the ‘why not my OS’ syndrome… it’s just not worth it when the web is getting more and more powerful as an application environment all the time.

Mobile devices also have web browsers so we can use the web version in Mobile and we’ll take advantage of that for some mobile browsers (See iOS icons and splash screens, below.)

The DRM/EME monster rears its ugly head

One issue that needs to be addressed is Digital Rights Management or DRM.

People look at DRM as a way to preserve intellectual property and to keep people from giving away or lending books that they did not buy.

But DRM is not a perfect (or even a good) solution. Here are some reasons:

  • The DRM schemas can be broken and the content can still be given away. It is not a trivial exercise, true. But it’s not very difficult either
  • If your ebook provider goes under you will loose access to your books unless the seller has made arrangements to continue supporting the DRM scheme
  • You’re locked to your vendor. Amazon, Apple and Barnes and Nobles all use different DRM schemes and they are not compatible. You may still be locked to your vendor without DRM but it would make switching readers easier if they use a common format without restrictions

Ian Hickson writes about DRM. In one of the last paragraphs of the post, Hickson observes that:

Arguing that DRM doesn’t work is, it turns out, missing the point. DRM is working really well in the video and book space. Sure, the DRM systems have all been broken, but that doesn’t matter to the DRM proponents. Licensed DVD players still enforce the restrictions. Mass market providers can’t create unlicensed DVD players, so they remain a black or gray market curiosity. DRM failed in the music space not because DRM is doomed, but because the content providers sold their digital content without DRM, and thus enabled all kinds of players they didn’t expect (such as “MP3” players). Had CDs been encrypted, iPods would not have been able to read their content, because the content providers would have been able to use their DRM contracts as leverage to prevent it.

This is not just an academic exercise on freedom of expression. Publishers like O’Reilly (described here and here) and Tor have removed DRM from their books and, while the books have been widely pirated, sales have not decreased and have seen a modest improvement. I’ll try to get information from O’Reilly with updated figures and will update the article when/if I received an answer.

In 2009, David Pogue, a technology columnist from the New York Times, wrote a piece about ebooks and copy protection. In the article one of his readers sums up what, to me, the real issue:

“When the iPod introduced music lovers to the idea of copy protection, a years-long war ensued between consumers and the RIAA (and others). The primary issue was that if I purchased a song for my music player, it would only play on that player; I didn’t really own it, per se. Years later, we finally have digital music without copy protection.”

This was reinforced when Amazon deleted books from Kindle readers in 2009 and later in 2012 allegedly wiped a user’s entire Kindle library.

While I understand publishers’ positions, DRM is not the answer any more than it was in the Music industry when Apple introduced the iPod. If we can consistently prove that removing DRM will not damage sales and will improve t he user experience the more we can get publishers to stop thinking in terms of absolute sales as the only goal that matters.

Although not directly related to DRM, in the sense that they don’t provide the full set of access restrictions DRM does, Encrypted Media Extensions (EME) provide a similar platform for building restrictions to video content on the web.

I mention EME briefly because it will become the next battleground in the fight between content distributors and content consumers. The best explanation of what EME is and how it affects the web and its ideals is a page titled What is EME by Henri Sivonen.

What worries me the most is the fact that in the case of Firefox:, as mentioned by Cory Doctorow:

The inclusion of Adobe’s DRM in Firefox means that Mozilla will be putting millions of its users in a position where they are running code whose bugs are illegal to report. So it’s very important that this code be as isolated as possible.

All browsers have some level of support for EME. Firefox has announced their intent to implement EME, Google and Apple already support parts (in the case of Google) and all of the specs (Apple) to fully encrypt video content. At least 3 of these browsers: Firefox, Chrome and Opera (or Chrome Jr.) have open bug reporting systems; how will they be affected by these new restrictions on the proprietary software that makes EME?

Netflix seems to have gotten away with EME, at least for now. MSE, EME, and Web Cryptography APIs to fully control when, how and who can access their content. An earlier post in their technology blog seems to indicate that the technologies are also supported in ChromeOS (with the exception of the Crypto API) and that when Web Crypto is implemented in Chrome then they will move to encrypting all content viewable in Chrome for all platforms.

It’ll be interesting to see how this evolves and what other areas it moves to beyond video. For an interesting discussion about DRM listen to The Web Ahead, Episode 73 with Doug Scheppers and Jeremy Keith.

Online versus offline

One specific type of enhancement we’ll discuss before jumping into the bells and whistles is whether we should add offline caching.

The APIs are in progress. Chrome supports most of the APIs we need to create offline capable applications as part of ServiceWorkers (they support cache, through polyfill, push messaging and notification) whether the page using them is open or not. While the Chrome implementation only support Google Cloud Messaging the idea is that we’ll soon have an open source solution to the push and notification challenges we currently face. So, unless you’re already working with GCM and ther other required technologies it may be better to see what the open web has to offer when the specifications are finalized.

The idea behind push and background notifications is that we can build a fully responsive user experience that will work on and offline and notify the user on specified events, such as updated content, and the application doesn’t even need to be running to do so.

I’ve written about ServiceWorkers when discussing Athena as an offline reading experience so I won’t repeat all the rationale and code here.

In an HTML5 Rocks article Jeff Posnick describes how we can automate the creation of a caching service worker using Gulp.

gulp.task('generate-service-worker', function(callback) {
  var fs = require('fs');
  var path = require('path');
  var swPrecache = require('sw-precache');
  var rootDir = 'app';

  swPrecache({
    staticFileGlobs: [rootDir + '/**/*.{js,html,css,png,jpg,gif}'],
    stripPrefix: rootDir
  }, function(error, swFileContents) {
    if (error) {
      return callback(error);
    }
    fs.writeFile(path.join(rootDir, 'service-worker.js'), swFileContents, callback);
  });
});

Enhancing the user experiences

Offline content caching is just part of the exercise. The other part is what additional tools, libraries and scripts we add to our web documents and how will they work in an offline environment.

For each of the technologies discussed below I’ll provide a brief summary and why I chose the technology.

One thing to realize from the beginning is that, while I chose to show all possible technologies, some of these are part of the build process for our site/app they are still important and need to be mentioned

Modernizr and Modernizr.load

Modernizr makes it easier to use new HTML5 tags and APIs and CSS3 technologies in a way that will also provide graceful degradation for our content.

We can leverage Modernizr from both CSS and Javascript.

For CSS Modernizr will add classes for each feature tested depending on whether it supports a feature (regions would be the class if regions are supported) or not (no-regions in that case).

.video .highlight {}

.no-video .highlight {}

For Javascript Modernizr creates an object and attaches all successful tests. for examplle, if we wanto to test if a browser supports video we can do something like this:

if (modernizr.video) {
  console.log ('we can play video');
  // load the vide or do furhter testing
} else {
  console.log ('we cannot play video, need polyfill');
  // load an alternative, perhaps the solution from
  // video for everyone
}

Modernizr.load uses Modernizr’s feature detection libarry to conditionally load content based on feature availability. Continuing with our video example, if the browser supports HTM5 video and can play h264 (MP4) video we load the video.js otherwise (cannot play h264 or cannot play HTML5 video altogher) we load a polyfill library or, most likely the solution presented in Video for everybody by Kroc Camen.

Modernizr.load({
  test: Modernizr.video && Modernizr.video.h264,
  yep : 'video.js',
  nope: 'video-polyfill.js'
});

There are ways to test for features without using Modernizr, but they all require lots of testing and they are not guaranteed to work on every browser.

Normalize.css

Normalize is a CSS library that provides an event and better playing field. In addition to providing the functionality of a CSS Reset library (Like Eric Meyer’s CSS Reset with added functionality.

It [Normalize] fixes common desktop and mobile browser bugs that are out of scope for resets. This includes display settings for HTML5 elements, correcting font-size for preformatted text, SVG overflow in IE9, and many form-related bugs across browsers and operating systems.

For a more detailed explanation see Nicolas Gallagher post abut Normalize.css

Singularity / Susy Grid System

Singularity is a Grid System designed with repsponsive grids in mind. From the documentation:

Singularity is a next generation grid framework built from the ground up to be responsive. What makes Singularity different? Well, a lot of things. Singularity is based on internal ratios instead of context based which allows for better gutter consistency across breakpoints. Ratio based math also allows for non-uniform grids in any unit you want to use.

If you’re used to working with SASS and Compass then it’s a breeze to work with Singularity; however that’s where the problem is: you must work with the Ruby version of SASS and you must work with Compass. Integrating Ruby, SASS installation and compilation and Compass is not a small undertaking so I try to avoid it where possible.

Susy is a more flexible framework; It provides the same functionality without requiring Compass. It also plugs in with existing Grunt SASS tasks, something like this (ignore the syntax for the moment, we’ll revisit Grunt and Gulp later in the article):

// Gruntfile.js
sass: {
  dist: {
    options: {
      style: 'expanded',
      require: 'susy'
    },
    files: {
        'css/style.css': 'scss/style.scss'
    }
  }
}

Beyond the obvious use of grids to provide a consistent interface to layout content they provide answer to more complicated questions: How do we create layouts with columns of arbitrary width (using percentages or rem units)? How do we span multiple columns? How do we change the gutter for our layout (or parts of the layout)?

Media Queries Support

I am lazy. Even though I have defined my own set of media queries and even took into account different screen sizes and resolutions, it’s not something that I want to maintain long-term. Breakpoint to the rescue!

Breakpoint abstracts a lot of the work in creating Mediaqueries. It includes support for when queries are not supported, ability to pass a context to your own mixins and advanced media queries including: compound queries, density-based and media types.

In an ideal world all browsers would have the same support for the same features and we wouldn’t have to deal with inconsistencies. Media Queries are one step in solving these issues.

Prefix Free and UNCSS

If I don’t have to write it usually I won’t. On the other hand there are times when the accumulation of cruft (old classes the are no longer used) or the sheer size of a framework (think Twitter Bootstrap, Zurb Foundation or Adobe Top Coat) versus the classes from the framework we actually use make for bloated CSS and unnecessary data being sent over the wire.

Addy Osmani has written about this problem along with a potential solution. UNCSS will load the HTML and CSS using Phantom.js and then create a new CSS file using only those selectors that match content in the HTML files. The savings can reach the 100k mark (!).

PrefixFree is a Javascript library that automates vendor prefixes for CSS selectors. The classic example is border radius, there are 5 nearly identical ways to address the same property (WebKit, Chrome/Opera, Mozilla, IE and Standard). Prefix Free takes care of the differences so we don’t have to

When we discuss tooling we’ll talk about grunt-autorprefixer, which removes the Javascript library while achieving the same effect of prefixing content as needed for the browsers we specify.

As I mentioned, I’m lazy and don’t want to write any more code than absolutely necessary have to. This is one way to reduce the code count

Typography

Compass Typography suffers from the same issues as all Compass-related plugins do. They depend on Compass which in turns depends on having Ruby installed on your system. Again, don’t get me wrong, I think compass is awesome but it’s not always necessary and it adds bloating to the resulting CSS.

Typeplate takes a minimalist approach to framework development. It doesn’t do much but what it does well and it does simply. It provides a minimal set of HTML models and corresponding SCSS/CSS templates. You can use it as-is or you can enhance it

The idea of using SASS/CSS typography solutions is that it makes it easier to create your content. You don’t always have to stick with what the framework has to offer… I’ve always considered CSS frameworks to be a starting point for my own work and not and end in and of itself.

Neither of the alternatives offers answers to how to load the fonts on the page. Depending on the fonts we may be able to leverage services like fonts.com, Adobe Typekit, Font Squirrel, Google and Font Deck, among others, to handle the download of your fonts.

Some of the best fonts are not available through font services. If you’re sure the font matches your needs and the license available (in most cases it’s a different license for web and ebooks) you can host the font on your server and use it from there. There are ups and downs like having to provide for font obfuscation and other security measures to having a wider selections of fonts to license and use.

Note the different versions of the same font you have to support to be compatible with most (all?) existing browsers. You probably can do away with supporting IE6 – IE8 if you can but that still leaves you with 5 different formats for each font you want to support (you can convert your woff font to woff2 using this online converter.)

We can embed fonts in our web sites (assuming that we have the license for doing so) with a command like this in our main CSS style sheet:

@font-face {
  font-family: Open Sans';
  src: url('opensans.eot'); /* IE9 Compat Modes */
  src: url('opensans.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('opensans.woff2') format('woff2'), /* Super Modern Browsers */
       url('opensans.woff') format('woff'), /* Pretty Modern Browsers */
       url('opensans.ttf')  format('truetype'), /* Safari, Android, iOS */
       url('opensans.svg#svgFontName') format('svg'); /* Legacy iOS */
}

And then use the font as you would normally in a font-family instructions.

body {
  background: #efefef;
  font-family: 'Open Sans', sans-serif;
  font-size: 16px;
  line-height: 24px;
  padding: 50px;
}

CSS Tricks has an interesting article explaining how to use web fonts.

WebFont Loader

The Web Font Loader is a joint project between Typekit and Google that provides tighter control over your fonts loadings process. Main advantage of a system like this is that you can work with fonts from different vendors and reduce the likelihood of the dreaded ‘Flash of Unstyled Content’.

Modular scales

modularscale.com and its companion SASS Module provide an easier way to incorporate the scale into you projects.

Drive before you buy

Services like Typecast.com allow you to test fonts in a fully responsive environment with your own text before you commit to using the font in your project. Until recently I thought that was not necessary and that we’d only have to test on devices. This is no longer the case, we should test as much as possible in as many devices as possible.

References

I love The Web Ahead. I think Jenn Simmons does an awesome job in selecting her guests and having meaningful and insightful conversations about the web; not just the technology but what makes the web work.

This was specially true about the typography episodes where she’s talked to people who have changed the way that I look at fonts and how we use them on the web. The podcasts (in reverse chronological order) are:

Picture elements and responsive images

Wouldn’t it be nice if we could use something like Media Queries for images? We can… it’s the picture element.

The picture element attempts to solve 4 issues / Answer 4 questions:

  • Can I serve different image sizes based on some attribute of the browser accessing the page?
  • Can I provide different images based on DPI?
  • Can I provide different image formats based on device capability? (For example, not all browsers support WebP)
  • Can I provide different images based on my art direction requirements? (full size images may be overkill for smaller devices)

The example below, taken from Opera Developer’s sitearticle on responsive images takes the extreme view of supporting all 4 use cases for responsive images.

For browser windows with a width of 1280 CSS pixels and wider, a full-shot photo with a width of 50% of the viewport width is used; for browser windows with a width of 640-1279 CSS pixels, a photo with a width of 60% of the viewport width is used; for less wide browser windows, a photo with a width that is equal to the full viewport width is used. In each case, the browser picks the optional image from a selection of images with widths of 200px, 400px, 800px, 1200px, 1600px and 2000px, keeping in mind image width and screen DPI. These photos are served as WebP to browsers that support it; other browsers get JPG.

<picture>
  <source
    media="(min-width: 1280px)"
    sizes="50vw"
    srcset="opera-fullshot-200.webp 200w,
            opera-fullshot-400.webp 400w,
            opera-fullshot-800.webp 800w,
            opera-fullshot-1200.webp 1200w,
            opera-fullshot-1600.webp 1600w,
            opera-fullshot-2000.webp 2000w"
    type="image/webp">
  <source
    sizes="(min-width: 640px) 60vw, 100vw"
    srcset="opera-closeup-200.webp 200w,
            opera-closeup-400.webp 400w,
            opera-closeup-800.webp 800w,
            opera-closeup-1200.webp 1200w,
            opera-closeup-1600.webp 1600w,
            opera-closeup-2000.webp 2000w"
    type="image/webp">
  <source
    media="(min-width: 1280px)"
    sizes="50vw"
    srcset="opera-fullshot-200.jpg 200w,
            opera-fullshot-400.jpg 400w,
            opera-fullshot-800.jpg 800w,
            opera-fullshot-1200.jpg 1200w,
            opera-fullshot-1600.jpg 1800w,
            opera-fullshot-2000.jpg 2000w">
  <img
    src="opera-closeup-400.jpg" alt="The Oslo Opera House"
    sizes="(min-width: 640px) 60vw, 100vw"
    srcset="opera-closeup-200.jpg 200w,
            opera-closeup-400.jpg 400w,
            opera-closeup-800.jpg 800w,
            opera-closeup-1200.jpg 1200w,
            opera-closeup-1600.jpg 1600w,
            opera-closeup-2000.jpg 2000w">
</picture>

Sure, this takes a lot more work to setup both in terms of preparing images of different sizes and resolutions and in terms of preparing your HTML to accomodate all your needs but we can now finally stop depending on servers to convert our images or provide a one-size-fits all solution.

ServiceWorker caching

I ran my first experiment with ServiceWorkers as part of my Athena Framework Experiment where the idea was (and still is) to cache content for offline viewing so that network becomes another layer of enhancement as we only need to be online the first time we access out content and the cache will display the content whether we are online or not.

If you use Chrome as your primary development platform you can take advantage of Push Messaging (Google Cloud Messagin) and Background notification to enhance your users’ experience but only tied to the Google echo system.

Despite the advantages I’ve decided to hold off on Push and Background Notification and concentrate on caching the content. Once the open APIs for Push and Background notification reach candidate recommendation status (meaning that there are two interoperable implementations available in the wild) I will revisit the issue.

Emphasis deep Linking

The Emphasis Library was initially developed by The New York Times as a highlighting and deep linking library. What caught my attention is that you’re not limited to single user linking; you can share the link and it will display the same highlights and annotations that you created.

Emphasis was initially developed as a jQuery plugin which made it less attractive as someone who wanted to develop a dependecy-free framework. When I revisited the plugin I had decided to use jQuery anyways and the pluging had moved away from jQuery as a dependency.

Even though I chose to make jQuery available I was still pleasantly surprised to see the code be made jQuery-free.

Highlight.js

A lot of what I write is web-related with lots of code examples for HTML, CSS and Javascript. I know for certain that I don’t want to do the highlighting by hand.

There are many code highlighting libraries available. I chose highlight.js for HTML as well as PDF generated from XML.

I love the library’s breadth of supported languages and the work it saves makes it totally worth it.

Another library worth looking at is Prism.js

Regions and Shapes

If we’ll push the envelope then I want to be able to push the envelope in terns of the technologies that will make the user experience more engaging and interactive content.

I’ve written about shapes both as a new technology and in conjunction with svg clip paths.

Shapes can provide better drop cap support (by wrapping closer to the shape of the letter) and can provide better floated text with different shapes.

Support is inconsistent and must be polyfilled in order to work accross the board. See the polyfill readme file for more information on how to use the polyfill and what browsers are supported.

Regions provide a different way to layout the content that doesn’t involve tables and doesn’t require Javascript.

OS Specific Home Screen Icons and Splash Screens

While I remain committed to keeping this project on the web, there are enhancements we can make to provide a better experience in mobile without loosing the desktop experience.

The downside is that these enhancements are platform specific. Every time we add this functionality we must do so for each browser.

iOS icons and splash screens

When iOS was first introduced one of the features that first caught my attention was the ability to save web sites to the home screen and use them as an online-only web application. I always thought that it was something only full applications or apps from larger companies could do. It wasn’t until I read the Configuring Web Applications section of the Safari Web Content Guide that I realized that it was hard work but it was doable by anyone.

We add the following elements to the head of our content page (not 100% sure if this is for every page or only for the index). The first set of resources deal with fixing the width of the device to a 1 to 1 scale window, full screen and no app bar at the top of the application.

<meta name="viewport" content="user-scalable=no, initial-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />

The second block adds the application icons that will appear in the home screen when we add the site/app. We have to add multiple icons to account for different screen size/resolution/DPI combinations available to different devices.

<!-- iOS ICONS AND START SCREENS -->
<link rel="apple-touch-icon" href="/images/misc/apple-touch-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/images/misc/apple-touch-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/images/misc/apple-touch-icon-114x114.png" />

The final step is to add the spalsh screen that will appear while the site is loading. As with the icons, we have to account for different size/resolution/DPI combinations for different devices.

<!-- iPhone/iPod Touch Portrait – 320 x 460 (standard resolution) -->
<!-- These are not all available resolutions, do your homework -->
<link rel="apple-touch-startup-image" href="/images/misc/splash-screen-320x460.png" media="screen and (max-device-width: 320px)" />

<!-- For iPad Landscape 1024x748 -->
<link rel="apple-touch-startup-image" sizes="1024x748" href="/images/misc/splash-screen-1024x748.png" media="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape)" />

<!-- For iPad Portrait 768x1004 (high-resolution) -->
<link rel="apple-touch-startup-image" sizes="1536x2008" href="/images/misc/splash-screen-1536x2008.png" media="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait) and (-webkit-min-device-pixel-ratio: 2)"/>

Windows8 application tiles

Windows 8 (in tablets and phones) allows applications to be tiled on the start screen. We can take advantage of this feature by going to buildmypinnedsite.com completing the form and download the resulting kit. We can the paste the code below on the head of our pages and upload the associated images to the server.

<-- Windows 8+ tile stuff -- Assumes all content is uploaded to server -->
<meta name="application-name" content="My Awesome Site"/>
<meta name="msapplication-TileColor" content="#e809e8"/>
<meta name="msapplication-square70x70logo" content="tiny.png"/>
<meta name="msapplication-square150x150logo" content="square.png"/>
<meta name="msapplication-wide310x150logo" content="wide.png"/>
<meta name="msapplication-square310x310logo" content="large.png"/>

Chrome on Android

Chrome takes a two-prong approach to adding web apps to the homescreen. First it asks to link to a json manifest file (in the example below I called it manifest.json

<link rel="manifest" href="manifest.json">

The manifest itself looks like this:

{
  "name": "Web Application Manifest Sample",
  "icons": [
    {
      "src": "launcher-icon-0-75x.png",
      "sizes": "36x36",
      "type": "image/png",
      "density": "0.75"
    },
    {
      "src": "launcher-icon-1x.png",
      "sizes": "48x48",
      "type": "image/png",
      "density": "1.0"
    },
    {
      "src": "launcher-icon-1-5x.png",
      "sizes": "72x72",
      "type": "image/png",
      "density": "1.5"
    },
    {
      "src": "launcher-icon-2x.png",
      "sizes": "96x96",
      "type": "image/png",
      "density": "2.0"
    },
    {
      "src": "launcher-icon-3x.png",
      "sizes": "144x144",
      "type": "image/png",
      "density": "3.0"
    },
    {
      "src": "launcher-icon-4x.png",
      "sizes": "192x192",
      "type": "image/png",
      "density": "4.0"
    }
  ],
  "start_url": "index.html",
  "display": "standalone",
  "orientation": "portrait"
}

More information on the Chrome Developers’ site

jQuery

jQuery has always been a touchy subject for me. On the one hand it is still a good library to smooth out browser idiosyncracies and to provide a common interface for developers to work. I usually chose jQuery over Dojo (even though I think Dojo is the better library) because of all the plugins available and the relative ease of implementing your own.

The problem I have is not really with jQuery but with the people who use the technology without understanding what it does, how it works and how to modify it when needed.

I tend not to use jQuery much but make it available in case there are plugins that the creator may want to use.

The two sides of jQuery

Below are 2 views on the jQUery debate. I will let you decide for yourself if this is worth it.

@zackbloom and adamfschwartz created You Might Not Need jQuery to show developers that jQuery is not the only way to achieve web effect and support older browsers. They use IE as an example, probably because older versions of IE is the most problematic of browsers

John-David Dalton, Paul Irish created a document outlining browser bugs jQuery fixes as an answer to You May Not Need jQuery. They point out that:

While the sentiment of youmightnotneedjquery is great, developers should be aware that ditching libraries, like jQuery, can easily require large amounts of research on their end to avoid bugs (even in modern browsers). The snippets provided by youmightnotneedjquery are a starting point but hardly scratch the surface of being a solid robust replacement to jQuery.

The great thing about an established library, like jQuery, is it’s hammered on by lots of talented people, transparently improved, and refined by the community. jQuery core is very careful not to bloat their codebase and does not add features or fixes without serious consideration and peer review. If it’s in jQuery that means it’s addressing real compatibility issues.

stayInApp jQuery Plugin

One of the annoyances of working on mobile browsers is that clicking on links takes you out of the full screen experience into Safari’s interface.There is a jQuery plugin designed to keep you in your web application when you click on links and, thus, preserving your application’s experience.

The Plugin only works for iOS and it takes advantage of the ability to detect when iOS is in full screen mode

I’m looking for ways to provide and equivalent functionality for Android and Windows.

Tooling and Automation

For most web-related project I’ve used Grunt as my task runner. Grunt was the first software I used to run commands like I used to do with Ant and Make in a pure Javascript environment. sometimes it gets painfully slow but nowhere near as slow as Ant used to be.

Grunt automates all the tasks that I need in a project: convert from SASS to CSS, concatenate and minnify all third party Javascript libraries and plugins, use Autoprefixer and UNCSS on the generated CSS and save it with the same name, copy all the resources needed into a distribution folder and even publish the distribution to Github’s gh-pages branch.

Gulp is similar to Grunt but it starts from a different premise. Where Grunt puts the emphasis on configuring the task to run, Gulp gives developers the flexibility to create their own tasks to work anyway they want and only enforces how these tasks connect to each other. put in another way: “Grunt focuses on configuration, while Gulp focuses on code.”

sass: {
  dev: {
    options: {
      style: 'expanded'
    },
    files: [ {
      expand: true,
      cwd: 'scss',
      src: [ '*.scss'],
      dest: 'css',
      ext: '.css'
    }]
  },
  production: {
    options: {
      style: 'compact'
    },
    files: [ {
      expand: true,
      cwd: 'scss',
      src: [ '*.scss'],
      dest: 'css',
      ext: '.css'
    }]
  }
},

The best way I’ve found to do this with Gulp is create two separate tasks, one for development and one for production. They would looks something like this:

gulp.task('sass-dev', function() {
  return gulp.src('src/styles/main.scss')
    .pipe(sass({ style: 'expanded' }))
    .pipe(gulp.dest('dist/assets/css'))
});

gulp.task('sass', function() {
  return gulp.src('src/styles/main.scss')
    .pipe(sass({ style: 'compressed' }))
    .pipe(gulp.dest('dist/assets/css'))
});

Gulp allows you to pipe commands to output of the previous command. The example below will do the following:

  • Convert the SASS files into CSS
  • Minify the CSS
  • Rename the CSS file and convert it to .min.css
  • Write the resulting file out
//declare the task
gulp.task('sass', function(done) {
  gulp.src('sass/main.scss')
    .pipe(sass({ style: 'compressed'}))
    .pipe(gulp.dest('./www/css/'))
    .pipe(minifyCss({
      keepSpecialComments: 0
    }))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(gulp.dest('./www/css/'))
    .on('end', done);
});

As you can see, each Gulp tasks does one thing and then passes its output as the input the next task.

Grunt / Gulp links and resources

Towards Subcompact Publishing

In Platforming books Craig Mod proposes a multi platform approach to book publishing anchored in the success of his Artspace Tokyo Kickstarter project.

He suggests that books should have: An open web presence with the complete book content, an iBooks version to enjoy the advanced capabilities available to the format, Kindle and PDF versions of the book with the advantages of each format and the things you can get out of it.

Then in Subcompact Publishing he proposes a departure from tradition in the digital publishing business. It advocates for a system that has/is:

  • Small issue sizes (3-7 articles / issue)
  • Small file sizes
  • Digital-aware subscription prices
  • Fluid publishing schedule
  • Scroll (don’t paginate)
  • Clear navigation
  • HTML(ish) based
  • Touching the open web

While some of these areas apply to periodical publications (magazines and such) several of these elements are applicable to a wider publishing channels.

Examples

Note that not all examples listed are books or book-like web experiences. Some, like Unnumbered Sparks, are listed because there was some aspect I thought important to highlight.

  <h3>Books and magazines</h3>
  • Offline Reader. I’m not much for paginated content but think this is an example of how to make it work. It is also built with Polymer so it’s become a good model of how this can be done
  • Artspace Tokyo by Craig Mod and Ashley Rawlings. It highlights a lot of the ethos of Subcompact Publishing and how to Platform books
  • Shape of Design by Fran Chimero. The navigation was a little hard to understand at first but once I understood the metaphor it became very easy to navigate
  • The Magazine provides a good example of what a SubCompact publication may look like. What I loved the most was t he speed of publication, how long it took to download and read and, particularly, the little link trick where clicking on a link will pop up a small window with information about the link and the giving you the option of actually going to the link

Other Online

  • Liz Danzico’s blog provides a clean and crisp interface. I particularly love the way the site (designed by Jason Santa Maria) uses white space
  • Climbing Everest presents a fully interactive experience and it draws the reader to interact with the content
  • Tokyo Otaku Mode started as a Facebook page and reached over 3 million subscribers before developing apps and how to subvert the publishing and marketing worlds
  • Unnumbered Sparks is the largest web browser I’ve ever seen. There is a Chrome instance about 10 million pixels that projects users’ interactions into the hanging structure. Every time I see this project (both the video and the material available at the Autodesk Museum in San Francisco) makes me think I’m not thinking big enough
  • Cabbibo’s website makes extensive use of WebGL and 3D web as an expressive medium. It is in the convergence of 2D and 3D where we can find the trully expressive potential of the web
  • Forest Giant and Alice in Woderland are technology demonstrations from Adobe that push the envelope of what you can do with web technologies. Unfortunately some of the CSS technologies have been caught in what I call “specification hell” with a very uncertain future (which makes me really sad)

SVG Clip Path and Shapes. An interesting alternative

We’ll borrow a play from the SVG playbook for this post. We’ll use clip path to generate masks around an image to control what the user gets to see and what shapes the image takes without changing the image itself.

We’ll look at the process and then we’ll build an e-book with examples to test if this works with iBooks (and whatever other reader you want to test with) and how can we better leverage the feature in our reflowable projects.

CSS clip-path

CSS clip-path attribute is the star of the show either in CSS, via SVG or a mix of the two of them, it will clip the image and hide portions outside the clipping region (and therefore changing the image’s visible shape) without changing the image file.

Rather than figure out the coordinates for each point in the shape or polygon I’ll be working on I chose to use Clippy, a tool by Bennett Feely. It is certainly not the only one but it is certainly the easiest to use of those I’ve found. If you use Brackets you may want to look at the CSS Shapes Editor that’s available for the editor.

For this example I took a triangle and put it on its side, the same shape in the Demosthenes example but with a different image.

The code looks like this:

See the Pen Breaking The Box — Step 1 by Carlos Araya (@caraya) on CodePen.2039

SVG Clip path

All is well and good for browsers that support the CSS clip-path property whether prefixed or not. But what happens to older browsers? Fortunately for us support for SVG is wider than the support for CSS clip path.

SO we take a two-pronged approach, we create an SVG clip path element and then we reference the SVG from our CSS.

This bit looks like this:

See the Pen Breaking The Box — Step 2 by Carlos Araya (@caraya) on CodePen.2039

CSS shapes

I’ve discussed CSS shapes in other blog posts so I won’t cover it again here. But it’s important to keep this in mind as it’ll be what will pull the components together below.

Putting it all together

We have all the components we need. It’s time to put them together. We use shapte-outside to tel the CSS engine to put the content closer to masked shape of the image.

The final code looks like this:

See the Pen Breaking The Box — Step 3 by Carlos Araya (@caraya) on CodePen.2039

Moving it to ePub and the result thereof

I had initially targeted iBooks but even within the iBooks platform, the results are inconsistent. I’m working on trying to figure out if it’s a code issue or if the different versions of iBooks really are that inconsistent with each other.

iBooks for Mac (1.1.1 (600) running on OS X 10.10.3) produces no visible result. The image is not displayed at all.

iBooks for iOS in an iPad Air 2 produces a distorted image and not the sharp triangle like the one provided for the open web.

I’m researching if this is an issue with the way I’m using clip-path, the limitations for using SVG clip path inside an XHTML document, or just that it’s not supported.

If you want to help me test the epub I created (with the cover and title for Peter Pan) is available here

Links and credits

Idea from http://demosthenes.info/blog/1007/Combining-CSS-clip-path-and-Shapes-for-New-Layout-Possibilities

Image used in this post courtesy of Craig Deakin used under a Creative Commons attribution license

image is available in codepen

Trimming the CSS fat

Trimming the CSS fat

After reading India Amos Degristling the sausage: BBEdit 11 Edition I thought I’d share my tricks for making CSS files as small as possible. While I learned these tricks as a front end developer they apply equally to creating content for e-books.

One thing that has always stopped me from fully embracing frameworks is that they use an insane amount of code and it’s really difficult to trim until I’m done with a project and, at that time, I usually don’t want to have to look at CSS for a few weeks.

In researching front end techniques I’ve discovered a few techniques to make CSS development more bearable and to cut the size of our CSS files at the same time.

The main requirement for the chosen tools is that they have both a command line tool or a grunt/gulp build system plugin.

For tools like CodeKit, a Macintosh application, or Prepros, cross platform, they must support all the tool discussed.

Both of these task runners, and the plugins that run within them, depend on Node.js and NPM. They both must be installed on your system before any of the tools discussed will work.

SASS

SASS and related libraries require Ruby and the SASS gem. Ruby is installed in most (if not all) Linux and OS X systems.

To install SASS just do gem install sass

I’ve been a fan of SASS ever since I first read about it a few years ago. It allows you to build more complex structures that you can with pure CSS.

Part of the fat trimming is the use of variables and reducing the number of redundant selector rules that we write.

I have written about SASS and some of its features

I followed it up with this post about advanced features to make CSS more manageable.

Grunt/Gulp Build System

After a long time saying I didn’t need a build system but, the more tools and techniques I’ve discovered. the harder it gets to remember the command line tools you have to use to accomplish these tasks

Grunt is the first task runner I saw and the one I still work with. It works in discrete tasks. It is very configuration heavy; the Gruntfile.js configuration file is full of instructions for how to run each task.

In the example below we define our tasks, along with the options and settings for each, and finally we define a custom task that includes all the steps we want to take.


/*global module */
/*global require */
(function () {
  "use strict";
  module.exports = function (grunt) {
    // require it at the top and pass in the grunt instance
    // it will measure how long things take for performance
    //testing
    require("time-grunt")(grunt);

    // load-grunt will read the package file and automatically
    // load all our packages configured there.
    // Yay for laziness
    require("load-grunt-tasks")(grunt);

    grunt.initConfig({
      // SASS RELATED TASKS
      // Converts all the files under scss/ ending with .scss
      // into the equivalent css file on the css/ directory
      sass: {
        dev: {
          options: {
            style: "expanded"
          },
          files: [{
            expand: true,
            cwd: "scss",
            src: ["*.scss"],
            dest: "css",
            ext: ".css"
          }]
        },
        production: {
          options: {
            style: "compact"
          },
          files: [{
            expand: true,
            cwd: "scss",
            src: ["*.scss"],
            dest: "css",
            ext: ".css"
          }]
        }
      },
     scsslint: {
        allFiles: [
          "scss/*.scss",
          "scss/modules/_mixins.scss",
          "scss/modules/_variables.scss",
          "scss/partials/*.scss"
        ],
        options: {
          config: ".scss-lint.yml",
          force: true,
          colorizeOutput: true
        }
      },

      autoprefixer: {
        options: {
          browsers: ["last 2"]
        },

        files: {
          expand: true,
          flatten: true,
          src: "scss/*.scss",
          dest: "css/"
        }
      },

      // CSS TASKS TO RUN AFTER CONVERSION
      // Cleans the CSS based on what"s used in the specified files
      // See https://github.com/addyosmani/grunt-uncss for more
      // information
      uncss: {
        dist: {
          files: {
            "css/tidy.css": ["*.html", "!docs.html"]
          }
        }
      }
    }); // closes initConfig

    // CUSTOM TASKS
    // Usually a combination of one or more tasks defined abov

    // Prep CSS starting with SASS, autoprefix et. al
    grunt.task.registerTask(
      "prep-css",
      [
        "scsslint",
        "sass:dev",
        "autoprefixer",
        "uncss"
      ]
    );
  }; // closes module.exports
}()); // closes the use strict function

Gulp is a stream oriented task runner where the emphasis is connecting (piping) the output one task to the input of the next. In the example below we create a task and then pipe the different plugins as input until the last pipe is for the destination of the product.


var cssc   = require("gulp-css-condense"),
    csso   = require("gulp-csso"),
    more   = require("gulp-more-css"),
    shrink = require("gulp-cssshrink");

gulp.task("styles", function () {
    return sass("./styles", {
        loadPath: "./vendor/bootstrap-sass/assets/stylesheets"
    }).on("error", console.warn.bind(console, chalk.red("Sass Errorn")))
        .pipe(autoprefixer())
        .pipe(combinemq())
        .pipe(cssc())
        .pipe(csso())
        .pipe(more())
        .pipe(shrink())
        .pipe(gulp.dest("./build/css"));
});

Combine Media Queries

The first optimization is to consolidate our Media Queries using Combine MQ. The idea behind this is to reduce the number of Media Queries and their associated rules.

We do this reduction first to make sure that we won’t have to run Autoprefixer and UnCSS again after reducing the number of Media Queries in our final CSS file.

There are Grunt and Gulp plugins available

AutoPrefixer

Autoprefixer helps in dealing with ‘prefix hell’ for the most part.

In their race to be first to implement a css feature, vendors added it behind a vendor-specific prefix (-webkit for Safari, Chrome and Opera, -o for Opera before they adopted Webkit, -moz for Firefox and -ms for Microsoft) to hide it for the browsers that had not adopted it or implemented differently.

Note that Autoprefixer does not handle ePub specific vendor prefixes. There are PostCSS tools that will do it for you when/if needed.

I’ve chosen not to implement these postcss plugins

That left developers having to figure out which elements had which vendor prefixes and to update them when/if the vendor finally decided to drop the prefix altogether.

Autoprefixer is a command line tool that will take care of vendor prefixes. It uses caniuse.com to determine what prefixes to apply to which element.

You can also specify how far back to go for prefixes. Examples of valid browser values:

  • last 2 versions: the last 2 versions for each major browser.
  • last 2 Chrome versions: the last 2 versions of Chrome browser.
  • > 5%: versions selected by global usage statistics.
  • > 5% in US: uses USA usage statistics. It accepts [two-letter country code].
  • Firefox > 20: versions of Firefox newer than 20.
  • Firefox >= 20: versions of Firefox newer than or equal to 20.
  • Firefox < 20: versions of Firefox less than 20.
  • Firefox <= 20: versions of Firefox less than or equal to 20.
  • Firefox ESR: the latest [Firefox ESR] version.
  • iOS 7: the iOS browser version 7 directly.

You can also target browsers by name:

  • Android for Android WebView.
  • BlackBerry or bb for Blackberry browser.
  • Chrome for Google Chrome.
  • Firefox or ff for Mozilla Firefox.
  • Explorer or ie for Internet Explorer.
  • iOS or ios_saf for iOS Safari.
  • Opera for Opera.
  • Safari for desktop Safari.
  • OperaMobile or op_mob for Opera Mobile.
  • OperaMini or op_mini for Opera Mini.
  • ChromeAndroid or and_chr for Chrome for Android (mostly same as common Chrome).
  • FirefoxAndroid or and_ff for Firefox for Android.
  • ExplorerMobile or ie_mob for Internet Explorer Mobile.

Autoprefixer is available as a command line tool, a Grunt Plugin and a Gulp Plugin

UnCSS

User-interface libraries like Bootstrap, TopCoat and so on are fairly prolific, however many developers use less than 10% of the CSS they provide (when opting for the full build, which most do). As a result, they can end up with fairly bloated stylesheets which can significantly increase page load time and affect performance. grunt-uncss is an attempt to help with by generating a CSS file containing only the CSS used in your project, based on selector testing.

From Grunt UnCSS

Uncss takes a set of HTML files, a css stylesheet and produces a new stylesheet with only those rules actually used in the HTML files. The idea is to reduce the size of the CSS being pushed to the client.

Shrinking the size of our CSS file(s) may not seem like a big deal but it becomes important when you use large libraries like Bootstrap or Zurb Foundation or when your own CSS libraries become too large to handle (special cases can be killers.)

Addy Osmani, the creator and maintainer claims that he has reduced the CSS size on a multi page Bootstrap project from over 120KB to 11KB.

UnCSS Size Reduction

There are UnCSS plugins for Grunt and Gulp available

CSSO or other minimizers

Now that we have a prefixed CSS file with only the classes we need we can look at further size reduction by doing optional compressions. I’ve chose to be somehwat conservative and choose two possible options of the many minimizers available through NPM and Grunt.

If you want to see a more detailed comparison check sysmagazine comparison of CSS and Javascript processors

CSS Optimizer

We will first run the CSS file through CSS Optimizer. What brought this plugin to my attention is that it not only does the traditional minimizations. According to the documentation it can perform:

  • Safe transformations:
    • Removal of whitespace
    • Removal of trailing ;
    • Removal of comments
    • Removal of invalid @charset and @import declarations
    • Minification of color properties
    • Minification of 0
    • Minification of multi-line strings
    • Minification of the font-weight property
  • Structural optimizations:
    • Merging blocks with identical selectors
    • Merging blocks with identical properties
    • Removal of overridden properties
    • Removal of overridden shorthand properties
    • Removal of repeating selectors
    • Partial merging of blocks
    • Partial splitting of blocks
    • Removal of empty ruleset and at-rule
    • Minification of margin and padding properties

As with the other tools, there are Grunt and
Gulp plugins available.

CSS Shrink

While CSSO may have gotten as small as possible, I’d rather make sure. That’s where CSS Shrink comes in.

You may be wondering why is Carlos being so obsessive with reducing the size of his CSS files?

Fair question. Here’s the answer:

Images are loaded asynchronously. We can load JavaScript asynchronously if we so choose. CSS is the only component of your web page that only loads synchronously and most browsers will block rendering the page until all your CSS downloads. That’s why it pays for it to be the smallest we can make it and combined the CSS into as few files as possible.

CSS Shrink provides that second level of compression, just to make sure we didn’t miss anything 🙂

As usual, plugins for Grunt and Gulp are available.

CodeKit/Prepros: One tool to rule them all

I know that some developers would rather not use command line tools. There are applications that provide almost equivalent functionality.

CodeKit (Mac only) and Prepros (Mac and Windows)

The screenshot below shows Codekit’s UI with a project open

Codekit Project UI

The second screenshopt shows SCSS compilation options on the right side of the screen.

Codekit Compilation Options

I own a copy of Codekit more from curiosity than from any actual use but realize that it may be better for developers who are not comfortable with command line interfaces.

Code Repository and Additional Goodies

I’ve created a Github Repository to go along with the ideas in this article. It’s a drop-in structure for a new project and it’s also an opinionated skeleton for new projects.

Issues, comments and Pull Requests are always welcome