Dienstag, 27. Mai 2014

SVG `text` and Small, Scalable, Accessible Typographic Designs




CSS-Tricks





SVG `text` and Small, Scalable, Accessible Typographic Designs



Let's say you designed something with custom fonts that was a little bit fancy. Perhaps a certain word is positioned between the ascenders of another word below it. Some text is kerned out below to match the width of that same word.


This is something we might tell a graphic designer switching from print to web to avoid. It's too finicky. Too much touchy, unscalable absolute positioning. Too much risk from different font rendering behavior.


But with inline SVG, we can do it, and do it well.



SVG <text>


The big "trick" here is that SVG has a <text> element that is just that: text. Not outlines of text, just regular ol' selectable, accessible web text.


<svg xmlns="http://www.w3.org/2000/svg"
width="800px" height="300px" viewBox="0 0 800 300">

<text x="25" y="55"
font-family="'Lucida Grande', sans-serif"
font-size="32">

Regular ol' text here. Hi.

</text>

</svg>

See.


<text> is happy to use custom fonts


Using @font-face and custom fonts on your site? No problem. That SVG is happy to use them. This works with inline SVG, where you can set font-family with CSS:


<text class="hook">Some Cool Text Yeah.</text>

.hook {
font-family: "proxima-nova", sans-serif;
}

but it even works for SVG-as-<img> (or background-image, presumably) as well, as long as the font-family references the custom font by the right name.


<text x="25" y="55" 
font-family="'proxima-nova', sans-serif"
font-size="32">

Use Design Software


I haven't tested a ton of different software, but Adobe Illustrator can "Save As" SVG. When you design with text elements, <text> is what you get in the .svg file.



You might have to do a little hand-tweaking to remove or adjust the font attributes/styles.


The beauty of this is that it takes away finicky task of positioning with CSS and lets you do it right in software that is awesome at it. Then the actual positioning happens with that matrix transform.


Scales Perfectly


If you were trying to replicate a design like this in just HTML/CSS. It's not just that the positioning is finicky to begin with, it's that it doesn't scale. Something like font-size: 41px; top: 37px; left: 81px; works only at one size. Perhaps you could do something with vw units and percentages and stuff, but it's just a lot easier in SVG.


In SVG, the font-size you set is relative to the size of the SVG itself, not the whole document. So if you adjust the size of the SVG (it can easily be fluid width), your typographic design stays perfectly intact.


A fluid width kinda setup:


<div class="ad-wrapper">
<svg class="ad">
<text ... />
<text ... />
<text ... />
</svg>
</div>

/*div*/.ad-wrapper {
height: 0;
padding-top: 100%;
position: relative;
}
/*svg*/.ad {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}

Scales proportionately. Text is still selectable as normal.

Design with fonts you have on the web


This workflow works best if you can fart around in local software with the fonts that you also have available via @font-face. For instance, if you were working in Open Sans, you could download a copy of that for desktop use from Font Squirrel but then use it on the web via Google Fonts.


I think Typekit makes this workflow pretty nice, with their desktop syncing feature. When you're picking out fonts, you can add them to a Kit to use on the web, as well as sync locally via the Creative Cloud thingy.



Then they are available right in Illustrator.



It's a little funky because the font-family names will be a little off. For instance, you might get like


<text font-family="'MarketOT'">Example</text>

from Illustrator, but on the web it'll need to be like


<text font-family="ff-market-web, cursive">Example</text>

But hey that's just part of the job. Maybe there is a good reason for it. Maybe someday they can get those things in sync.


When to use


If you're using the same custom fonts elsewhere on the site, it's a no-brainer, go ahead and use <text> based designs as needed. If the fonts in use aren't used elsewhere, it might be a tall order to include an entire custom font just for use in a single graphic. Or perhaps not. You'll have to balance the options yourself.


In the example I've used here, I used Proxima Nova and FF Market from Typekit, and the Kit was about 115K. Not too bad if the rest of the site was using those fonts too. But then I converted the example to outlines (meaning <text> is out and <path>s are used instead to draw the letter shapes), and the file ballooned from an incredibly tiny 4K to an incredibly large 260K (bigger than the entire fonts, albeit unzipped).


I'm sure in some cases outlining makes good sense, and sometimes even a retina raster graphic works, assuming you take all the necessary accessibility steps (a good alt tag at a minimum).


Demo


Here's a demo that shows everything at work, including the scaling, selectability, and the custom fonts at work:


See the Pen SVG with example by Chris Coyier (@chriscoyier) on CodePen.




SVG `text` and Small, Scalable, Accessible Typographic Designs is a post from CSS-Tricks








Sonntag, 25. Mai 2014

Ideas Behind Responsive Emails




CSS-Tricks





Ideas Behind Responsive Emails



Say you've designed an HTML email with 3 columns. Because of limited and weird CSS support in email clients, email design is done with tables. That 3 column design looks great on large-ish screens, but it squishes awkwardly on small screens. Theoretically a media query would save us here, but as we can't even count on floats we sure can't count on those. There is still a way though.



In this article, I'm just going to poke at some ideas around responsive email. These are not robust, production-ready ideas, I just thought it was fun to think about. It was inspired by listening to Fabio Carneiro speak recently. Fabio works for MailChimp doing all this hardcore email layout wrangling and shared some of the ideas behind responsive emails in that talk. He also has a Treehouse Course on email.


Jason Rodriguez also wrote a bit on the topic recently.


Rows with align="left"


Here's some chunks in a layout:



You might think: each of those will be a <td>. But no, if that was the case you'd never be able to get them to wrap in the limited CSS world of emails.


Actually, each chunk is a <table align="left">. Align is an ancient, deprecated attribute, but it's still supported in all email clients. It's sort of like float, but we can't use float. I think of it more like you're making the table behave like an inline-block element. You can control it's width, it can sit on the same line as other stuff, and it can still wrap.


So that would be like:


<table class="main-wrapping-table">

<tr>

<td>

<table align="left" style="width: 33.33%">
</table>

<table align="left" style="width: 33.33%">
</table>

<table align="left" style="width: 33.33%">
</table>

</td>

</tr>

</table>

There would be slews of other inline CSS in there as well, doing centering and whatnot, but this is the layout concept.


Extending that idea to some other rows with different numbers of chunks, we get this:



Not too bad of a base for using nothing any email client can't use.


Breakable Rows with min-width


Some email clients support min-width. So if we put that on the chunks that need it, we can get those rows breaking at a reasonable place.


You could put the CSS right on the table chunk, like:


<table align="left" style="width: 33.33% min-width: 200px;" class="chunk">
<table>


A bit better. Now each chunk will break where it needs to and never get too squishy.


Fill space with @media query


Some email clients support @media queries, so if that's the case, we'll target those chunks and make sure they fill the space better when those breaks occur.


/* Figure out where the breaks happen and use that in the media query */
@media (max-width: 400px) {
.chunk {
width: 100% !important;
}
}


A little bit better yet. You could do better than I did there, making sure all the breaks all happen just as you plan.


Not too wide with max-width


Just as too-squishy is bad, too wide can be bad too. Might as well limit the container table in browsers that support max-width.


<table style="max-width: 600px; margin: 0 auto;" class="main-table">

</table>


Demo


Again, this isn't quite production-ready, it's just demonstrating the ideas.


See the Pen "Responsive" Email by Chris Coyier (@chriscoyier) on CodePen.


If you want production-ready, I'd probably use Email Blueprints by MailChimp. Seems like they use a rigid, fixed breakpoint. So it just either displays a "desktop" or "mobile" version depending on screen space available. "Adaptive" design, as it were. I could see that being desireable in HTML email design.




Ideas Behind Responsive Emails is a post from CSS-Tricks








Samstag, 24. Mai 2014

Script-injected “async scripts” considered harmful




CSS-Tricks





Script-injected “async scripts” considered harmful



Async is still cool (<script async src="script.js">), but the one where you create a script element with a src and inject it isn't anymore. There are a few gotcha's though, so make sure to read Ilya's whole article.


I made sure to update my article.


Direct Link to ArticlePermalink



Script-injected “async scripts” considered harmful is a post from CSS-Tricks








Freitag, 23. Mai 2014

SVG `use` with External Source




CSS-Tricks





SVG `use` with External Source



Inline SVG is an awesome way to use SVG because, among other reasons, the individual shapes that make up the graphic can be scripted and styled. The shapes are right in the DOM. But does that mean we have to define those shapes right in the HTML on every page? Nope, we can <use> to reference them from elsewhere. Ideally, that "elsewhere" is an external file, because that means that file can be cached by the browser, efficiency!



Here's what I mean:


<!-- `<use>` shape defined ON THIS PAGE somewhere else -->
<svg viewBox="0 0 100 100">
<use xlink:href="#icon-1"></use>
</svg>

<!-- `<use>` shape defined in an EXTERNAL RESOURCE -->
<svg viewBox="0 0 100 100">
<use xlink:href="defs.svg#icon-1"></use>
</svg>

So yeah: external resource = the way to go.


But, the external resource way doesn't work in any version (up to 11 tested) of Internet Explorer. Even the ones that do support inline SVG: 9, 10, 11.


Fortunately, Jon Neal has a clever solution. It's a little script called SVG for Everybody. The idea is this: just use <use> as if it works, and the script will handle it in IE 9, 10, 11. A polyfill, except just for this scenario (it doesn't make this work anywhere that doesn't already support inline SVG use).


It works like this:



  1. If the browser is IE 9, 10, or 11 (User Agent sniff, but that's the whole point here).

  2. Ajax for the SVG file referenced

  3. Find the needed bit, based on the ID referenced (e.g. #icon-1)

  4. Inject that into the <svg> on the page


It totally works.



I think inline SVG is damn useful and this (tiny) script means you can use it in a more responsible (cacheable) way.




SVG `use` with External Source is a post from CSS-Tricks








Dienstag, 20. Mai 2014

The Dangers of Stopping Event Propagation




CSS-Tricks





The Dangers of Stopping Event Propagation



The following is a guest post by Philip Walton (@philwalton). He is going to explain why stopping event propagation isn't something you should do lightly, and probably something you should avoid altogether.



If you're a front end developer, at some point in your career you've probably had to build a popup or dialog that dismissed itself after the user clicked anywhere else on the page. If you searched online to figure out the best way to do this, chances are you came across this Stack Overflow question: How to detect a click outside an element?.


Here's what the highest rated answer recommends:


$('html').click(function() {
// Hide the menus if visible.
});

$('#menucontainer').click(function(event){
event.stopPropagation();
});

In case it's not clear what this code is doing, here's a quick rundown: If a click event propagates to the <html> element, hide the menus. If the click event originated from inside #menucontainer, stop that event so it will never reach the <html> element, thus only clicks outside of #menucontainer will hide the menus.


The above code is simple, elegant, and clever all at the same time. Yet, unfortunately, it's absolutely terrible advice.


This solution is roughly equivalent to fixing a leaky shower by turning off the water to the bathroom. It works, but it completely ignores the possibility that any other code on the page might need to know about that event.


Still, it's the most upvoted answer to this question, so people assume it's sound advice.


What Can Go Wrong?


You might be thinking to yourself: who even writes code like this themselves anymore? I use a well-tested library like Bootstrap, so I don't need to worry, right?


Unfortunately, no. Stopping event propagation is not just something recommended by bad Stack Overflow answers; it's also found in some of the most popular libraries in use today.


To prove this, let me show you how easy it is to create a bug by using Bootstrap in a Ruby on Rails app. Rails ships with a JavaScript library called jquery-ujs that allows developers to declaratively add remote AJAX calls to links via the data-remote attribute.


In the following example, if you open the dropdown and click anywhere else in the frame, the dropdown should close itself. However, if you open the dropdown and then click on "Remote Link", it doesn't work.


See the Pen Stop Propagation Demo by Philip Walton (@philipwalton) on CodePen.


This bug happens because the Bootstrap code responsible for closing the dropdown menu is listening for click events on the document. But since jquery-ujs stops event propagation in its data-remote link handlers, those clicks never reach the document, and thus the Bootstrap code never runs.


The worst part about this bug is that there's absolutely nothing that Bootstrap (or any other library) can do to prevent it. If you're dealing with the DOM, you're always at the mercy of whatever other poorly-written code is running on the page.


The Problem with Events


Like a lot of things in JavaScript, DOM events are global. And as most people know, global variables can lead to messy, coupled code.


Modifying a single, fleeting event might seem harmless at first, but it comes with risks. When you alter the behavior that people expect and that other code depends on, you're going to have bugs. It's just a matter of time.


And in my experience, these sorts of bugs are some of the hardest to track down.


Why Do People Stop Event Propagation?


We know there's bad advice on the Internet promoting the unnecessary use of stopPropagation, but that isn't the only reason people do it.


Frequently, developers stop event propagation without even realizing it.


Return false


There's a lot of confusion around what happens when you return false from an event handler. Consider the following three cases:


<!-- An inline event handler. -->
<a href="http://google.com" onclick="return false">Google</a>

// A jQuery event handler.
$('a').on('click', function() {
return false;
});

// A native event handler.
var link = document.querySelector('a');

link.addEventListener('click', function() {
return false;
});

These three examples all appear to be doing the exact same thing (just returning `false`), but in reality the results are quite different. Here's what actually happens in each of the above cases:



  1. Returning false from an inline event handler prevents the browser from navigating to the link address, but it doesn't stop the event from propagating through the DOM.

  2. Returning false from a jQuery event handler prevents the browser from navigating to the link address and it stops the event from propagating through the DOM.

  3. Returning false from a regular DOM event handler does absolutely nothing.


When you expect something to happen and it doesn't, it's confusing, but you usually catch it right away. A much bigger problem is when you expect something to happen and it does but with unanticipated and unnoticed side-effects. That's where nightmare bugs come from.


In the jQuery example, it's not at all clear that returning false would behave any differently than the other two event handlers, but it does. Under the hood, jQuery is actually invoking the following two statements:


event.preventDefault();
event.stopPropagation();

Because of the confusion around return false, and the fact that it stops event propagation in jQuery handlers, I'd recommend never using it. It's much better to be explicit with your intentions and call those event methods directly.


Note: If you use jQuery with CoffeeScript (which automatically returns the last expression of a function) make sure you don't end your event handlers with anything that evaluates to the Boolean false or you'll have the same problem.


Performance


Every so often you'll read some advice (usually written a while ago) that recommends stopping propagation for performance reasons.


Back in the days of IE6 and even older browsers, a complicated DOM could really slow down your site. And since events travel through the entire DOM, the more nodes you had, the slower everything got.


Peter Paul Koch of quirksmode.org recommended this practice in an old article on the subject:


If your document structure is very complex (lots of nested tables and such) you may save system resources by turning off bubbling. The browser has to go through every single ancestor element of the event target to see if it has an event handler. Even if none are found, the search still takes time.


With today's modern browsers, however, any performance gains you get from stopping event propagation will likely go unnoticed by your users. It's a micro-optimization and certainly not your performance bottleneck.


I recommend not worrying about the fact that events propagate through the entire DOM. After all, it's part of the specification, and browsers have gotten very good at doing it.


What To Do Instead


As a general rule, stopping event propagation should never be a solution to a problem. If you have a site with several event handlers that sometimes interfere with each other, and you discover that stopping propagation makes everything work, that's a bad thing. It might fix your immediate problem, but it's probably creating another one you're not aware of.


Stopping propagation should be thought of like canceling an event, and it should only be used with that intent. Perhaps you want to prevent a form submission or disallow focus to an area of the page. In these cases you're stopping propagation because you don't want an event to happen, not because you have an unwanted event handler registered higher up in the DOM.


In the "How to detect a click outside of an element?" example above, the purpose of calling stopPropagation isn't to get rid of the click event altogether, it's to avoid running some other code on the page.


In addition to this being a bad idea because it alters global behavior, it's a bad idea because it puts the menu hiding logic in two different and unrelated places, making it far more fragile than necessary.


A much better solution is to have a single event handler whose logic is fully encapsulated and whose sole responsibility is to determine whether or not the menu should be hidden for the given event.


As it turns out, this better option also ends up requiring less code:


$(document).on('click', function(event) {
if (!$(event.target).closest('#menucontainer').length) {
// Hide the menus.
}
});

The above handler listens for clicks on the document and checks to see if the event target is #menucontainer or has #menucontainer as a parent. If it doesn't, you know the click originated from outside of #menucontainer, and thus you can hide the menus if they're visible.


Default Prevented?


About a year ago I start writing an event handling library to help deal with this problem. Instead of stopping event propagation, you would simply mark an event as "handled". This would allow event listeners registered farther up the DOM to inspect an event and, based on whether or not it had been "handled", determine if any further action was needed. The idea was that you could "stop event propagation" without actually stopping it.


As it turned out, I never ended up needing this library. In 100% of the cases where I found myself wanting to check if an event hand been "handled", I noticed that a previous listener had called preventDefault. And the DOM API already provides a way to inspect this: the defaultPrevented property.


To help clarify this, let me offer an example.


Imagine you're adding an event listener to the document that will use Google Analytics to track when users click on links to external domains. It might look something like this:


$(document).on('click', 'a', function() {
if (this.hostname != 'css-tricks.com') {
ga('send', 'event', 'Outbound Link', this.href);
}
});

The problem with this code is that not all link clicks take you to other pages. Sometimes JavaScript will intercept the click, call preventDefault and do something else. The data-remote links described above are a prime example of this. Another example is a Twitter share button that opens a popup instead of going to twitter.com.


To avoid tracking these kinds of clicks, it might be tempting to stop event propagation, but inspecting the event for defaultPrevented is a much better way.


$(document).on('click', 'a', function() {

// Ignore this event if preventDefault has been called.
if (event.defaultPrevented) return;

if (this.hostname != 'css-tricks.com') {
ga('send', 'event', 'Outbound Link', this.href);
}
});

Since calling preventDefault in a click handler will always prevent the browser from navigating to a link's address, you can be 100% confident that if defaultPrevented is true, the user did not go anywhere. In other words, this technique is both more reliable than stopPropagation, and it won't have any side effects.


Conclusion


Hopefully this article has helped you think about DOM events in a new light. They're not isolated pieces that can be modified without consequence. They're global, interconnected objects that often affect far more code than you initially realize.


To avoid bugs, it's almost always best to leave events alone and let them propagate as the browser intended.


If you're ever unsure about what to do, just ask yourself the following question: is it possible that some other code, either now or in the future, might want to know that this event happened? The answer is usually yes. Whether it be for something as trivial as a Bootstrap modal or as critical as event tracking analytics, having access to event objects is important. When in doubt, don't stop propagation.




The Dangers of Stopping Event Propagation is a post from CSS-Tricks








Mittwoch, 14. Mai 2014

Updated Flexbox Guide




CSS-Tricks





Updated Flexbox Guide



Worth mentioning here: I updated the Complete Guide to Flexbox here on the site that Hugo Giraudel originally helped me with. The idea was to have the complete set of information there, but quickly get to the references to the the properties, what they do, and which elements they go on.


Direct Link to ArticlePermalink



Updated Flexbox Guide is a post from CSS-Tricks








Dienstag, 13. Mai 2014

jQuery with CoffeeScript




CSS-Tricks





jQuery with CoffeeScript



I don't always write CoffeeScript, but when I do, I'm probably using jQuery too I always forget the syntax for stuff. So I'm going to write it all down here so I can reference it until I memorize it.



Note that the compiled example doesn't include the automatic closure around everything you get in CoffeeScript.


Safe jQuery Closure


So you can use the $ safely (common in WordPress):


(($) ->

) jQuery

(function($) {

})(jQuery);

DOM Ready


$ ->
console.log("DOM is ready")

$(function() {
return console.log("DOM is ready");
});

Call Method with No Params


$(".submit").click ->
console.log("submitted!")

$(".submit").click(function() {
return console.log("submitted!");
});

Call Method with One Param


$(".button").on "click", ->
console.log("button clicked!")

$(".button").on("click", function() {
return console.log("button clicked!");
});

Call Method With Multiple Params


$(document).on "click", ".button2", ->
console.log("delegated button click!")

$(document).on("click", ".button2", function() {
return console.log("delegated button click!");
});

Params in the Anonymous Function


$(".button").on "click", (event) ->
console.log("button clicked!")
event.preventDefault()

$(".button").on("click", function(event) {
console.log("button clicked!");
return event.preventDefault();
});

Returning False


$(".button").on "click", ->
false

$(".button").on("click", function() {
return false;
});

A Simple Plugin


$.fn.extend
makeColor: (options) ->
settings =
option1: "red"

settings = $.extend settings, options

return @each () ->
$(this).css
color: settings.color

$.fn.extend({
makeColor: function(options) {
var settings;
settings = {
option1: "red"
};
settings = $.extend(settings, options);
return this.each(function() {
return $(this).css({
color: settings.color
});
});
}
});

Using Plugin


$("a").makeColor
color: "green"

$("a").makeColor({
color: "green"
});

Ajax


Note the string interpolation in there too, that's nice.


$.ajax
url: "some.html"
dataType: "html"
error: (jqXHR, textStatus, errorThrown) ->
$('body').append "AJAX Error: #{textStatus}"
success: (data, textStatus, jqXHR) ->
$('body').append "Successful AJAX call: #{data}"

$.ajax({
url: "some.html",
dataType: "html",
error: function(jqXHR, textStatus, errorThrown) {
return $('body').append("AJAX Error: " + textStatus);
},
success: function(data, textStatus, jqXHR) {
return $('body').append("Successful AJAX call: " + data);
}
});

Animation


Two ways.


div.animate {width: 200}, 2000

div.animate
width: 200
height: 200
2000

div.animate({
width: 200
}, 2000);

div.animate({
width: 200,
height: 200
}, 2000);

Animation with Callback


div.animate
color: red
2000
->
doSomething()

div.animate({
color: red
}, 2000, function() {
return doSomething();
});

Chaining


Not too much different.


$("input")
.val("")
.css
'z-index': 5
.removeClass "fart"

$("input").val("").css({
'z-index': 5
}).removeClass("fart");

Promises


The last line gets returned here when it doesn't really need to but whatever.


$.when(
$.get("/feature/", (html) ->
globalStore.html = html;
),
$.get("/style.css", (css) ->
globalStore.css = css;
)
).then ->
$("<style />").html(globalStore.css).appendTo("head")
$("body").append(globalStore.html)

$.when($.get("/feature/", function(html) {
return globalStore.html = html;
}), $.get("/style.css", function(css) {
return globalStore.css = css;
})).then(function() {
$("<style />").html(globalStore.css).appendTo("head");
return $("body").append(globalStore.html);
});

Fat Arrow to Retain `this`


Otherwise inside the setTimeout you wouldn't have a reference to the button.


$(".button").click ->
setTimeout ( =>
$(@).slideUp()
), 500

$(".button").click(function() {
return setTimeout(((function(_this) {
return function() {
return $(_this).slideUp();
};
})(this)), 500);
});



Here's the lot of them in a Pen if you wanna tinker.




jQuery with CoffeeScript is a post from CSS-Tricks








Montag, 12. Mai 2014

Tips for Creating Accessible SVG




CSS-Tricks





Tips for Creating Accessible SVG



Léonie Watson with a much-needed reference on how to do a good job with SVG accessibility. A couple of takeaways: 1) Use it, the sharp clarity of SVG is good for low vision folks. 2) Inline SVG offers better accessibility 3) Use <title> and <desc>. Plus several more you should definitely read about.


Direct Link to ArticlePermalink



Tips for Creating Accessible SVG is a post from CSS-Tricks








Samstag, 10. Mai 2014

Winner Winner




CSS-Tricks





Winner Winner



Super group hug and jumping high fives for everyone. I was honored to accept the Outstanding Contribution award for The Net Awards this year. The entire internet got to vote in the first round, then a select group of peers voted in the second round, so that's makes it a double-special thing to win.



I sadly couldn't make the ceremony, but I saw lots of pictures and heard nothing but great things. I sent them this acceptance video to play in my absence:



And to literally double the honor, Dave Rupert and I also won Podcast of the Year. Dave wasn't able to attend either, so we made this Thank You page and sent in this acceptance video:



♥❤♥❤♥



Winner Winner is a post from CSS-Tricks








Freitag, 9. Mai 2014

oEmbed Bring Embedded Pens All Over




CSS-Tricks





oEmbed Bring Embedded Pens All Over



oEmbed is a neat little technology that allows for rich content to be embedded into other content very easily. You paste a link to the "thing" and, when published, that link magically transforms into something much more useful than a link. A quintessential example is a link to a YouTube video. Just drop the URL to a video in a blog post, and it will transform into an embedded version of that video. Flickr URL... turns into an embedded photo.


CodePen supports oEmbed as well, which means you can put Embedded Pens in some interesting places right now, and enabling your site to allow them is pretty easy as well.



I mention this here, because it works great right here on CSS-Tricks!


Embedded Pens in the Forums


We encourage you to post Pens of issues in the forums anyway, because that's 100 times easier to play with and diagnose than trying to just look at code and imagine it.


See how easy? Just paste the link to the Pen in there.

Embedded Pen in the Comments


Right here in the blog, works the exact same way.


Don't worry if you don't see it in the Preview tab, the oEmbed process happens after publishing.

Why use oEmbed?


Of course, it's easy. But there is more than that. With oEmbed, you are whitelisting places you allow embedded rich content from. It's a trust thing.


CodePen embeds require JavaScript to work. That sounds anti-progressive-enhancement, but it's actually the opposite. By requiring JavaScript, we can take a perfectly good bit of content (a sentence explaining the title, author, and info about a Pen) and transform it into an <iframe> embed experience. So without JavaScript, the content still "works" and makes sense. With JavaScript, it's better. An <iframe> alone would just break in a no-JS environment (for us).


So, because we need need that <script> for our embeds to work, that limits where they can be used. Most sites don't allow you to just to execute whatever <script> you put on them. That would be highly irresponsible and a major security flaw (XSS). With oEmbed, you can allow that <script> through only for trusted sources. Pretty cool way to handle it, I think.


How it Works


oEmbed works by:



  1. Detecting URLs that match one of the whitelisted URL formats any particular site supports

  2. Makes a request to that sites oEmbed API, passing along that URL

  3. The API returns HTML the site uses to embed that "rich content"


You can see more about the CodePen oEmbed API here, including our API endpoint and what we return.


Enabling oEmbed on your WordPress site


It's basically one line of code to enabled it on a self-hosted WordPress site, but you might as well make use a plugin because that's what they are for. Then to make it work in comments (and bbPress), there is another plugin.


Iframely supports CodePen, and 900+ other domains embedded content, so that's an option too.


If you use Jetpack, support is coming soon to that.


But remember, if you are just embedding Pens into blog posts and stuff you don't need oEmbed at all. You can use our embed code, which means you can adjust heights and change themes and stuff, which is more powerful.


Discourse supports CodePen oEmbed


Discourse, as in the excellent forum software.



WordPress.com supports CodePen oEmbed



Thanks to Joey Kudish and the WordPress.com for getting Embedded Pens working there!




Lemme know if you end up using it in a cool way.


A major reason we started building CodePen at all was because showing snippets of code alone pales in comparison to seeing that code actually running, and this makes it easier to bring those running bits of code to the same types of places that used to be limited to snippets.




oEmbed Bring Embedded Pens All Over is a post from CSS-Tricks








Mittwoch, 7. Mai 2014

Reading Position Indicator




CSS-Tricks





Reading Position Indicator



The following is a guest post by Pankaj Parashar. Pankaj has written here before, last time about the progress element. I'm happy to have Pankaj back, this time to tackle the idea of showing reading progress (or really, a scroll position indicator) on websites, which has been a mini-trend lately.



Lately I've seen quite a few websites that have some kind of an indicator to display the current reading position (how much you have "read", depending on how far you have scrolled down an article). Generally, such indicators are used on blog posts or long form articles and help readers understand how far they are from finishing the article.


Here are some examples:



(View Full Size)
1) Stammy's blog uses a red color progress bar
2) Ben Frain's website displays the number of words left
3) Information Architects show "minutes left" to indicate the current reading position.



Interestingly, all three techniques represent the same information but with a different approach. I don't know if there is a name for this feature - so throughout the article, I call it a Reading Position Indicator.


In this article, we'll focus on the first technique that uses a horizontal progress bar as the indicator. But instead of using traditional div/span(s) and some non-linear math to build the indicator, we will use the HTML5 progress element. In my opinion <progress> is much more semantically accurate and suitable to represent this information, and that too with no complex calculations involved.


If you have never used the HTML5 progress element before, then I would strongly recommend you to read my article on CSS-Tricks that gives you an introduction on how to use this element in your markup and style them via CSS as cross-browser as possible with decent fallback techniques.

The Problem


To build a reading position indicator, we need to answer two important questions:



  1. What is the length of the webpage? The length of the webpage is same as the length of the document, which can be calculated via JavaScript.

  2. What is the current reading position of the user? Determining the current reading position of the user would entail hacking into the user's mind to extract the portion of the document currently being read by the user. This appears more like a candidate for Artificial Intelligence and seems impossible; given the scope of technologies that we are dealing with.


This leaves us with no choice but to tackle this problem statement with a completely different approach.


Principle


The principle behind this technique is based on a simple fact that the user needs to scroll to reach the end of the web page. Once the user reaches the end of the web page we can conclude that he/she has finished reading the article. Our technique revolves around the scroll event which is likely to be the key to determine an approximate position of the user while reading.


Assuming the user starts reading from the top and will only scroll once he/she reaches the end of the viewport, we'll attempt to answer the following questions:



  1. How much the user needs to scroll to reach the end of the web page? The portion of page that is hidden from the viewport is exactly the amount of scroll the user needs to perform to reach the end of the page. This will become our max attribute.

  2. How much portion of the page, user has already scrolled? This can be determined by calculating the vertical offset of the top of the document from the top of the window which will become our value attribute.



A demo simulating the scrolling behaviour of the user. As soon as the user starts scrolling in the downward direction to access the hidden part of the web page, the vertical offset increases. Demo on CodePen



In the context of the browser, document and window are two different objects. window is the viewable area of the browser (thick blue box in the above example) and document is actually the page that loads inside the window (thin grey box currently scrolling).


Markup


Let's start with a basic markup:


<progress value="0"></progress>

It's important to explicitly specify the value attribute. Otherwise, our progress bar will be in the indeterminate state. We don't want to add unnecessary styles in CSS for the indeterminate state. Thus we choose to ignore this state by specifying the value attribute. Initially, the user starts reading from the top, hence, the starting value set in the markup is 0. The default value of the max attribute (if unspecified) is 1.


To determine the correct value for the max attribute, we need to subtract the window's height from the height of the document. This can only be done via JavaScript, so we will worry about it at a later stage.


The placement of the markup in the HTML document would heavily depend on the how rest of the elements are placed. Typically, if you have no fixed position containers in your document, then you can place the progress element right on top of all the elements inside the <body> tag.


<body>
<progress value="0"></progress>

<!--------------------------------
Place the rest of your markup here
--------------------------------->
</body>

Styling the indicator


Since, we want our indicator to always sit on top of the web page, even when the user scrolls, we'll position the progress element as fixed. Additionally, we would want the background of our indicator to be transparent so that an empty progress bar doesn't create a visual hinderance while scrolling through the web page. At the same time this will also help us tackle browsers with JavaScript disabled that we'll cover later.


progress {
/* Positioning */
position: fixed;
left: 0;
top: 0;

/* Dimensions */
width: 100%;
height: 5px;

/* Reset the appearance */
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;

/* Get rid of the default border in Firefox/Opera. */
border: none;

/* Progress bar container for Firefox/IE10+ */
background-color: transparent;

/* Progress bar value for IE10+ */
color: red;
}

For Blink/Webkit/Firefox, we need to use vendor specific pseudo elements to style the value inside the progress bar. This will be used to add color to our indicator.


progress::-webkit-progress-bar {
background-color: transparent;
}

progress::-webkit-progress-value {
background-color: red;
}

progress::-moz-progress-bar {
background-color: red;
}

Interaction


Calculating the width/height of window and document in JavaScript is messy and varies horribly across different breed of browsers. Thankfully, jQuery manages to abstract all the complexities offered by these browsers and provides a much cleaner mechanism to calculate the dimensions of window and document. Hence, for the rest of the article we'll rely on jQuery to handle all our interactions with the user.


Before, we begin, do not forget to add jQuery library to your document.


<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

We need jQuery to determine the max and the value attribute of our progress element.



  • max - The max value is the portion of the document that lies outside the viewport which can be calculated by subtracting the window's height from the height of the document.
    var winHeight = $(window).height(),
    docHeight = $(document).height();
    max = docHeight - winHeight;

    $(progress).attr('max', max);


  • value - Initially, value will be zero (already defined in the markup). However, as soon as the user starts scrolling, the vertical offset of the top of the document from the top of the window will increase. If the scrollbar is at the very top, or if the element is not scrollable, the offset will be 0.
    var value = $(window).scrollTop();
    $(progress).attr('value', value);



Instead of using document in $(document).height(), we can use other elements like section, article or div that holds the content of the article to calculate the height and present the user with a much more accurate representation of the reading position indicator. This becomes quite useful, when you have a blog post that is filled with comments and constitutes more than 50% of the actual article.

Now, everytime the user scrolls, we need to re-calculate the y-offset from the top of the window and then set it to the value attribute of the progress element. Note that the max attribute remains the same and doesn't change when the user scrolls.


$(document).on('scroll', function() {
value = $(window).scrollTop();
progressBar.attr('value', value);
});

The direction in which the user is scrolling is not important, because we always calculate the y-offset from the top of the window.


It's important that our code executes only then the DOM is loaded, otherwise, premature calculation of window/document's height could lead to weird and unpredictable results.


$(document).on('ready', function() {  
var winHeight = $(window).height(),
docHeight = $(document).height(),
progressBar = $('progress'),
max, value;

/* Set the max scrollable area */
max = docHeight - winHeight;
progressBar.attr('max', max);

$(document).on('scroll', function(){
value = $(window).scrollTop();
progressBar.attr('value', value);
});
});

(Or ensure this code is loaded at the bottom of the page instead of the top, and skip the document ready call.)


Browser compatibility


This is all what we need to build a functional reading position indicator that works equally well in all the browsers that support the HTML5 progress element. However, the support is limited to Firefox 16+, Opera 11+, Chrome, Safari 6+. IE10+ partially supports them. Opera 11 and 12 doesn't permit changing the progress bar color. Hence, our indicator reflects the default green color.


Variants


There are quite a few variations possible in which we can style the indicator. Especially, the semantic color scheme (fourth variation) is a useful experiment, wherein the indicator changes color based on the proximity of the reading position from the end of the article.



  • Flat color scheme (default)

  • Single color gradient

  • Multi color gradient

  • Semantic color scheme


See the Pen Reading Position Indicator by Pankaj Parashar (@pankajparashar) on CodePen.


Edge cases


There are few scenarios, where our code can potentially break or present the user with an incorrect indicator. Let's look at those edge cases:


Document height <= Window height


So far, our code assumes that the height of the document is greater than the window's height, which may not be the case always. Fortunately, browsers handle this situation very well by returning the height of the window, when the document is visibly shorter than the window. Hence, docHeight and winHeight are the same.


max = docHeight - winHeight; // equal to zero.

This is as good as a progress element with both max and value attribute as zero.


<progress max="0" value="0"></progress>

Hence, our progress bar would remain empty and since our background is transparent, there will be no indicator on the page. This makes sense because, when the entire page can fit within the viewport there is really no need for an indicator.


Moreover, the scroll event won't fire at all because the height of the document doesn't exceed the window height. Hence, without making any modification, our code is robust enough to handle this edge case.


User resizes the window


When the user resizes the window, the height of the window and the document will change. This means that we will have to recalculate the max and the value attribute to reflect the correct position of the indicator. We'll bind the code that calculates the correct position to the resize event handler.


$(window).on('resize', function() {
winHeight = $(window).height(),
docHeight = $(document).height();

max = docHeight - winHeight;
progressBar.attr('max', max);

value = $(window).scrollTop();
progressBar.attr('value', value);
});

Javascript is disabled


When JavaScript is disabled our progress bar would have the default value as 0 and max as 1.


<progress max="1" value="0"></progress>

This would mean that the progress bar would remain empty and wouldn't affect any part the page. This is as good, as a page with no indicator isn't a big loss to the reader.


Fallback for older browsers


Older browsers that do not support the HTML5 progress element will simply ignore the progress tag. However, for some devs providing a consistent experience is important. Hence, in the following section, we'll employ the same fallback technique that was used in my previous article to implement the reading position indicator for oler browsers.


Markup - The idea is to simulate the look and feel of the progress element with div/span(s). Modern browsers will render the progress element and ignore the markup inside it, whereas older browsers that cannot understand the progress element will ignore it and instead render the markup inside it.


<progress value="0">
<div class="progress-container">
<span class="progress-bar"></span>
</div>
</progress>

Styling - The container will always span across the width of the webpage and the background will stay transparent to handle other edge cases.


.progress-container {
width: 100%;
background-color: transparent;
position: fixed;
top: 0;
left: 0;
height: 5px;
display: block;
}
.progress-bar {
background-color: red;
width: 0%;
display: block;
height: inherit;
}

Interaction - First we need to separate browsers that do not support the progress element from the browsers that support them. This can be achieved either with native JavaScript or you can use Modernizr to test the feature.


if ('max' in document.createElement('progress')) {
// Progress element is supported
} else {
// Doesn't support the progress element. Put your fallback code here.
}

The inputs still remain the same. But, in addition to determining the value, we need to calculate the width of the .progress-bar in percentage.


winHeight = $(window).height();
docHeight = $(document).height();

max = docHeight - winHeight;
value = $(window).scrollTop();

width = (value/max) * 100;
width = width + '%';

$('.progress-bar').css({'width': width});

After exploring all the edge cases, we can refactor the code to remove any duplicate statements and make it more DRY-er.


$(document).ready(function() {

var getMax = function(){
return $(document).height() - $(window).height();
}

var getValue = function(){
return $(window).scrollTop();
}

if ('max' in document.createElement('progress')) {
// Browser supports progress element
var progressBar = $('progress');

// Set the Max attr for the first time
progressBar.attr({ max: getMax() });

$(document).on('scroll', function(){
// On scroll only Value attr needs to be calculated
progressBar.attr({ value: getValue() });
});

$(window).resize(function(){
// On resize, both Max/Value attr needs to be calculated
progressBar.attr({ max: getMax(), value: getValue() });
});

} else {

var progressBar = $('.progress-bar'),
max = getMax(),
value, width;

var getWidth = function() {
// Calculate width in percentage
value = getValue();
width = (value/max) * 100;
width = width + '%';
return width;
}

var setWidth = function(){
progressBar.css({ width: getWidth() });
}

$(document).on('scroll', setWidth);
$(window).on('resize', function(){
// Need to reset the Max attr
max = getMax();
setWidth();
});
}
});

Performance


Generally, it is considered a bad practice to attach handlers to the scroll event because the browser attempts to repaint the content that appears every time you scroll. In our case, the DOM structure and the styles applied to them are simple, hence, we wouldn't observe any lag or noticeable delay while scrolling. However, when we magnify the scale at which this feature can be implemented on websites that employs complex DOM structure with intricate styles, the scroll experience can become janky and the performance may go for a toss.


If scrolling performance is really becoming a big overhead for you to overcome, then you can either choose to get rid of this feature completely or attempt to optimize your code to avoid unnecessary repaints. Couple of useful articles to get you started:



Ambiguity


I am no UX expert, but in some cases, the position and appearance of our indicator can be ambiguous and potentially confuse the user. Ajax-driven websites like Medium, Youtube etc., use similar kind of a progress bar to indicate the load status of the next page. Chrome for mobile natively uses a blue color progress bar for the webpage loader. Now, if you add the reading position indicator to this frame, I am sure that an average user will have a hard time understanding what the progress bar at the top of the page really means.



Website loading bars from Youtube, Medium and Chrome Mobile
Credits to Usability Post for screenshots from Medium/Youtube.



You'll have to make the call for yourself if this is of benefit to use your users or not.


Pros



  1. Semantically accurate.

  2. No math or complex computation involved.

  3. Minimum markup required.

  4. Seamless fallback for browsers with no support for HTML5 progress element.

  5. Seamless fallback for browsers with JavaScript disabled.


Cons



  1. Cross browser styling is complex.

  2. Fallback for older browsers relies on traditional div/span(s) technique making the entire code bloat.

  3. Scroll hijacking can potentially reduce FPS on webpages with complex DOM structure and intricate styles.

  4. It conflicts with the progress bar used to indicate web page loading and might confuse users.




Reading Position Indicator is a post from CSS-Tricks








Montag, 5. Mai 2014

Links with Inline SVG, Staying on Target with Events




CSS-Tricks





Links with Inline SVG, Staying on Target with Events



It's pretty common to use SVG within an anchor link or otherwise "click/tappable thing" on a web page. It's also increasingly common that the SVG is inline <svg>, because it's often nice having the SVG in the DOM since you can style it with CSS and script it with JS and such. But what does that mean for click events?



A link with an SVG icon in it might be like this:


<a href="#0" data-data="something">
<svg ... >
<rect ...>
<svg>
</a>

Now you want to bind a click event to that anchor link. In jQuery:


$("a").on("click", function(event) {

// `this` will always be the <a>
console.log($(this).data("data"));
// "something"

});

That will work perfectly fine. Note there is a data-* attribute on the anchor link. That's probably there specifically for JavaScript to access and use. No problem at all how we have it written right now, because within the anonymous function we have bound, this will always be that anchor link, which has that attribute available. Even if you use event delegation and call some function who-knows-where to handle it, this will be that anchor link and you can easily snag that data-* attribute.


But let's say you're going to rock some raw JavaScript event delegation:


document.addEventListener('click', doThing);

function doThing(event) {
// test for an element match here
}

You don't have an easy reference to your anchor link there. You'll need to test the event.target to see if it even is the anchor link. But in the case of our SVG-in-a-link, what is that target?


It could either be:



  1. The <a>

  2. The <svg>

  3. The <rect>


You might just have to check the tagName of the element that was clicked, and if you know it was a sub-element, move up the chain:


document.addEventListener('click', doThing);

function doThing(event) {
var el;

// we can check the tag type, and if it's not the <a>, move up.
if (event.target.tagType == "rect") {
// move up TWICE
el = event.target.parentElement.parentElement;
} else if (event.target.tagType == "svg") {
// move up ONCE
el = event.target.parentElement;
} else {
el = event.target;
}
console.log(el.getAttribute("data-data"));
}

That's pretty nuts though. It's too tied to the HTML and SVG structure. Toss a <g> in there around some <path>s, which is a perfectly fine thing to do for grouping, and it breaks. Or the tagType is path not a rect, or any other DOM difference.


Personally I've been preferring some CSS solutions.


One way is to lay a pseudo element over top the entire anchor element, so that the clicks are guaranteed to be on the anchor element itself, nothing inside it:


a {
position: relative;
}
a::after {
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
}

This seems to work pretty well too:


a > svg {
pointer-events: none;
}

pointer-events typically doesn't work in IE (it does in 11+, but not lower), but it actually does when applied to SVG, in IE 9+, which is the version of IE that supports SVG anyway.


Here's a Pen with the issue demonstrated and the fixes:


See the Pen owyFj by Chris Coyier (@chriscoyier) on CodePen.


Point is


If you're using SVG in a click target, be very careful you're getting the right element in JavaScript, and if you have trouble, consider a CSS cover.




Links with Inline SVG, Staying on Target with Events is a post from CSS-Tricks








Freitag, 2. Mai 2014

Programming Sucks




CSS-Tricks





Programming Sucks



Too many great quotes in this essay by Peter Welch . I'll just pick this one:


Right now someone who works for Facebook is getting tens of thousands of error messages and frantically trying to find the problem before the whole charade collapses. There's a team at a Google office that hasn't slept in three days. Somewhere there's a database programmer surrounded by empty Mountain Dew bottles whose husband thinks she's dead. And if these people stop, the world burns. Most people don't even know what sysadmins do, but trust me, if they all took a lunch break at the same time they wouldn't make it to the deli before you ran out of bullets protecting your canned goods from roving bands of mutants.


Over-the-top hilariously negative, but you can feel the love through it.


Direct Link to ArticlePermalink



Programming Sucks is a post from CSS-Tricks








Donnerstag, 1. Mai 2014

Improving UI Animation Workflow with Velocity.js




CSS-Tricks





Improving UI Animation Workflow with Velocity.js



The following is a guest post by Julian Shapiro. Julian recently released Velocity.js, a more performant jQuery replacement for .animate(). He recently wrote about how JavaScript animations can be so fast over on David Walsh's blog, a topic we've covered here as well. In this article, Julian introduces Velocity.js itself.



Velocity.js is a jQuery plugin that re-implements jQuery's $.animate() function to produce significantly higher performance (making Velocity also faster than CSS transitions in many cases) while including several new features to improve animation workflow.


In 7Kb (zipped), Velocity includes all of $.animate()'s features while also packing in transform animation, looping, class animation, and scrolling. In short, Velocity is designed to be the best of jQuery, jQuery UI, and CSS transitions.


Velocity works everywhere — back to IE8 and Android 2.3. Further, since Velocity's syntax is identical to $.animate()'s, none of your page's code needs to change.


The goal of Velocity is to be a leader in DOM animation performance and convenience. This article focuses on the latter. To learn more about the former, refer to Velocity's performance comparisons over at VelocityJS.org. In particular, this article demonstrates how to use Velocity to improve your UI animation workflow. In a concise showdown, eight of Velocity's features are compared against their jQuery counterparts.


If you feel that your current UI workflow is messy, poorly segregated, or too reliant upon jQuery’s broad array of style functions, then this walkthrough is for you.


Brief Overview


Before we dive into Velocity, let's quickly cover the bases: It should be pointed out that both $.animate() and $.velocity() support a malleable options syntax. You can either pass in options as comma-separated values, or you can pass in a standalone options object.


Here's an example of the comma-separated syntax, in which an integer is treated as the animation's duration, a string is treated as the easing type, and a function is treated as a callback (which is triggered upon the animation's completion):


$div.animate(
{
opacity: 1
},
1000,
"linear",
function() {
alert("Done animating.");
}
);

Next, here's an example of the object syntax:


$div.animate(
{
opacity: 1
},
{
duration: 1000,
easing: "linear",
complete: function() {
alert("Done animating!")
},
queue: "myQueue"
}
);

Beyond producing cleaner-looking code, using the options object provides access to additional animation parameters that are otherwise not able to be specified via the comma-separated syntax.


An example of one such option provided by jQuery is "queue". Velocity also provides the queue option, and multiple animation calls chained onto a single element automatically queue onto one another.


Here, a div's opacity will be animated to 1 for 1000ms then back down to 0 for the next 1000ms:


$div
.animate({ opacity: 1 }, 1000)
.animate({ opacity: 0 }, 1000);

Now, with the bases out of the way, let's start comparing Velocity to jQuery.


Reversing


In place of a properties map, Velocity also accepts "reverse" as its first parameter. Reverse animates the target element toward its values prior to its previous Velocity call.


In jQuery, that would be like:


$div
/* Fade an element in while sliding it into view. */
.animate({ opacity: 1, top: "50%" })
/* The values below are what we originally set the element to in our stylesheet. Animate back to them. */
.animate({ opacity: 0, top: "-25%" });

In Velocity, it's easier as it is not only less code, but you don't have to repeat values from your stylesheet:


$div
.velocity({ opacity: 1, top: "50%" })
.velocity("reverse");

By default, Velocity's reverse command uses the same options that were passed into the previous Velocity call. These options can be extended by passing new options into the "reverse" call. For example:


$div
.velocity({ opacity: 1, top: "50%" }, 1000)
/* Animate back to the prior visual state at half the duration of the previous animation. */
.velocity("reverse", 500);

Scrolling


A popular UI technique is to scroll the browser so that it's aligned with an element further down the page, then to animate that element with attention-grabbing flourishes. Pulling this off with jQuery involves messy, non-performant code:


In jQuery, animating the scrollTop property requires you to target both the html element and the body element in order for the animation to work in older versions of Internet Explorer.


$("html, body").animate(
{
scrollTop: $div.offset().top
},
1000,
function() {
/* We use a callback to fade in the div once the browser has completed scrolling. */
$div.animate({ opacity: 1 });
}
);

In Velocity, you target the element you want to scroll to:


$div
.velocity("scroll", 1000)
.velocity({ opacity: 1 });

Just as with Velocity's "reverse" command, "scroll" can be passed in as Velocity's first parameter in place of a properties map. Also like the reverse command, the scroll command accepts animation options and can be chained onto other calls.


The scroll command's behavior is straightforward: Scroll the browser to the top of the element targeted by the Velocity call.


Looping


Oftentimes, an element's animation needs to be looped. Examples include shaking a dialog box to indicate invalid user input or bouncing a notification icon to grab the user's attention.


In jQuery, looping an animation entails messing your animation logic by breaking part of it out into a for statement:


for (var i = 0; i < 5; i++) {
$div
/* Slide the element up by 100px. */
.animate({ top: -100 })
/* Then animate back to the original value. */
.animate({ top: 0 });
}

In Velocity, simply set the loop option to an integer equal to the desired number of loop cycles. A single loop cycle consists of animating toward the values in the property map followed by reversing back to the original values.


$div.velocity(
{ top: -100 },
{ loop: 5 }
);

Fading Elements


You'll often find yourself fading in an element whose display property was initially set to none, so that the element wasn't immediately visible upon page load. Subsequently fading in these elements requires several lines of jQuery:


$div
/* Use jQuery's $.show() function to make the element visible by switching its display property to "block"/"inline" as appropriate. */
.show()
/* Set the element's starting opacity to 0 so that it can be gradually faded in by the subsequent animation call. */
.css("opacity", 0)
/* Fade in and slide into view. */
.animate({
opacity: 1,
top: "50%"
});

In Velocity, you simply pass in display as an option. The display option accepts the same set of values that its CSS property counterpart does (e.g. "block", "inline", and "none").


$div.velocity(
{
opacity: 1,
top: "50%"
},
{
display: "block"
}
);

When the display option is set to a value other than none, the element's display property is set to the provided value at the start of the animation. Conversely, when display is passed a value of none, the display property is set upon the animation's completion.


$div
/* Fade out and slide out of view. */
.animate({ opacity: 0, top: "-50%" })
/* Then set the display property to "none" via a queued $.fadeOut() call. */
.fadeOut(1);

$div.velocity(
{
opacity: 0,
top: "-50%"
},
{
display: "none"
}
);

Further, if an element's opacity is being animated to a non-zero value while its display option is being set to a value other than none, Velocity conveniently defaults opacity's start value to 0.


Delaying


Velocity accepts a delay option that replaces having to sprinkle $.delay() calls throughout your animation code:


$div
.delay(1000)
.animate({
opacity: 1
});

$div.velocity(
{
opacity: 1
},
{
delay: 1000
}
);

Beyond consolidating animation logic into a single call, using Velocity's built-in delay option allows Velocity to optimize chained animations by caching values between them.


Class Animation


To avoid declaring CSS styles alongside JavaScript code, which is considered poor practice due to its resulting code maintainability complications, it is often recommended to separate out your animation styles into CSS classes then to trigger them using JavaScript.


Note that to perform class animation in jQuery, you must also have jQuery UI loaded. jQuery UI adds 62KB to your page once zipped. Conversely, class animation is already built into Velocity.


.animate_slideIn {
opacity: 1;
top: 50%;
}

$div.addClass("animate_slideIn", 1000);

$div.velocity("slideIn", 1000);

To animate a class in Velocity, simply pass in its name as Velocity's first parameter. Note that Velocity requires you to prefix your animation classes with animate_, but that you do not include this prefix in the Velocity call.


Also note that - in order to significantly increase performance - Velocity does not actually apply the class to the target element; the class is merely used as a property map container.


Forced Hardware Acceleration


Forcing hardware acceleration (HA) on an element is an easy to way to dramatically increase animation performance on mobile devices. Enabling HA is traditionally achieved by setting an element's transform property to translateZ(0).


$div
.css("transform", "translateZ(0)")
.animate({ opacity: 1 })
.css("transform", "none");

In Velocity, HA is automatically applied on mobile devices (there's no performance boost to be gained on the desktop). Velocity's control over HA is highly optimized.


$div.velocity({ opacity: 1 });

Wrapping Up


The purpose of this walkthrough has been to demonstrate Velocity's consolidation of animation logic within your code. In short, Velocity is an expressive and efficient tool for crafting UI animations.


While jQuery is tremendously powerful, it was never jQuery's design goal to function as an optimized animation engine, and it suffers accordingly from less-than-ideal performance and workflows. At just 7Kb zipped, Velocity packs in enough features and speed gains for you to consider making it your animation engine of choice.


To explore the remainder of Velocity's features, including color and transform animation, check out Velocity's documentation at VelocityJS.org.


Before we conclude, here are some extreme examples of web animation that are made possible through the expressiveness and speed of Velocity:





Improving UI Animation Workflow with Velocity.js is a post from CSS-Tricks