Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

February 24 2014

14:47
Tags: Article

February 20 2014

21:48
Tags: Article
Sponsored post
soup-sponsored
05:36
Reposted bySchrammelhammelMrCoffeinmybetterworldkonikonikonikonikoniambassadorofdumbgroeschtlNaitliszpikkumyygittimmoe

February 18 2014

16:33
Tags: Article
14:48
Tags: Article

February 17 2014

16:09
Tags: Article

February 13 2014

21:34

Multiple Simultaneous Ajax Requests (with one callback) in jQuery

Let's say there is a feature on your website that only gets used 5% of the time. That feature requires some HTML, CSS, and JavaScript to work. So you decide that instead of having that HTML, CSS, and JavaScript on the page directly, you're going to Ajax that stuff in when the feature is about to be used.

We'll need to make three Ajax requests. Since don't want to show anything to the user until the feature is ready to go (plus they all kinda rely on each other to work right) we need to wait for all three of them to be complete before proceeding.

What's the best way to do that?

Ajax calls in jQuery provide callbacks:

$.ajax({
  statusCode: {
    url: "/feature",
    success: function() {
      // Ajax success
    }
  }
});

Or the "Deferred" way, this time using a shorthand $.get() method:

$.get("/feature/").done(function() {
  // Ajax success
});

But we have three Ajax requests we're needing to perform, and we want to wait for all three of them to finish before doing anything, so it could get pretty gnarly in callback land:

// Get the HTML
$.get("/feature/", function(html) {

  // Get the CSS
  $.get("/assets/feature.css", function(css) {
    
    // Get the JavaScript
    $.getScript("/assets/feature.js", function() {

       // All is ready now, so...

       // Add CSS to page
       $("<style />").html(css).appendTo("head");

       // Add HTML to page
       $("body").append(html);

    });

  });

});

This successfully waits until everything is ready before adding anything to the page. So by the time the user sees anything, it's good to go. Perhaps that makes some of you feel nauseated, but I've done things that way before. At least it makes sense and works. The problem? It's slow.

One request ... wait to be done ... another request ... wait to be done ... another request ... wait to be done ... go.

It would be faster if we could do:

All three requests in parallel ... wait for all three to be done ... go.

We can use a bit of Deferred / Promises action to help here. I'm sure this is some JavaScript 101 stuff to some of you but this kind of thing eluded me for a long time and more complex Promises stuff still does.

In our simple use case, we can use jQuery's $.when() method, which takes a list of these "Deferred" objects (All jQuery Ajax methods return Deferred objects) and then provides a single callback.

$.when(

  // Deferred object (probably Ajax request),

  // Deferred object (probably Ajax request),

  // Deferred object (probably Ajax request)

}.then(function() {

  // All have been resolved (or rejected), do your thing

});

So our callback-hell can be rewritten like:

$.when(
  // Get the HTML
  $.get("/feature/", function(html) {
    globalStore.html = html;
  }),

  // Get the CSS
  $.get("/assets/feature.css", function(css) {
    globalStore.css = css;
  }),

  // Get the JS
  $.getScript("/assets/feature.js")

).then(function() {

  // All is ready now, so...

  // Add CSS to page
  $("<style />").html(globalStore.css).appendTo("head");

  // Add HTML to page
  $("body").append(globalStore.html);

});

Another use case: mustard cutting

My use-case example above is a 5% feature. Keep the page lighter for the 95% of users who don't use the feature, and have it be a relatively quick add-on for those that do.

Another situation might be a cut-the-mustard situation where you add in additional features or content to a page in certain situations, as you decide. Perhaps do a matchMedia test on some media queries and determine the device's screen and capabilities are such that you're going to include some extra modules. Cool, do it up with some parallel Ajax calls!


Multiple Simultaneous Ajax Requests (with one callback) in jQuery is a post from CSS-Tricks

Tags: Article

February 12 2014

21:51

Sticking Around

I'll be danged if I can find it but someone tweeted to @CodePen the other day something like: "Is it worth it for me to go PRO? Or are you going to up and shut down one day like so many startups do?" It was a hard question to answer, and not because I'm not sure what the answer is.

It was hard because saying something like "Don't worry, we aren't going away" is a weak and lame answer. Like I looked up how to respond in Corporate Social Media for Dummies!

So instead of a lame answer, I made a note to write up my feelings on the matter. This is that attempt.

CodePen, nor any of the other things I work on, is a fly by night operation. My plan is to build a business by building and maintaining a good product that is useful to people - and do right by those people.

There will be bugs. We'll screw up sometimes. But we'll always be working toward a better product and a better business. One that the Archiveteam doesn't need to worry about.

I know the only way to prove this is by proving it over time, so day by day we'll be doing that. But I can tell you this isn't some new revelation for me. Over many years I've focused the things I work on. I've stopped working on so many projects and have avoided picking up any new ones. I outsource as much as I can. Long-term work on a just a few things is what feels right to me. I wrote on The Pastry Box Mediocre ideas, showing up, and persistence.

Don’t get distracted by some other idea and prance away to that tomorrow. Keep doing it until you’ve done everything you set out to do and everyone and their mom knows it.

Persistence is kinda my thing.


You're excited about it now, but what happens when the passion fades and you get bored of a project? Historically that tends to not happen to me for the things I work on that I care deeply about. But I suppose it could, in which case I would take care that the project is in good shape to be sustained with minimal effort and otherwise in good hands.

What if you sell it? There are no plans for that and I can't see it happening anytime soon. It could happen someday though, and my top priority would be ensuring a healthy future for it. I have been a part of an acquisition before with Wufoo and now, many years later, Wufoo is still going strong.


I was compelled to finally write this as I read Protecting Against Link Rot While Embracing the Future by Tim Murtaugh on A List Apart. Tim lays out a plan to keep embedded code demos healthy in the event that CodePen were to go away. He is 100% right and I'm glad A List Apart is approaching things in that smart future-proof way. It was just weird to read about the theoretical demise of my own project when I feel so strongly about it's own future-proof-ness. So here we are =).


Sticking Around is a post from CSS-Tricks

Tags: Article

February 10 2014

16:15

Test for Support of SVG as img

Browser support for SVG isn't quite as simple as yes or no. In addition to some quirks on how that support plays out, it depends on how that SVG is being used. One common way is right within an image tag, like <img src="image.svg" alt="description">.

How can you detect if a browser supports SVG use in that way?

It's one thing to just know which browsers do. The only real danger zones are IE 8- and Android 2.3. You could do user agent detection, and while I wouldn't want to get too judgey about that, it's generally a bad idea.

I was looking at SVGeezy, a mini JavaScript plugin specifically for helping with SVG-as-img fallbacks. Of course, in order for it to work, it needs to do a feature detect. In the source code, it's a simple a one liner:

supportsSvg: function() {
  return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1");
}

I had never seen document.implementation.hasFeature ever before, so I asked around a bit, as it seemed a little too good to be true for something I'd never even heard of. Most documentation out there is pretty generic and suggest great browser support, making me even more skeptical.

The deal is: it's pretty much useless. It almost always returns true for everything. Except, apparently, in the case of SVG-as-img, when it's correct. As a skeptic, I went about creating a test to see if this was really true.

The first thing I did was check how Modernizr detects it, as the go-to source for feature detects. Important note here: Modernizr's default SVG test (Modernizr.svg) is not testing SVG-as-img support, it's testing SVG support as an <object> or <embed>. Just be aware of that when using it for fallbacks. Test the right thing (they have tests for all the ways you can use SVG).

They have a test specifically for SVG-as-img that was like this:

Modernizr.addAsyncTest(function () {
  var img = new Image();

  img.onerror = function () {
    addTest('svgasimg', false);
  };
  img.onload = function () {
    addTest('svgasimg', img.width == 1 && img.height == 1);
  };

  // 1px x 1px SVG; must be base64 or URI encoded for IE9... base64 is shorter
  img.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==';
});

This creates an new image element, injects a Data URI of a 1x1 SVG image then either waits for it to fail or load correctly.

Obviously different than the hasFeature test, so I created a Pen that showed the results of both methods. Then I tested in all kinds of different browsers. A mixture of those which are known to support SVG-as-img and those that do not. In all cases, the results were identical. Weird, but pretty cool!

The original Modernizr test is what they call an "async" test, meaning it relies upon callback functions to give an answer. Modernizr generally prefers "sync" tests in which as soon as the test is defined it has the right answer.

So, after talking about it with the Modernizr team, it is now the default test for SVG-as-img. It's not quite out in a release yet, so for now you'd have to just run it.

Modernizr.addTest('svgasimg', document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Image', '1.1'));

I'll update this post (and the version we run on CodePen) as soon as it's out.

Thanks to Patrick Kettner for overseeing it getting into Modernizr, Stu Cox for the feedback and OKing the replacement of his original method, Ben Howdle for knowing about the cool hasFeature() and using it in SVGeezy and Mike Taylor for verifying it's usefulness.

Oh, and if you you detect the browser doesn't support SVG-as-img, you'll want to flip out the src for an image format that is supported. Probably the-same-image.png either automatically based on a naming convention or selectively based on a data-* attribute.


Test for Support of SVG as img is a post from CSS-Tricks

Tags: Article

February 07 2014

17:29

Draggable Elements That Push Others Out Of Way

Aside from a few esoteric tricks involving stuff like the resize handle on textareas, draggable elements is JavaScript territory on the web. E.g. click on element, hold down mouse button, drag mouse cursor, element drags with the mouse, release mouse button to release element. Or the touch equivalents. Fortunately this is well-tread territory. Time tested tools like jQuery UI offer Draggable (and other similar methods) to make this easy.

But recently in trying to achieve a certain effect (see title of this article) I couldn't quite get jQuery UI to do it how I wanted. But I got it done and here's how.

I was trying to recreate the effect in the sidebar in Keynote where you can drag to rearrange slides. Here's the finished effect:

You can get super close with some really basic jQuery UI configuration. We're using the Sortable method here. This is specifically for sorting lists, which is what we are doing, which is a bit like using both Draggable and Droppable.

$(".all-slides").sortable({
  
  axis: "y",
  revert: true,
  scroll: false,
  placeholder: "sortable-placeholder",
  cursor: "move"

});

On some basic HTML like this:

<div class='all-slides'>

  <div class='slide'>Slide</div>
  <div class='slide'>Slide</div>
  <div class='slide'>Slide</div>

  <!-- etc -->

The "placeholder" in the configuration is an element (with the provided class name) that gets inserted amongst the slides where that slide would drop if you released the mouse button right now. You can style that however you want with CSS, so I made it look like the blue-line-on-the-left like Keynote.

The trouble here is we don't get that "push out of the way" effect we're going for. The placeholder just shows up immediately. Originally I tried to solve it by using a @keyframes animation to expand the height of the placeholder from 0 to the slide height and then stay there will fill-mode. That works for the appearance of the placeholder, but jQuery UI just rips that placeholder out of the DOM when it goes away which didn't allow for a graceful exit.

So some deeper trickery was in order. Fortunately, after bemoaning the difficulty on Twitter, AJ Kandy found a handy example doing just what I needed.

Bear with me, this gets a bit complicated:

  1. Loop through all the slides
  2. Create a duplicate of each slide
  3. Position the slide directly on top of the original
  4. Hide it
  5. Save a reference to the slide it was duplicated from

Then you initiate the Sortable method on just the originals. Then when you start dragging a slide:

  1. Hide all the original slides
  2. Reveal the clones
  3. As you drag around, the originals will be re-arranging invisibly
  4. After they do that, animate the clones to those new positions

When the dragging stops:

  1. Make sure all the clones are in the right final position
  2. Swap out the visibility again, revealing the originals

It took a good amount of time to wrap my head around and tinker with to get just right. In my example I use psuedo-elements to number the slides, so there is a bit of code for that as well. Here it is all together.

$(".slide").each(function(i) {
  var item = $(this);
  var item_clone = item.clone();
  item.data("clone", item_clone);
  var position = item.position();
  item_clone
  .css({
    left: position.left,
    top: position.top,
    visibility: "hidden"
  })
    .attr("data-pos", i+1);
  
  $("#cloned-slides").append(item_clone);
});

$(".all-slides").sortable({
  
  axis: "y",
  revert: true,
  scroll: false,
  placeholder: "sortable-placeholder",
  cursor: "move",

  start: function(e, ui) {
    ui.helper.addClass("exclude-me");
    $(".all-slides .slide:not(.exclude-me)")
      .css("visibility", "hidden");
    ui.helper.data("clone").hide();
    $(".cloned-slides .slide").css("visibility", "visible");
  },

  stop: function(e, ui) {
    $(".all-slides .slide.exclude-me").each(function() {
      var item = $(this);
      var clone = item.data("clone");
      var position = item.position();

      clone.css("left", position.left);
      clone.css("top", position.top);
      clone.show();

      item.removeClass("exclude-me");
    });
    
    $(".all-slides .slide").each(function() {
      var item = $(this);
      var clone = item.data("clone");
      
      clone.attr("data-pos", item.index());
    });

    $(".all-slides .slide").css("visibility", "visible");
    $(".cloned-slides .slide").css("visibility", "hidden");
  },

  change: function(e, ui) {
    $(".all-slides .slide:not(.exclude-me)").each(function() {
      var item = $(this);
      var clone = item.data("clone");
      clone.stop(true, false);
      var position = item.position();
      clone.animate({
        left: position.left,
        top: position.top
      }, 200);
    });
  }
  
});

And the demo:

See the Pen Slide Rearranger like Keynote by Chris Coyier (@chriscoyier) on CodePen.

Bonus feature: the slides get a class when being drug the pulsates their size, like in Keynote.

Packery & Dragabilly

David DeSandro has some projects you may have heard of all about rearranging boxes on the web, like Masonry and Isotope. He also has one called Packery which uses an algorithm to pack boxes into spaces. Along with another project of his, Dragabilly, you can create the same effect where dragging an element moves others out of the way. The single-axis nature of our demo is easy work for it.

David forked my demo and made it work with those tools, and it's a good bit less code:

See the Pen Slide Rearranger like Keynote - with Packery and Draggabilly by David DeSandro (@desandro) on CodePen.


Draggable Elements That Push Others Out Of Way is a post from CSS-Tricks

Tags: Article

February 05 2014

15:01

Design Systems: Building for the Future

The following is a guest post by Ara Abcarians (@itsMeAra). Ara is a UX Engineer at Media Temple and worked on the recent redesign of mediatemple.com. Here he shares the ideas, approach, and tech behind that work.

Full disclosure: Media Temple has long given me free hosting. I even use an affiliate link when I link to Media Temple, which I earn a little money from. But I'm not publishing for some backroom shoulder-rubbing reason. I'm publishing it because they did a good job with the redesign, Ara wanted to write it, and I think we call can benefit from his insights on an important large-scale redesign.

Now Ara.


The modern web design and development process is rapidly evolving, and responsive websites are quickly becoming the norm. Frameworks like Bootstrap and Foundation are showing us the value of creating robust systems of components to make building things on the web faster, better, and easier.

About a year ago, I joined LA-based web hosting and cloud services company (mt) Media Temple as a UX Engineer. Tasked with leading the front-end development of (mt)’s website redesign, I took the opportunity to slow down and revisit my front-end development approach. That’s how I realized that the way I was previously building large websites was a little flawed. I wanted to share some of my learning process and shed some light on the high-level approach I chose to take while learning about and building a design system.

But what exactly is a design system?

At FOWA 2013 in London, Mark Otto described a design system as “everything that makes up your product” (see his entire talk here: Build your own Bootstrap).

Everything? Everything. From typography, layouts and grids, colors, icons, components and coding conventions, to voice and tone, style-guide and documentation, a design system is bringing all of these together in a way that allows your entire team to learn, build, and grow.

At first, I wasn’t sure whether I should start building something custom or begin with an existing framework like Bootstrap. Ultimately, I decided against using the latter for a few reasons:

  • We already had a custom design. When I started at Media Temple, the visual designs for the new site were just about complete. If I used a framework, I’d have to significantly customize it to fit our designs.
  • I wanted to establish coding conventions and structure based on my team’s preferences. Again, I’d have to spend a ton of time re-naming classes or reorganizing things to fit our needs.

The amount of time I would spend essentially gutting the framework didn’t seem worth it. I felt like building our own framework would be beneficial to us in the long run, more maintainable, and, as a bonus, would be an incredible learning experience. It also helped that I had the time to do it, and an entire team that was excited to be a part of it.

Establish Top Level Goals

When rebuilding a legacy website, you're presented with the opportunity to improve a lot of things. Before I began any actual development, I started out by establishing some top level goals:

  • Organization: A messy codebase can become a nightmare to work with. Making sure we had a well thought-out structure and approach was very important.
  • Maintainability: Over time, there are going to be new developers jumping in to fix bugs and add features. We needed to have proper guidelines and conventions to make it easy for people to do things correctly.
  • Responsiveness: Having seen a steady rise in mobile/tablet traffic, it was very important to make the experience platform-agnostic.
  • Scalability: The company will grow in the future, and so should its website. Creating promotional pages and/or new product pages should no longer be an unpleasant (and near impossible) task.

My “a-ha” moment

With the top level goals in mind, I started doing extensive research. I began by reading about HTML semantics and front-end architecture and discovered the benefits of building flexible modules, not pages. That was my “a-ha” moment.

Previously, while building large websites, I was used to dividing the work by page templates. I’d tackle a set of related templates, then move on to another set. The problem with this approach is that, if the communication between the team isn’t exceptional, you’ll end up with many similar — sometimes identical — modules and components marked up and styled in different ways. If you don’t spend the extra time refactoring them, your codebase will turn into an absolute mess.

I decided to study two excellent — but different — projects very deeply: InuitCSS by Harry Roberts and Bootstrap by Mark Otto and Jacob Thornton, and I quickly realized the next step I needed to make was to establish guidelines around how our HTML, CSS, and JavaScript should be coded and what our overall front-end approach should be.

Coding Conventions and Guidelines

Inspired by Idiomatic HTML, CSS Guidelines, and Idiomatic JavaScript, I began adapting these into our own set of coding guidelines. In the process, I discovered and adopted an interesting naming methodology called BEM (Block, Element, Modifier). It’s essentially a clever way of naming your CSS classes to make them more meaningful and simpler to understand.

Our slightly modified convention is:

  • .block {} - Represents the main component.
  • .block-elementName {} - A child element that helps make up the component as a whole.
  • .block--modifier {} - A modifier class that is used to alter the state or appearance of the component.

Here is an example of an alert box using this approach:

/* Main 'alert' component */
.alert {}

  /* Sub-components that make up the 'alert' */
  .alert-text {}
  .alert-close {}

/* Modifiers for various styles of the 'alert' */
.alert--warning {}
.alert--error {}
.alert--success {}
.alert--info {}

I also finalized a set of tools to help us along the way, including LESS for our CSS pre-processing needs, and Grunt to compile our LESS files and compress, minify, and concatenate our code.

Developing Base Styles

An example of base styles Base HTML elements courtesy of HTML Ipsum

Similar to InuitCSS and Bootstrap, I created a primary stylesheet called mt-global.less which would import all of the site styles together and create the final mt-global.css file. In an effort to keep things organized, I created a few folders:

  • core - This would hold our custom variables and mixins.
  • vendor - For vendor utilities used, such as LESSHat and REMixins.
  • base - For all of the underlying base styles like typography, colors, and structure.

I started out with normalize.css, adapting it as needed, and continued styling general elements such as headings, links, lists, form elements, and tables.

Identify and Build Components

With the base styles in place, it was time to take a look at the website as a whole, and start identifying individual components. I started building a custom grid system based on the grid used for the designs. From there I continued on to common elements like buttons, call to action links, hero units, and navigation.

An example of the featurette component

As I was building components, I started figuring out ways to abstract common styles into reusable objects, similar to the media object. InuitCSS was a huge help here as it contains tons of useful objects. All of these styles were put into folder called components.

Identify and Build Modules

Breakdown of homepage modules

With most of the components ready to go, it was time to use these building blocks to create each page’s various modules. I created another folder called modules, and began putting them together, starting with global modules like the site header, footer, and hero unit.

Establishing Patterns

An example of the preliminary style-guide Sections of the preliminary style-guide.

As I was building components and modules I started to plug them into a style guide using the Style-Guide Boilerplate. The result was a single point of reference for any team member interested in learning how to contribute to the website. Once the whole team had access to the style guide, building page templates was a breeze. It was just a matter of mixing and matching modules, and extending or customizing them when necessary.

In Conclusion

Building a design system is a long process filled with trial and error. Established frameworks can save you weeks of development time, but if you’ve built your web project with a framework that has since gone through many releases, maintaining it can be difficult. Do you upgrade your codebase with each release? What if you have customized it so much that updating it isn’t even an option?

If you have the opportunity to rebuild a site from the ground up, building a custom solution solves a lot of issues: It helps establish a custom tailored system enabling your entire team to quickly and easily learn how to contribute to your project; it’s built by you and specifically for your company’s needs; and, most importantly, it’s built for the future. Without being tied down to another project’s evolution and direction, it’s free to scale at your companies pace.

Research. Build. Learn. Repeat.
- John Polacek

Above all, it was an incredible learning experience and a great source of pride for our team. I encourage everyone to study the many resources available about design systems and the ever changing web design process.


Design Systems: Building for the Future is a post from CSS-Tricks

Tags: Article

February 04 2014

22:44

Force Quit a Tab in Google Chrome

Normally Google Chrome is very good at allowing you to close misbehaving tabs. Each tab is like its own little universe so if it crashes it doesn't affect other tabs. That's the whole "multi process" thing that Chrome brought to the WebKit party and was part of the reason for the Blink break-up.

But let's say there is a tab that just won't close. You click the closing ✕ and nothing happens. Try using ⌘W to close it, nothing. File > Close Tab, nothing.

It happens to me maybe once a week as I'm browsing around different Pens on CodePen. Perhaps there is an infinite-loop in the JS or some other madness and the tab just won't crash, it just hangs.

You can get that tab closed by using the Task Manager.

Window > Task Manager

Find the tab in the list. They are listed by <title> so hopefully you either recognize it or can drag the window wide enough to see the name in the tab itself. Then click the End Process button in the lower right. That'll close that tab no matter how stubborn it's being (in my experience).


Force Quit a Tab in Google Chrome is a post from CSS-Tricks

Tags: Article

February 01 2014

22:57

International box-sizing Awareness Day

It's February 1st today, which I've decided to declare International box-sizing Awareness Day. In honor of, you guessed it, the most humble and undersung, yet awesome and useful CSS property: box-sizing.

The date corresponds to Paul Irish's post where he introduced the concept of using it on every single element on the page. We've talked about it around here a few times as well.

Here it is, in all it's glory:

*, *:before, *:after {
  -webkit-box-sizing: border-box; 
  -moz-box-sizing: border-box; 
  box-sizing: border-box;
}

The default value for box-sizing is content-box, which is what we are overriding here. There is also a padding-box value but... kinda useless if you ask me. We'll get to what this means shortly.

Notice we're using the * selector to select all elements, as well as making pseudo elements use the same model, which otherwise wouldn't be selected by the * selector alone.

Here's the browser support situation. "-" = "this version and down". "+" = "this version and up".

*, *:before, *:after {
  /* Chrome 9-, Safari 5-, iOS 4.2-, Android 3-, Blackberry 7- */
  -webkit-box-sizing: border-box; 

  /* Firefox (desktop or Android) 28- */
  -moz-box-sizing: border-box;

  /* Firefox 29+, IE 8+, Chrome 10+, Safari 5.1+, Opera 9.5+, iOS 5+, Opera Mini Anything, Blackberry 10+, Android 4+ */
  box-sizing: border-box;
}

In the fairly near future we won't need any prefixes at all for it, but I like to just leave that kind of thing to Autoprefixer.

Why all the HOO-RAH?!

It makes working with boxes so super duper much nicer.

When you set the width of an element, that's the width that it is. If you set the width to 25%, it will take up 1/4 of the horizontal space available in its parent element. That's it.

That's not always the case. With the default box-sizing, as soon as an element has either padding or border applied, the actual rendered width is wider than the width you set.

Actual width = width + border-left + border-right + padding-left + padding-right

The math is bad enough, but when combined with percentages (or any mixed units, really) the result is impossible to do in your head and, more importantly, ends up being some useless number that you can't do anything with.

You might think of it this way: with box-sizing: border-box the padding and border press their way inside the box rather than expand the box. The result is a box the exact width you set it to be and can count on.

Columns is a particularly useful case, but this comes in useful all the time and becomes one of those things that just makes CSS development better.


Remember to read Paul's original post which covers some more ground like performance (don't worry about it), jQuery (don't worry about it), and third-party content (easy to fix).

Happy International box-sizing Awareness Day! Maybe next year we can get organized about it and all wear groovy square sunglasses or something.


International box-sizing Awareness Day is a post from CSS-Tricks

Tags: Article

January 30 2014

20:27

Boxes That Fill Height (Or More) (and Don’t Squish)

It's hard to sum up all the awesome that is flexbox in a little ol' blog post. Although we gave it a shot here. Here, let's just try and focus on one thing that flexbox solves very nicely: the ability to have an arbitrary set of boxes fill up all the available height of a parent box. And not only that, but expand beyond that if needed (not squish them to fit).

By "box", I just mean block level element. Div, section, article, whatever.

By default those boxes height is determined by the content inside them. They will stack on top of each other. Their parent boxes height might also be determined by their height combined, but it could be different (e.g. it's set explicitly or it's something variable like the browser window). If the parent box has a larger height, there will just be empty space below.

Can't we force the boxes to split up the space evenly amongst that space? We can with flexbox.

Left: default; Right: what we wanna do

Say the HTML is like:

<section class="fill-height-or-more">
  <div>
    <!-- stuff -->
  </div>
  <div>
    <!-- stuff -->
  </div>
  <div>
    <!-- stuff -->
  </div>
</section>

Then we kick off flexbox with the parent box:

.fill-height-or-more {
  display: flex;
}

and make the boxes up-and-down (column) rather than left-and-right (row) as is the default:

.fill-height-or-more {
  display: flex;
  flex-direction: column;
}

With just that, it will look no different than it did if we did nothing. But now we apply the flex property to the children and they will fill the space:

.fill-height-or-more > div {
  /* these are the flex items */
  flex: 1;
}

Annnnd done =).

As a detail here, flex: 1; is the same as saying flex: 1 1 auto; It is shorthand for three different properties:

flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;

Just so happens that giving them the ability to grow on an equal basis the most common need so flex: 1; is a nice way to write that.

One of the nice things about flexbox is this will work with an arbitrary number of boxes. Could be a single box! Could be 100 boxes! Doesn't matter. If there is extra room, the space will be divided and filled. If not, no big deal.

In a pre-flexbox world, we might have tried to know/find out how many boxes there were, and then set their heights with percentages. That works to fill extra space, but if there were too many boxes, you'd get squished. That's another nice thing about flexbox, it won't squish those boxes to the point of them not being able to fit their content. So...

Left: if we were to use percentages; Right: Normal desired behavior

If we wanted to take this a step further, we could use flexbox to center the content within those boxes too (!). This is where people get mad at CSS though. Vertical centering is kinda hard. Even with flexbox here, we'll need to make each of those flex item children we have into flex containers as well. Then use an internal wrapper which becomes the flex item we center. So yeah, an extra element still.

<section class="fill-height-or-more">
  <div>
    <div>
      <!-- stuff -->
    </div>
  </div>
  ...
.fill-height-or-more > div {
  /* flex item */
  flex: 1;

  /* and a flex container */
  display: flex;
}

Then to center it, we make the direction up-and-down again (column) and use another flexbox property, justify-content, to center it.

.fill-height-or-more > div {
  flex: 1;

  display: flex
  justify-content: center;
  flex-direction: column;
}

This is where the reference guide comes in handy... finding out which property does what quickly.

Then we get this:

On one hand that makes sense. In order to center something you kinda need a single element in which to center. On the other hand, if these things were table cells, vertical-align would have worked there which doesn't need the extra element. Thus more CSS finger wagging.

Anyway, demo!

See the Pen Boxes That Fill Height (or more) by Chris Coyier (@chriscoyier) on CodePen.

Browser Support

I've only used the latest syntax here in this post. Current versions of IE, Chrome, Opera support it just like that. Near-future versions of Firefox and Android will be supporting it just like that as well. Safari and iOS support the new syntax, just with -webkit- prefixes. As always, Can I Use has the whole story.

It's understandable that you might need to go back a bit further. Firefox 27, IE 10, iOS 6, and Safari 6 are pretty legit browser support targets and all those use some variation of the older syntax, sometimes prefixed and sometimes not.

Just our little example looks like this when as fleshed out as it can be for support:

.fill-height-or-more {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -moz-box-orient: vertical;
  -moz-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
} 

.fill-height-or-more > div {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -ms-flex: 1;
  flex: 1;
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  -moz-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -moz-box-orient: vertical;
  -moz-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
}

Yeesh. My recommendation? Write it in the modern syntax like I have above and let Autoprefixer deal with it, which not only deals with the prefixing but the older syntax as well.

Video Screencast

Might as well hey? I published it here and I'll embed it also:


Oh and just for the record, the real-world scenario that brought this on for me was this page.


Boxes That Fill Height (Or More) (and Don’t Squish) is a post from CSS-Tricks

Tags: Article

January 28 2014

17:34

Play and Pause Buttons for YouTube and Vimeo Videos (via Their APIs)

Sometimes you just need to start a video playing by some user interaction on the page other than clicking right on that video itself. Perhaps a "Play Video" button of your own creation lives on your page and you want to start that video when that button is clicked. That's JavaScript territory. And if that video is a YouTube or Vimeo video, we'll need to make use of the APIs they provide. No problem.

For these examples, we'll assume you've already picked out a video and you're going to put it on the page in an

For YouTube

1. Make sure the iframe src URL has ?enablejsapi=1 at the end

Like this:

<iframe src="//www.youtube.com/embed/FKWwdQu6_ok?enablejsapi=1" frameborder="0" allowfullscreen id="video"></iframe>

I also put an id attribute on the iframe so it will be easy and fast to target with JavaScript.

2. Load the YouTube Player API

You could just link to it in a <script>, but all their documentation shows loading it async style, which is always good for third-party scripts, so let's do that:

// Inject YouTube API script
var tag = document.createElement('script');
tag.src = "//www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

3. Create a global function called onYouTubePlayerAPIReady

This is the callback function that the YouTube API will call when it's ready. It needs to be named this.

function onYouTubePlayerAPIReady() {

}

It's likely you have some structure to your JavaScript on your page, so generally I'd recommend just having this function call another function that is inside your organizational system and get going on the right track right away. But for this tutorial, let's just keep it soup-y.

4. Create the Player object

This is the object that has the ability to control that video. We'll create it using the id attribute on that iframe in our HTML.

var player;

function onYouTubePlayerAPIReady() {
  // create the global player from the specific iframe (#video)
  player = new YT.Player('video', {
    events: {
      // call this function when player is ready to use
      'onReady': onPlayerReady
    }
  });
}

Another callback!

5. Create the "player ready" callback and bind events

We named this function when we created the player object. It will automatically be passed the event object, in which event.target is the player, but since we already have a global for it let's just use that.

Here we bind a simple click event to an element on the page with the id #play-button (whatever custom button you want) and call the player object's playVideo method.

function onPlayerReady(event) {
  
  // bind events
  var playButton = document.getElementById("play-button");
  playButton.addEventListener("click", function() {
    player.playVideo();
  });
  
  var pauseButton = document.getElementById("pause-button");
  pauseButton.addEventListener("click", function() {
    player.pauseVideo();
  });
  
}

All Together Now

And that'll do it! Here's a demo:

See the Pen Play Button for YouTube by Chris Coyier (@chriscoyier) on CodePen.

I used a little SVG templating in there for the buttons just for fun.

For Vimeo

1. Make sure the iframe src URL has ?api=1 at the end

<iframe src="//player.vimeo.com/video/80312270?api=1" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen id="video"></iframe>

I also put an id attribute on the iframe so it will be easy and fast to target with JavaScript.

2. Load the "froogaloop" JS library

The Vimeo player API actually works by sending commands through postMessage right to the iframe. You don't need the froogaloop library to do that, but postMessage has some inherent complexities that this library (by Vimeo themselves) makes way easier. Plus it's only 1.8kb so I'd recommend it.

<script src="froogaloop.min.js"></script>

3. Create the player object

var iframe = document.getElementById('video');

// $f == Froogaloop
var player = $f(iframe);

We target the iframe by the id attribute we added. Then we create the player using the special froogaloop $f.

4. Bind events

All we have to do now is call methods on that player object to play and pause the video, so let's call them when our play and pause buttons are clicked.

var playButton = document.getElementById("play-button");
playButton.addEventListener("click", function() {
  player.api("play");
});

var pauseButton = document.getElementById("pause-button");
pauseButton.addEventListener("click", function() {
  player.api("pause");
});

All Together Now

That'll do it for Vimeo. Here's a demo:

See the Pen Pause / Play Buttons for Vimeo Videos by Chris Coyier (@chriscoyier) on CodePen.


You can do much more with the APIs for both of these services. It can be pretty fun, just dive in!


Play and Pause Buttons for YouTube and Vimeo Videos (via Their APIs) is a post from CSS-Tricks

Tags: Article

January 25 2014

19:53

Thought Process of a Front End Problem

"Your fonts render weirdly on Opera mobile."

Thanks for taking the time to let me know. Can you send me a screenshot so I can see?

Wow that is weird. I use custom fonts, via @font-face and a third party service. This isn't just a matter of the custom font failing and falling back to a different font, which may look weird because of different spacing and such. It appears that:

  • Some characters are rendered in the correct @font-face font
  • Some characters are rendreed in the fallback font
  • Some characters fail to render at all (box-with-x thing)

First, I know there are two different kinds of Opera mobile browsers. "Opera Mini" and "Opera Mobile". I should bone up on that quick.

{Googles "opera mini and opera mobile".}

Find some weird forums posts, click around a little, end up at a decent blog post that explains the difference.

In Opera Mini, the Opera Presto browser engine is located on a server. In Opera Mobile, it is installed on your phone.

The person who emailed about the font problem said it was Opera Mobile, so I'll test that first. But as I imagine everyone in the world doesn't know there are even different types of Opera browsers on mobile devices, I'll test the other if I need to. It actually kinda seems like Mini might be the problem as I can imagine a server-side rendering engine might do some special shenanigans like "only wait X seconds" for third-party resources or something like that, leaving a font file half-downloaded.

I wonder if I can replicate this myself.

I have a Kindle Fire around here somewhere, but that thing has that weird Amazon Silk browser on it and I don't think it allows me to download any other browser. I have a Nexus 7 I bought for testing on Android, but I can never get it to turn on. I got it to once but I had to take the back cover off and basically stab it with a knife until it worked. I haven't gotten around to throwing it into a volcano yet.

Maybe I should buy a new Android device for testing that is more well reviewed. Or maybe a device that has Opera on it by default. Oh well, no time for that right this second.

Maybe BrowerStack can emulate it for me? Ooooh it can, nice.

Bingo.

Now at least I can replicate the problem. That way if I think of something to change I can test the results. Although unfortunately there are are zero DevTools built into this emulator so it can't help me figure out the problem by itself.

Maybe there is an emulator I can run myself? Ooooh there is! Good on ya, Opera.

While I wait for this to download I'll Google around a little. Hmmmm, a post by Mr. Zeldman that is extremely similar. His solution was to use a third-party service (e.g. Typekit), essentially because they are in the business of getting this right. Or use a trusted tool like the Font Squirrel generator to ensure the best quality files and syntax.

Unfortunately I'm already using a third-party service (Cloud Typography), so I don't have much control there. I'm going to keep working on this myself, but I'm going to fire off an email to them describing the issue. Most importantly so they know about it, but also because they might have a fix up I could try.

{Types up email and sends.}

OK that emulator finished downloading.

It works. Cool. The download site made it seem like you could use Opera Dragonfly to debug from this, but in reading the docs for it, it seems like you can only do that for local sites and it's a bit of a weird setup. Plus now I look and in the version of Opera I have it's basically the Chrome DevTools now, not Dragonfly. So I'd have to find some old version of Opera to download to do this? Uckgh I feel like this rabbit hole is getting too deep.

Maybe I should check out another site that is also using the same third-party service as CSS-Tricks. We're using Cloud Typography on CodePen also to serve font, but totally different fonts, so that should be an interesting test too.

Ah ha! Janky in the same kinda way.

That's the strongest lead yet. It must just be how Cloud Typography does things. Unfortunately I have fairly little control over it, because they provide the files to you and they are intentionally rather obfuscated.

I do have control on whether I serve the stylesheet at all or not though. I know I'm not ready to ditch custom fonts all together, because I like them and they generally work fine, but maybe I can ditch them somehow just for Opera Mobile.

It's always a little tempting to try User Agent Detection. Opera provides docs on what they do there and I could always test. But I'm hesitant. Not only is it theoretically bad, but every time I've ever done it I've regretted it because it either didn't catch what I wanted it too, caught too much, or both. Plus, I'm not finding any good-looking PHP code snippets for specifically this and I'm a better ballet dancer than RegEx writer. Do I want to head down that road again? Not really.

I could look into analytics a bit here also to see the scope of this problem. Here's the top 10 browsers here:

"Opera Mobile" doesn't show up anywhere in the list, even looking at all 189 represented. It must either be lumped in with "Opera" (some portion of 1%) or "Opera Mini" (some portion of 0.1%). Mobile in its entirety is around 3% on this site, which includes iOS and Android which are far more popular. So I think this is affecting probably around 0.25% of people.

I really want to fix this, but with the super small numbers involved, the lack of good testing tools, the out-of-my-hands bits, and the potential dangers of some fixes, I feel rather helpless. I guess I'll just wait and see what the provider has to say.


This is just a story of what it's like being a front-end developer. It's not even about fonts so much as the struggle, the process, and the choices.


Thought Process of a Front End Problem is a post from CSS-Tricks

Tags: Article

January 23 2014

16:11

Single Page Refresh for Client Side Data Server Side

We recently covered how you could get client-side information and make it available server side. Do real tests on the client, like measure browser window width and do feature tests. Then save that data to a Cookie. Then next time the page is loaded, you'll have that data in a cookie.

I quite like that technique, and use it, but what if you really want to be using that info on the first page a user sees? You might need to do a page refresh, but you have to be safe about it.

You might be tempted to just test if the cookie is set, and if not, set it and reload. PHP and jQuery here used just for demo purposes, but you can (and I have) done this in any different backend language and with or without a front end library.

<?php if (isset($_COOKIE['_clientInfo'])) { ?>

  <script>
    // Do tests, set cookie

    location.reload(true); // true means don't use cache
  </script>

<?php } else { ?>

  <!-- Proceed normally, using cookie data to make more choices -->

<?php } ?>

This is quite dangerous though. Because:

  1. A user might disallow cookies on purpose.
  2. A user might be using a browser that doesn't allow cookies.

From what I can tell, iOS app that include a WebView need to specifically turn on the ability to accept cookies, meaning the default is to not allow them.

If either of those above two things are true, you'll get into an infinite-reload situation, which is very bad.

The trick here is to approach it this way:

  1. Test if the cookie is present server-side.
  2. If the cookie isn't set, set it on the client side with the data you want.
  3. Then do another test, client side, if the browser supports cookies or not.
  4. If it does support cookies and you haven't used it yet (cookieUsed), then refresh.

Here's a complete document that shows how it could go down:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset='UTF-8'>
  <title>Client Info In Cookie</title>
  <script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
</head>

<body>

    <?php if (isset($_COOKIE['_clientInfo'])) { ?>

      <p>Use the data as you see fit!</p>

      <?php
          $json = $_COOKIE['_clientInfo'];
          $obj = json_decode(stripslashes($json));
          echo "<p>Browser Width: " . $obj->{'browserWidth'} . "</p>";
          echo "<p>Browser Height: " . $obj->{'browserHeight'} . "</p>";
          echo "<p>Flexbox Support: " . $obj->{'flexboxSupport'} . "</p>";
          echo "<p>SVG Support: " . $obj->{'SVGSupport'} . "</p>";
      ?>

      <p>You can use it server-side OR client-side.</p>

      <script>
        // You could use the plugin here too, but whatever this is lighter
        var clientInfo = JSON.parse('<?php echo $_COOKIE['_clientInfo']; ?>');

        output = "<p>Browser Width: " + clientInfo.browserWidth + "</p>";

        $("body").append(output);
      </script>

    <?php } else { ?>

      <!-- LOAD TESTING LIBRARY, only load when testing -->
      <script src="js/modernizr.js"></script>

      <!-- COOKIE LIBRARY -->
      <script src="js/jquery.cookie.js"></script>

      <!-- CREATE COOKIE -->
      <script>

        var clientInfo = {
          browserWidth: $(window).width(),
          browserHeight: $(window).height(),
          flexboxSupport: Modernizr.flexbox,
          SVGSupport: Modernizr.svg
        };

        var cookieVal = JSON.stringify(clientInfo);

        // was using document.cookie, this plugin worked better
        $.cookie("_clientInfo", cookieVal, {
          expires: 7
        });
      </script>

      <!-- RELOAD PAGE if supported and not used -->
      <script>
        var cookiesEnabled = navigator.cookieEnabled ? true : false;
        if (cookiesEnabled) {
          location.reload(true);
        }
      </script>

      <p>Make sure you serve useful content here as well.</p>

    <?php } ?>

</body>

</html>

Live demo here.

You may need to mess around with that structure a little to suit your needs. The important part being that you serve useful content no matter what the result is. The worst that can happen then is that you keep trying to set a cookie that will never get set for those users in no-cookie environments. You make the call on how acceptable that is.

You could do more robust testing with something like Detector.


Single Page Refresh for Client Side Data Server Side is a post from CSS-Tricks

Tags: Article

January 20 2014

23:04

Changing Between Spaces and Tabs in Sublime Text

Sublime Text is pretty dang good at making it easy to switch between using tabs and spaces to indent your code. More importantly, it makes it easy to adjust the indentation of code that doesn't match your preference. I thought I'd put this together for reference, as there is a particular sequence of steps for some of the transitions that needs to be followed.

The first step is making sure your User Preferences are how you like them.

I prefer spaces, so my settings are like this:

{
  // other stuff

  "tab_size": 2,
  "translate_tabs_to_spaces": true,

   // more other stuff
}

Adjust to your liking there.

You can override these settings on any given file, from the bottom right.

The bottom right corner is where you can see the current settings for the open document.

This is also headquarters for fixing up a document that isn't how you like it.

Changing from Tabs to Spaces (Same Level of Indentation)

Here's a document that is in tabs right now. I can tell because I've selected the text and there are dashes in the white space not dots. Dashes are tabs, dots are spaces. Also, in the bottom right, I can see it says "Tabs Size: 2".

You can see that those Tabs are 2 spaces wide. Assuming I want to switch to spaces and I'm happy with 2 spaces per tab, I just select "Convert Indentation To Spaces" from that menu.

And I'm good to go for that case.

Changing from Tabs to Spaces (Different Level of Indentation)

Let's say a straight conversion from tabs to spaces isn't going to do it for me. Say the tab level is set to 6 spaces per tab, and I want to convert to spaces, but only 2 spaces per indentation. The trick here is to adjust the spacing while in tabs first, then convert.

Changing From Spaces to Spaces (Different Level of Indentation)

What if you have a file that is in spaces how you like it, but it's using 4 spaces instead of 2? Sublime Text can still help here. You use the ability of tabs to be of variable length. So first convert to tabs, adjust the width, then switch back to spaces.

Changing From Spaces to Tabs

I think we're getting the hang of this now. You can do any of this in the reverse direction if you prefer tabs.


I think you can extrapolate other switching scenarios from there.

I don't think there is any scenario that you can't adjust to your liking this way. If you're caught manually adjusting indentation (that is consistent within itself), stop, you can figure out a way to fix it with settings.

If you want to discuss tabs vs. spaces below, go for it, but I can tell you I really don't care. I mostly care that any particular project is consistent about it and enforces it.

.editorconfig

Also worth mentioning: There is a thing called EditorConfig. You put a file in the root of your project called .editorconfig. If someone opens that project in an editor that supports it, those settings will be honored. There is one for SublimeText.

The file might look something like:

# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false


Changing Between Spaces and Tabs in Sublime Text is a post from CSS-Tricks

Tags: Article

January 16 2014

16:24

CSS Animation Tricks: State Jumping, Negative Delays, Animating Origin, and More

The following is a guest post by Zach Saucier. Zach cooks up some pretty inspiring animations over on CodePen. I couldn't be happier that he wanted to share some of the tricks he uses to create them, especially because they are things we all strive for: efficiency, reusability, practicality, and speed.

I've fallen into the habit of creating CSS animations in my free time, inspired by things I come across during the day. To create the animations as I imagine them using as few elements as possible, I've found some tricks to make CSS do things you might not know it could do. I'd like to share them with you.

#1) Jump to another state mid-animation

CSS animation makes it easy to transition properties to a new value over time. They also have the ability to jump properties to a new value virtually instantly. The trick is to use two keyframes with a very small difference, around .001% works well.

@keyframes toggleOpacity {
  50% { opacity: 1; } /* Turn off */
  50.001% { opacity: 0.4; }

  /* Keep off state for a short period */

  52.999% { opacity: 0.4; } /* Turn back on */
  53% { opacity: 1; }
}

The following is an extreme example of this, toggling opacity and a text-shadow to mimic a flickering billboard light.

See the Pen No Vacancy 404 CSS Only by Chris Coyier (@chriscoyier) on CodePen.

#2) Negative animation delays

A positive animation delay is where the animation waits a certain amount of time to begin. A negative animation delay starts the animation immediately, as if that amount of time has already gone by. In other words, start the animation at a state further into the animation cycle. This allows animations to be reused across several elements, given all that needs changing is the timing.

Here is an example of that where each circle begins immediately at a different state in the animation cycle:

See the Pen Circle Snake by Zach Saucier (@Zeaklous) on CodePen

#3) Proportional animations

I try to make everything that I put into production be as responsive as possible, including my animations. Responsiveness for CSS animations is not possible for all animations I have created, but sometimes it is, using percentages and other relative units.

In many of my animations, I use elements like circles and squares which need the a proportional width and height. You might think I need to use fixed width & height values to keep them that way, but that's not the case! I am able to create them using a percentage width, zero height, and percentage padding. The padding-bottom is the trick to keep it proportional to the width, like this:

.container {
  position: relative;
  display: block;
  width: 100%;
  height: 0;
  padding-bottom: 100%;
}

You can see this in practice on the following demo by changing the size of the window it is in. The demo also makes use of negative animation delays.

See the Pen Responsive CSS bars by Chris Coyier (@chriscoyier) on CodePen.

#4) Changing transform-origin mid-animation

While working on one of my animations, I was surprised to find out that not only can transformation-origin be changed mid-animation, it is also animatable! In the example below, this allows us to create one animation using rotations on different axes instead of using four separate animations.

See the Pen Change transformation-origin mid animation by Zach Saucier (@Zeaklous) on CodePen

The downside to this trick is that you can't use animation-mode: forwards; for only a part of an animation. This means that we have to re-position the element to an equivalent of its state before applying the change in transformation-origin. In the above example, this is done by using translates to mimic the rotation's effects. However, this technique can get tedious on more complex examples, as seen here.

#5) Negative transform-origins

You are able to set a negative transform-origin, which is useful for things like creating circular movement paths. Instead of specifying specific translate and rotation values using one element to create circular animations as Lea Verou describes, we can do it much more simply by using negative transform-origin values in addition to a second element or pseudo-element (one element if we want the element to rotate as well as move in a circular path). By using varying values of a negative transform origin, we can reuse the same animation for multiple elements while still retaining circular motion for each.

See the Pen CSS Circular Motion Technique by Zach Saucier (@Zeaklous) on CodePen.

#6) Box shadow magic

For animations of simple no-content shapes, box-shadow is quite useful. The box-shadow property can create multiple borders around elements. That idea, combined with some displacement, can create new animatable "elements" out of no additional HTML elements. This enables us to create the following animation, which appears to be six circular elements rotating circularly, but is in fact one element with some offset box-shadow shapes.

See the Pen Single element color loader by Zach Saucier (@Zeaklous) on CodePen

Sadly, percents are not supported by any box-shadow properties so they are not as easily responsive as a native HTML element. However they can still be changed manually in an animation or by using transform:scale(n) on the actual HTML element which they are a part of.

#7) Using pseudo-elements

Similarly with box-shadows, pseudo elements can be used to add more content to the appearance of a single element. They can have separate animations from their parent, their own box-shadows, and are very similar to being child elements of without the HTML markup. This let's us create amazing single element creations like the one below.

See the Pen Single Element gif Recreation by Zach Saucier (@Zeaklous) on CodePen

In the example, all of the large circles around the middle flashing circle, as well as two of the smaller circles on the rim (opposite from each other) are box-shadows on the main element. The other two small circles are part of a pseudo-element's box-shadow and the ring made of dashes is an SVG applied as a background on the other pseudo element.


Some other things to note

Use transforms when you can

Transforms perform better than their non-transform counterparts as Paul Irish has shown (also). Primarily this means using scale and translate over changing the dimensions or top/left values.

Transforms also allow for more responsive design, allowing things such as scale to be used relative to their original size, as is shown in this animation by Amos.

Not using transforms can also cause problems that are hard to catch. For example, in this animation of mine the elements were being colored incorrectly in Chrome although the values themselves were correct. After switching it to use transforms all my problems were solved.

z-index can cause problems

I probably spend more time fixing z-index issues with my animations more than any other issue. Z-indexes are handled differently from vendor to vendor. In animations, the primary difference is that Mozilla does not animate z-index values, they have elements jump from one z-index to the next, whereas vendors like webkit do animate the z-index value.

Another thing to note is that if one wants their pseudo elements to appear behind their parent element, the pseudo element must have a negative z-index and the parent cannot have a stacking other than the default, which means you can't apply a z-index or anything else that takes the parent out of its natural stacking context.

One last trick dealing with z-index is one that deals with opacity. Whenever an element is given an opacity other than the default "1", it gains its own stacking context. For more information on this, check out Philip Walton's post

Get inspired

Whether it's something you see in the real world, an interesting web page that you find online, part of a video intro, a gif, or something else entirely, find things that you think may be possible to create and try to do so!

I have found that not looking at how the original author created it enables me to learn, to create it in a unique style, and sometimes even do it in a more efficient manor. Even if I end up failing at my original intention, I always become more comfortable with or learn more about the language I'm using. Often times I have something to show for it, even if it's not as grand as I would had originally hoped. Other times I'm completely surprised by how awesome my creation is when I didn't even mean for it to be!

I hope that this article helps you construct more awesome creations, even if you learned nothing from the specific techniques!


CSS Animation Tricks: State Jumping, Negative Delays, Animating Origin, and More is a post from CSS-Tricks

Tags: Article

January 15 2014

16:12

When to use target=”_blank”

Anchor links1 may have a target attribute which controls what happens when that link is clicked. One of the possible values of that attribute is _blank, which tells the browser to open a new window (or tab, if that's the user's preference) when that link is clicked.

This used to be "invalid" in HTML (maybe only XHTML?) but people used it anyway since it worked. It's now perfectly valid in HTML5. But are there good reasons to do so?

A Bad Reason: Because you like it that way.

Like it or not, target="_blank" is a change in default behavior. Links opening within the same page is the default behavior (as if the link had target="_self" on it).

Perhaps you've developed a personal taste for opening all links in new windows/tabs. That's wonderful for you, but it is safe to assume most users are most comfortable with the default behavior. And thus less comfortable with your forcing of a different behavior.

If it's an internal tool just for you, do whatever you want. If other people use the site, leave it be.

It is also worth noting that users can force a link to open in a new window/tab by [Meta Key]-clicking a link. That means both behaviors are available to them for links. That also means that if you like opening new tabs, you can, and you don't have to impart that behavior on anyone else.

By using target="_blank", only that behavior is available.

A Bad Reason: Just because you want users to never leave your page.

Branding branding branding! Eyeballs baby. Metrics. ENGAGEMENT.

Other sites should have normal-style links, but our site is special. Our site is more important and should never be left behind.

A Bad Reason: "Internal" links and "External" links are different.

We'll have "internal" links (links that point to our own site) behave normally, but "external" links (links that point to other sites) open in a new window/tab.

This is related to the above two reasons, only perhaps worse. You understand that normal style links are ideal, but if that means a user leaves your site, you're willing to break that ideal.

I've heard from a lot of people that this is "a convention." As in the way it's supposed to be done. It's not.

A Bad Reason: The link is to a PDF

Or any other type of non-web resource. Why should that be so different? You can still use the back button to come back from it. If you want to help users download it without actually opening it, that's a worthy UX goal but can be approached differently. For starters, using the download attribute.

A Bad Reason: My client wants it that way

I get the "I don't want to pick this fight" thing, since we only have so much energy. But it's weird this has to be a fight at all. If they don't trust you with this, what do they trust you about?

I might approach it like this:

The default behavior is for links to open normally. There are some reasons why we might want to break that behavior, and we can go over those, but for most links we don't. We don't want to force our desires on users and potentially frustrate them for such a small thing. We want our users to feel good about us.

And hopefully your calm and educated approach will help your client feel good about you.

A Bad Reason: It's on an infinite-scroll page

Infinite scrolling is tricky. It can be good UX in one sense because it can deliver content without interruption. It can be bad UX if not handled well. Coming "back" to an infinite scroll page should take you to where you left off in most cases. Handling that tricky problem is your job. Just forcing links to open in new tabs so that problem never comes up is avoiding your job.

A Good Reason: There is user-initiated media playing

For instance: music, video, a podcast...

The user started it. Moving pages would stop it. At that point, either have links open in new tabs or ask them if they are sure they want to leave the page. At that point you are trying to do right by them and have them not leave their place.

We've covered this idea before here. If the media is playing, handle links in a special way. When the media isn't playing, links are in their normal state.

Although as I say that, I check YouTube, and they don't bug you about it2 when changing videos.

A Good Reason: The user is working on something on the page, that might be lost if the current page changed.

Perhaps a user is writing something. Or arranging something. Doing any kind of work. Clicking a link and changing pages can be a heart-pounding, awful moment on the web. Did I just lose everything I was doing?

Even if you do something to ensure they don't lose that work, putting someone through that panic may as well be avoided.

I think of CodePen where users are often writing code. We do several things to help:

  • Links that go to other pages that are explicitly "learn more" style links (e.g. [?]), that you only see while interacting with the editor, open in a new tab.
  • Normal links (e.g. links in the footer) have normal behavior, but we detect if you have unsaved changes in the editor and prompt you to save them before you leave.
  • If you do leave to another site (or your browser crashes), we save the state of the editors in localStorage so you don't lose work.

Checkout is another case here. Of course you don't want to lose customers during their checkout process. A link to something like "shipping information" should be openable without them losing their place in checkout.

"Reading an article", in my opinion, doesn't qualify here. Since it's (generally) so easy to get back to (most browsers even scroll down to where you were), there is no risk of real loss, and readers are really skimmers anyway.

A Good Reason: Some technologically obscure point

I'm building an email where people in Outlook Kangaroo 2009 Enterprise Edition need to open it but links need to have target="blank" on them otherwise they open in the sidebar viewing panel and ...

Fine.

Tech

In case you have to...

Forcing user to verify they want to leave page:

window.onbeforeunload = function() {
  return "Two buttons will be below this message asking if user wants to stay on this page or leave.";
}

Drama

I realize I've been pretty opinionated here. This is one of those topics where everyone has an opinion. Feel free to share those opinions of course but lets keep things cool and focus on situations, solutions, and data if we can.


1 <form>s can have target="_blank" too. I would think it's a more uncommon use case, but the same type of thinking in this article would hold true.

2 If you choose another video you go right to it. But in that case I wonder if that was a UX choice or an advertising choice. If you're half-way through a video, click to another video (say by accident) then click the back button right away, your place is lost. Perhaps having as little friction transitioning from video to video is important for them, but it would be nice if they offered a bit of help there. Perhaps a small arrow beneath the timeline that was like a "You've watched this video this far before" link.


When to use target=”_blank” is a post from CSS-Tricks

Tags: Article

January 13 2014

17:01

Myth Busting: CSS Animations vs. JavaScript

The following is a guest post by Jack Doyle, author of the GreenSock Animation Platform (GSAP). Jack does a lot of work with animations in the browser and has discovered that the generic opinion that "CSS is faster" just isn't true. It's more than that, as well. I'll let him explain.

Once upon a time, most developers used jQuery to animate things in the browser. Fade this, expand that; simple stuff. As interactive projects got more aggressive and mobile devices burst onto the scene, performance became increasingly important. Flash faded away and talented animators pressed HTML5 to do things it had never done before. They needed better tools for complex sequencing and top-notch performance. jQuery simply wasn't designed for that. Browsers matured and started offering solutions.

The most widely-acclaimed solution was CSS Animations (and Transitions). The darling of the industry for years now, CSS Animations have been talked about endlessly at conferences where phrases like "hardware accelerated" and "mobile-friendly" tickle the ears of the audience. JavaScript-based animation was treated as if it was antiquated and "dirty". But is it?

As someone who's fascinated (bordering on obsessed, actually) with animation and performance, I eagerly jumped on the CSS bandwagon. I didn't get far, though, before I started uncovering a bunch of major problems that nobody was talking about. I was shocked.

This article is meant to raise awareness about some of the more significant shortcomings of CSS-based animation so that you can avoid the headaches I encountered, and make a more informed decision about when to use JS and when to use CSS for animation.

Lack of independent scale/rotation/position control

Animating the scale, rotation, and position of an element is incredibly common. In CSS, they're all crammed into one "transform" property, making them impossible to animate in a truly distinct way on a single element. For example, what if you want to animate "rotation" and "scale" independently, with different timings and eases? Maybe an element is continuously pulsing (oscillating scale) and you'd like to rotate it on rollover. That's only possible with JavaScript.

See the Pen Independent Transforms by GreenSock (@GreenSock) on CodePen

In my opinion, this is a glaring weakness in CSS but if you only do simpler animations that animate the entire transform state at any given time, this won't be an issue for you.

Performance

Most comparisons on the web pit CSS animations against jQuery since it is so pervasive (as if "JavaScript" and "jQuery" were synonymous) but jQuery is widely known to be quite slow in terms of animation performance. The newer GSAP is also JavaScript-based but it's literally up to 20x faster than jQuery. So part of the reason JavaScript animation got a bad reputation is what I call the "jQuery factor".

The most frequently cited reason for using CSS for animation is "hardware acceleration". Sounds yummy, right? Let's break it down into two parts:

GPU involvement

The GPU is highly optimized for tasks like moving pixels around and applying transform matrices and opacity, so modern browsers try to offload those tasks from the CPU to the GPU. The secret is to isolate the animated elements onto their own GPU layers because once a layer is created (as long as its native pixels don't change), it's trivial for the GPU to move those pixels around and composite them together. Instead of calculating every single pixel 60 times per second, it can save chunks of pixels (as layers) and just say "move that chunk 10 pixels over and 5 pixels down" (or whatever).

Side note: It's not wise to give every element its own layer because GPUs have limited video memory. If you run out, things will drastically slow down.

Declaring your animations in CSS allows the browser to determine which elements should get GPU layers, and divvy them up accordingly. Super.

But did you know you can do that with JavaScript too? Setting a transform with a 3D characteristic (like translate3d() or matrix3d()) triggers the browser to create a GPU layer for that element. So the GPU speed boost is not just for CSS animations - JavaScript animation can benefit too!

Also note that not all CSS properties get the GPU boost in CSS animations. In fact, most don't. Transforms (scale, rotation, translation, and skew) and opacity are the primary beneficiaries. So don't just assume that if you animate with CSS, everything magically gets GPU-juiced. That simply isn't true.

Offloading calculations to a different thread

The other part of "hardware acceleration" has to do with being able to use a different CPU thread for animation-related calculations. Again, this sounds great in theory but it doesn't come without costs, and developers often overestimate the benefits.

First of all, only properties that don't affect document flow can truly be relegated to a different thread. So again, transforms and opacity are the primary beneficiaries. When you spin off other threads there's overhead involved with managing that process. Since graphics rendering and document layout eat up the most processing resources (by FAR) in most animations (not calculating the intermediate values of property tweens), the benefit of using a separate thread for interpolation is minimal. For example, if 98% of the work during a particular animation is graphics rendering and document layout, and 2% is figuring out the new position/rotation/opacity/whatever values, even if you calculated them 10 times faster, you'd only see about a 1% speed boost overall.

Performance comparison

The stress test below creates a certain number of image elements (dots) and animates them from the center to random positions around the edges using random delays, creating a starfield effect. Crank up the number of dots and see how jQuery, GSAP, and Zepto compare. Since Zepto uses CSS transitions for all of its animations, it should perform best, right?

See the Pen Speed Test: GSAP vs Zepto (CSS Transitions) vs jQuery by GreenSock (@GreenSock) on CodePen

The results confirm what is widely reported on the web - CSS animations are significantly faster than jQuery. However, on most devices and browsers I tested, the JavaScript-based GSAP performed even better than CSS animations (by a wide margin in some cases, like on the Microsoft Surface RT GSAP was probably at least 5 times faster than the CSS transitions created by Zepto, and on the iPad 3 iOS7 transforms were significantly faster when animated with GSAP instead of CSS transitions):

Animated properties Better w/JavaScript Better w/CSS top, left, width, height Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS 6), iPad 3 (iOS7), Samsung Galaxy Tab 2, Chrome, Firefox, Safari, Opera, Kindle Fire HD, IE11 (none) transforms (translate/scale) Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS7), Samsung Galaxy Tab 2, Firefox, Opera, IE11 iPad 3 (iOS6), Safari, Chrome
Exactly how much "better"? The original version of the test had a frames-per-second counter for quantifiable results, but it quickly became apparent that there's no truly accurate way to measure FPS across browsers especially with CSS animations, and certain browsers were reporting misleading numbers, so I removed it. You can easily gauge relative performance, though, by cranking up the number of dots, switching among engines, and watching how things perform (smooth movement, steady timing and dot dispersion, etc.). After all, the goal is to have animations look good.

Interesting things to note:

  • When animating top/left/width/height (properties that affect document flow), JavaScript was faster across the board (GSAP, not jQuery).
  • A few devices seemed highly optimized for transforms whereas others handled top/left/width/height animations better. Most notably, the older iOS6 was much better with CSS-animated transforms, but the newer iOS7 flip-flopped and now they are significantly slower (I blogged about it here).
  • There's a substantial lag in the initial animation startup with CSS animations as the browser calculates layers and uploads the data to the GPU. This also applies to JavaScript-based 3D transforms, so "GPU acceleration" doesn't come without its own costs.
  • Under heavy pressure, CSS transitions were more likely to spray out in bands/rings (this appears to be a synchronization/scheduling issue, possibly due to them being managed in a different thread).
  • In some browsers (like Chrome), when there were a very high number of dots animating, it completely killed the opacity fade of the text, but only when using CSS animations!

Although well-optimized JavaScript is often just as fast if not faster than CSS animations, 3D transforms do tend to be faster when animated with CSS, but that has a lot to do with the way browsers handle 16-element matrices today (forcing conversion from numbers to a concatenated string and back to numbers). Hopefully that'll change, though. In most real-world projects, you'd never notice the performance difference anyway.

I'd encourage you to do your own testing to see which technology delivers the smoothest animation in your particular project(s). Don't buy the myth that CSS animations are always faster, and also don't assume that the speed test above reflects what you'd see in your apps. Test, test, test.

Runtime controls and events

Some browsers allow you to pause/resume a CSS keyframes animation, but that's about it. You cannot seek to a particular spot in the animation, nor can you smoothly reverse part-way through or alter the time scale or add callbacks at certain spots or bind them to a rich set of playback events. JavaScript provides great control, as seen in the demo below.

See the Pen Impossible with CSS: controls by GreenSock (@GreenSock) on CodePen

Modern animation is very much tied to interactivity, so it's incredibly useful to be able to animate from variable starting values to variable ending ones (maybe based on where the user clicks, for example), or change things on-the-fly but declarative CSS-based animation can't do that.

Workflow

For simple transitions between two states (i.e. rollovers or expanding menus, etc.), CSS Transitions are great. For sequencing things, however, you generally need to use CSS keyframe animations which force you to define things in percentages, like:

@keyframes myAnimation {
  0% {
    opacity: 0;
    transform: translate(0, 0);
  }
  30% {
    opacity: 1;
    transform: translate(0, 0);
  }
  60% {
    transform: translate(100px, 0);
  }
  100% {
    transform: translate(100px, 100px);
  }
}
#box {
   animation: myAnimation 2.75s;
}

But when you're animating, don't you think in terms of time rather than percentages? Like "fade up the opacity for 1 second, then slide to the right for 0.75 seconds, and bounce down to a rest 1 second later". What happens if you spend hours crafting a complicated sequence in percentages, and then the client says "make that part in the middle 3 seconds longer"? Ouch. You'd need to recalculate ALL of the percentages!

Usually building animations involves a lot of experimentation, especially with timing and eases. This is actually where a seek() method would be quite useful. Imagine building out a 60-second animation piece-by-piece and then finessing the final 5 seconds; you would need to sit through the first 55 seconds every time you want to see the results of your edits to the last parts. Yuck. With a seek() method, you could just drop that into place during production to skip to the part you're working on, and then remove it when you're done. Big time-saver.

It is becoming increasingly common to animate canvas-based objects and other 3rd-party library objects but unfortunately CSS animations can only target DOM elements. That means that if you invest a lot of time and energy in CSS animations, it won't translate to those other types of projects. You'll have to switch animation tool sets.

There are a few more workflow-related conveniences that are missing in CSS Animations:

  • Relative values. Like "animate the rotation 30 degrees more" or "move the element down 100px from where it is when the animation starts".
  • Nesting. Imagine being able to create animations that can get nested into another animation which itself can be nested, etc. Imagine controlling that master animation while everything remains perfectly synchronized. This structure would promote modularized code that is much easier to produce and maintain.
  • Progress reporting. Is a particular animation finished? If not, exactly where is it at in terms of its progress?
  • Targeted kills. Sometimes it's incredibly useful to kill all animations that are affecting the "scale" of an element (or whatever properties you want), while allowing the rest to continue.
  • Concise code. CSS keyframe animations are verbose even if you don't factor in all the redundant vendor-prefixed versions necessary. Anyone who has tried building something even moderately complex will attest to the fact that CSS animations quickly get cumbersome and unwieldy. In fact, the sheer volume of CSS necessary to accomplish animation tasks can exceed the weight of a JavaScript library (which is easier to cache and reuse across many animations).

Limited effects

You can't really do any of the following with CSS animations:

  • Animate along a curve (like a Bezier path).
  • Use interesting eases like elastic or bounce or a rough ease. There's a cubic-bezier() option, but it only allows 2 control points, so it's pretty limited.
  • Use different eases for different properties in a CSS keyframe animation; eases apply to the whole keyframe.
  • Physics-based motion. For example, the smooth momentum-based flicking and snap-back implemented in this Draggable demo.
  • Animate the scroll position
  • Directional rotation (like "animate to exactly 270 degrees in the shortest direction, clockwise or counter-clockwise").
  • Animate attributes.

Compatibility

CSS-based animation doesn't work in IE9 and earlier. Most of us hate supporting older browsers (especially IE), but the reality is that some of us have clients who require that support.

Browser prefixes are necessary for many browsers, but you can leverage preprocessing tools to avoid having to manually write them out.

Conclusion

Are CSS animations "bad"? Certainly not. In fact, they're great for simple transitions between states (like rollovers) when compatibility with older browsers isn't required. 3D transforms usually perform very well (iOS7 being a notable exception), and CSS animations can be very attractive for developers who prefer putting all of their animation and presentation logic in the CSS layer. However, JavaScript-based animation delivers far more flexibility, better workflow for complex animations and rich interactivity, and it often performs just as fast (or even faster) than CSS-based animation despite what you may have heard.

When compared to jQuery.animate(), I can understand why CSS Animations were so appealing. Who in their right mind wouldn't jump at the chance to get a 10-fold performance boost? But it's no longer a choice between jQuery and CSS Animations; JavaScript-based tools like GSAP open up entirely new possibilities and wipe out the performance gap.

This article isn't about GSAP or any particular library; the point is that JavaScript-based animation doesn't deserve a bad reputation. In fact, JavaScript is the only choice for a truly robust, flexible animation system. Plus, I wanted to shed some light on the frustrating parts of CSS animations (which nobody seems to talk about) so that you can ultimately make a more informed decision about how you animate in the browser.

Will the Web Animations spec solve things?

The W3C is working on a new spec called Web Animations that aims to solve a lot of the deficiencies in CSS Animations and CSS Transitions, providing better runtime controls and extra features. It certainly seems like a step forward in many ways, but it still has shortcomings (some of which are probably impossible to overcome due to the need for legacy support of existing CSS specifications, so for example, independent transform component control is unlikely). That's a whole different article, though. We'll have to wait and see how things come together. There are definitely some smart guys working on the spec.


Myth Busting: CSS Animations vs. JavaScript is a post from CSS-Tricks

Tags: Article
Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
Could not load more posts
Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
Just a second, loading more posts...
You've reached the end.
(PRO)
No Soup for you

Don't be the product, buy the product!

close
YES, I want to SOUP ●UP for ...