28
Apr 12

Typography Effects with CSS3 and jQuery

TypographyEffects

View demo Download source

Today we will create a set of nice typography effects for big headlines using CSS3 and jQuery. There are many things we can do with CSS3 animations and transitions and we’ll explore some of the possibilites.

We’ll be using Lettering.js in order to style single letters of the words we’ll be having in our big headlines.

The image used in the demo is by Andrey & Lili. They are licensed under the Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0) License.

The HTML

The structure will simply be an h2 element with an anchor inside. We’ll wrap the headline in a container:

<div id="letter-container" class="letter-container">
	<h2><a href="#">Sun</a></h2>
</div>

Then we’ll call the Lettering.js plugin, so that every letter gets wrapped in a span.

Now, let’s take a look at each example. I’ll show all the styles that are relevant to the effect. In the downloadable files, you can check out all the other styles, like the positioning of the headline, the fonts and so on.

In order not to bloat the tutorial, I will not be showing any CSS vendor prefixes. The downloadable files contain them, of course.

Example 1

TypographyEffect_1
In the first example we want to skew the letters in order to create bit of perspective. But we also want to change the word on hover, so our structure will contain an additional link element inside of the h2. For the effect to work nicely, we’ll choose two words with the same number of letters:

<div id="letter-container" class="letter-container">
	<h2><a href="#">Chaos</a></h2>
	<h2><a href="#">Order</a></h2>
</div>

We’ll give the link element an absolute position and make the second word disappear by giving it the opacity 0:

.letter-container h2 a{
	text-align: center;
	text-transform: uppercase;
	font-size: 150px;
	position: absolute;
	width: 800px;
	height: 180px;
	top: 0px;
	left: 50%;
	margin-left: -400px;
	transition: all 0.3s linear;
}
.letter-container h2 a:nth-child(2){
	opacity: 0;
}

The spans will have some characteristic text shadow and a transition. The even children of will be skewed 10 degrees and the odd ones -10 degrees:

.letter-container h2 a span{
	display: inline-block;
	position: relative;
	width: 120px;
	margin: 0px;
	transition: all 0.3s linear;
	text-shadow:
		2px 2px 2px rgba(0,0,0,0.6),
		1px 1px 2px rgba(0,0,0,0.4),
		0px 0px 2px rgba(255,255,255,0.9);
}
.letter-container h2 a span:nth-child(odd){
	transform: skewY(10deg);
	background: #333;
	box-shadow: 0px 3px 5px rgba(0,0,0,0.3);
	z-index: 10;
}
.letter-container h2 a span:nth-child(even){
	transform: skewY(-10deg);
	background: #666;
	box-shadow: 0px 3px 5px rgba(0,0,0,0.3);
	z-index: 10;
}

When we hover over the h2 element, we want the second link element to appear and the first to disappear:

.letter-container h2:hover a:nth-child(1){
	opacity: 0;
}
.letter-container h2:hover a:nth-child(2){
	opacity: 1;
}

Also, we want to straighten the letters out:

.letter-container h2:hover a span{
	transform: skewY(0deg);
	background: #680121;
}
.letter-container h2 a span:hover{
	color: #f6b0c5;
}

Example 2

TypographyEffect_2

In the second example we’ll play a bit with pseudo elements. First, we’ll style each span in a way to look like a polaroid:

.letter-container h2 a span{
	display: inline-block;
	position: relative;
	width: 200px;
	height: 140px;
	background: #000;
	line-height: 140px;
	font-size: 120px;
	margin: 3px;
	background-position: 50% 0%;
	background-size: 200px 267px;
	color: #fff;
	text-shadow:
		0px 0px 1px #fff,
		2px 2px 5px rgba(0,0,0,0.4);
	border-color: #fff;
	border-style: solid;
	border-width: 10px 10px 45px 10px;
	box-shadow:
		2px 2px 8px 4px rgba(0,0,0,0.9),
		0px 0px 2px rgba(0,0,0,0.2) inset;
	transition: all 0.3s ease-in-out;
}

We’ll then add a pseudo element that will contain a wicked gradient, making our polaroid look more real:

.letter-container h2 a span:before{
	content:'';
	position: absolute;
	width: 220px;
	height: 195px;
	top: -10px;
	left: -10px;
	background: linear-gradient(-45deg, rgba(14,14,14,0.32) 0%,rgba(127,127,127,0.21) 18%,rgba(170,170,170,0.11) 34%,rgba(201,201,201,0) 51%,rgba(242,242,242,0.1) 66%,rgba(255,255,255,0.18) 79%,rgba(71,69,69,0.32) 100%);
}

Now, we’ll rotate the odd and even children differently to create a random look:

.letter-container h2 a span:nth-child(even){
	transform: rotate(3deg);
}
.letter-container h2 a span:nth-child(odd){
	transform: rotate(-5deg);
}

For each character (we are using the classes applied by lettering.js but we could also use the nth-child selector) we will add a different background image:

.letter-container span.char1{
	background-image: url(../images/1.jpg);
}
.letter-container span.char2{
	background-image: url(../images/2.jpg);
}
.letter-container span.char3{
	background-image: url(../images/3.jpg);
}
.letter-container span.char4{
	background-image: url(../images/4.jpg);
}
.letter-container span.char5{
	background-image: url(../images/5.jpg);
}

On hover over the whole link, we will rotate the spans and scale them down:

.letter-container h2 a:hover span:nth-child(even){
	transform: scale(0.9) rotate(-5deg);
}
.letter-container h2 a:hover span:nth-child(odd){
	transform: scale(0.9) rotate(3deg);
}

The specific span that we are hovering will have an animation that makes the background image move:

.letter-container h2 a span:nth-child(even):hover,
.letter-container h2 a span:nth-child(odd):hover{
	animation: moveImg 9s linear infinite forwards;
	color: rgba(255,255,255,0.4);
	text-shadow:0px 0px 5px rgba(0,0,0,0.1);
	transform: scale(1.1);
	z-index: 10;
	box-shadow:
		2px 2px 20px 4px rgba(0,0,0,0.6),
		0px 0px 2px rgba(0,0,0,0.2) inset;
}
@keyframes moveImg {
    0%{
		background-position: 50% 0%;
	}
	50%{
		background-position: 50% 100%;
	}
	100%{
		background-position: 50% 0%;
	}
}

Example 3

TypographyEffect_3

In the third example we will apply an animation to the span class which will run once when the page is loaded. We will make a blurry letter become sharp. We will also use a mask to add some texture to the letters (only Webkit browsers currently):

.letter-container h2 a span {
	font-size: 105px;
	color: #444;
   	opacity: 1;
   	text-shadow: 0px 0px 2px #444, 1px 1px 4px rgba(0,0,0,0.7);
	mask-image: url(../images/mask2.png);
	transition: all 0.3s linear;
	animation: sharpen 0.6s linear backwards;
}

When hovering over a letter we’ll change its color:

.letter-container h2 a span:hover{
	color: #3f7f75;
}

We’ll create some random appearence of the letters by giving each letter an animation delay:

.letter-container h2 a span:nth-child(1) {
	animation-delay: 1.2s;
}
.letter-container h2 a span:nth-child(2) {
	animation-delay: 0.1s;
}
.letter-container h2 a span:nth-child(3) {
	animation-delay: 1s;
}
/* ... and so on for all the letters */

The animation makes the letter appear blurry with a text-shadow with high fuzziness and a transparent color. Then it will appear sharpened by turning into a letter with solid color and a subtle text shadow:

@keyframes sharpen {
 0% {
   	opacity: 0;
   	text-shadow: 0px 0px 100px #444;
   	color: transparent;
 }
 90% {
   	opacity: 0.9;
   	text-shadow: 0px 0px 10px #444;
   	color: transparent;
 }
 100% {
    color: #444;
   	opacity: 1;
   	text-shadow: 0px 0px 2px #444, 1px 1px 4px rgba(0,0,0,0.7);
 }
}

Example 4

TypographyEffect_4
This example is quite different from all the others because we will apply some more jQuery. To understand what we are doing, I will show you what our jQuery function is making out of the headline. The structure that is created for each letter span after we apply lettering.js is the following:

<div class="twrap">
	<div class="tbg"><span>P</span></div>
	<div class="tup">
		<div class="tfront"><span>P</span></div>
		<div class="tback"><span>P</span></div>
	</div>
	<div class="tdown"><span>P</span></div>
</div>

Now, why such a structure? We want to play with perspective and 3d transforms, so we need a few more elements to make this work.
We want this headline to look like an airport information board and when we hover over a span, we want the little top element to fall down, but in 3D! This will only work in a Webkit browser, but we will have a nice alternative for the others.

So, let’s start by styting that new wrapper. It will be the container with the persepctive:

.letter-container h2 .twrap{
	position: relative;
	display: inline-block;
	width: 100px;
	height: 120px;
	line-height: 120px;
	font-size: 120px;
	border: 15px solid rgba(0,0,0,0.5);
	-webkit-perspective: 400;
	box-shadow: 1px 1px 4px #000;
}

Then we’ll style the background letter, which will be yellow:

.letter-container h2 .tbg{
	background: #121212;
	position: absolute;
	color: #f2c200;
	width: 100%;
	height: 100%;
	box-shadow: 0px 1px 3px rgba(0,0,0,0.9);
}

The down part of the letter in both the “tdown” and the “tup” (“tback”) container will be pulled up with a negative margin, because we just want to show the lower part:

.letter-container h2 .tdown{
	height: 50%;
	top: 50%;
	width: 100%;
	position: absolute;
	overflow: hidden;
	z-index: 1;
	background: #151515;
	box-shadow: 0px 1px 3px rgba(0,0,0,0.9);
	transition: all 0.3s linear;
}
.letter-container h2 .tdown span,
.letter-container h2 .tup .tback span{
	display: block;
	margin-top:-60px;
}

All the elements will have an aboslute position. The elements inside of “tup” will have -webkit-backface-visibility: hidden. Like that we’ll be able to rotate “tback” in 3d space and then “tup” when we hover:

.letter-container h2 .tup{
	height: 50%;
	width: 100%;
	position: absolute;
	z-index: 10;
	-webkit-transform-origin: 50% 100%;
	transition: all 0.3s linear;
	box-shadow: 0px 1px 3px rgba(0,0,0,0.9);
}
.letter-container h2 .tup .tfront,
.letter-container h2 .tup .tback{
	position: absolute;
	width: 100%;
	height: 100%;
	top: 0px;
	overflow: hidden;
	-webkit-backface-visibility: hidden;
	background: #151515;
}
.letter-container h2 .tup .tback{
	background: #121212;
	color: #f2c200;
}
.csstransforms3d .letter-container h2 .tup .tback{
	-webkit-transform: rotateX(-180deg);
}
.csstransforms3d .letter-container h2 a .twrap:hover .tup{
	-webkit-transform: rotateX(-180deg);
}

When we dont’ have support for the 3d transform then we’ll not show “tback”. We’ll instead animate “tup” and “tdown” to move to the back:

/* For browsers with no 3d transfrom support */
.no-csstransforms3d .letter-container h2 .tup .tback{
	display: none;
}
.no-csstransforms3d .letter-container h2 a .twrap:hover .tup{
	animation: moveBackUp 0.7s ease-in-out forwards;
}
.no-csstransforms3d .letter-container h2 a .twrap:hover .tdown{
	animation: moveBackDown 0.7s ease-in-out forwards;
}
@keyframes moveBackUp {
    0%{
		transform: translateY(0%);
	}
	50%{
		transform: translateY(-120%);
		z-index: -1;
	}
	100%{
		transform: translateY(0%);
		z-index: -1;
	}
}
@keyframes moveBackDown {
    0%{
		transform: translateY(0%);
	}
	50%{
		transform: translateY(120%);
		z-index: -1;
	}
	100%{
		transform: translateY(0%);
		z-index: -1;
	}
}

Example 5

TypographyEffect_5
Ok, example 5 looks crazy: we’ll create a text shadow that “elevates” the letters. We’ll also create a pseudo element which has a superhero as background:

.letter-container h2 a:before{
	content: '';
	position: absolute;
	z-index: 0;
	width: 525px;
	height: 616px;
	background: transparent url(../images/superhero.png) no-repeat center center;
	background-size: 40%;
	top: 0px;
	left: 50%;
	margin-left: -277px;
	transition: all 0.3s ease-in-out;
}

On hover, we will animate the background size to make the superhero larger:

.letter-container h2 a:hover:before{
	background-size: 100%;
}

The span will have the text-shadow that “elevates” the letters and on hover, we will move the letter down by adding a padding and changing the shadow:

.letter-container h2 a span{
	color: #ff3de6;
	float:left;
	position: relative;
	z-index: 100;
	transition: all 0.3s ease-in-out;
	text-shadow:
	  0px -1px 3px #cb4aba,
	  0 4px 3px #934589,
	  2px 15px 5px rgba(0, 0, 0, 0.2),
	  1px 20px 10px rgba(0, 0, 0, 0.3);
}
.letter-container h2 a span:hover{
	color: #e929d0;
	padding-top: 10px;
	text-shadow:
	  0px -1px 3px #cb4aba,
	  0 4px 3px #934589,
	  1px 1px 10px rgba(0, 0, 0, 0.2);
}

Example 6

TypographyEffect_6
In this example we’ll do something similar like in demo 3, except that we’ll animate the letters in order.
We’ll also apply a mask that will give some texture to the letters:

.letter-container h2 a {
	text-align: center;
	font-size: 130px;
	line-height: 160px;
	display: block;
	padding-bottom: 30px;
	mask: url(../images/mask.png) repeat;
}

The animation will sharpen the letters and we will apply a different animation delay to each child:

.letter-container h2 a span {
	color: #fff;
   	opacity: 1;
   	text-shadow: 0px 0px 2px #fff, 1px 1px 4px rgba(0,0,0,0.7);
	transition: all 0.3s linear;
	animation: sharpen 0.9s linear backwards;
}
.letter-container h2 a span:hover{
	text-shadow: 0px 0px 40px #fff;
}
.letter-container h2 a span:nth-child(1) {
	animation-delay: 0s;
}
.letter-container h2 a span:nth-child(2) {
	animation-delay: 0.1s;
}
.letter-container h2 a span:nth-child(3) {
	animation-delay: 0.2s;
}
/* ...and so on for all the letters */

@keyframes sharpen {
 0% {
   	opacity: 0;
   	text-shadow: 0px 0px 100px #fff;
   	color: transparent;
 }
 90% {
   	opacity: 0.9;
   	text-shadow: 0px 0px 10px #fff;
   	color: transparent;
 }
 100% {
    color: #fff;
   	opacity: 1;
   	text-shadow: 0px 0px 2px #fff, 1px 1px 4px rgba(0,0,0,0.7);
 }
}

Example 7

TypographyEffect_7
In the last example we’ll create some circles for each letter and on hover we will add a radial gradient to make it appear as a sun:

.letter-container h2 a span{
	display: inline-block;
	background: #bfd4e2;
	color: #ecf0f2;
	text-shadow: 1px 1px 2px rgba(120,155,179,0.5);
	width: 200px;
	height: 200px;
	line-height: 200px;
	font-size: 100px;
	margin: 3px;
	cursor: pointer;
	border-radius: 50%;
	box-shadow:
		2px 2px 10px rgba(43,54,61, 0.4),
		0px 0px 0px 9px rgba(116,161,191,0.3) inset;
	transition: all 0.3s ease-in-out;
}
.letter-container h2 a:hover span{
	opacity: 0.3;
}

You can read a great explanation of the radial gradient here: CSS3 Radial Gradient Syntax Breakdown – Impressive Webs

.letter-container h2 a span:hover{
	opacity: 1;
	box-shadow:
		2px 2px 10px rgba(43,54,61, 0.4),
		0px 0px 0px 0px #fedc3f inset,
		0px 0px 100px 30px rgba(255,244,193,0.8);
	color: #ff8624;
	text-shadow:
		1px 1px 2px rgba(166,97,41,0.5),
		1px 1px 1px #e66212, 3px 3px 1px #fdff64,
		4px 4px 6px #ff7420;
	background-image:
		radial-gradient(
			center center,
			circle contain,
			#fedc3f 0%, #ff7420 100%
			);
}

And that’s it! I hope you enjoyed creating some crazy typography effects with CSS3 and jQuery!
What’s your favorite one?

View demo Download source

Share and Enjoy:Diggdel.icio.usFacebookLinkedInRedditRSSTwitterGoogle BookmarksStumbleUponTechnoratiDZoneemailblogmarksDesign FloatDiigoFriendFeedGoogle BuzzIdenti.caMisterWongNewsVinePing.fmPlurkPosterousSlashdotSuggest to Techmeme via TwitterTumblr


Codrops

Tags: ,
11
Apr 12

Strategies for Scaling Real-Time Web Apps

Using Polling
Don't setup any cacheing and run a normal server. Poll for whatever data you need at any time, by as many users as possible. This puts load on your app and your database server. You can probably do a couple of thousand updates per minute before you get into trouble with a standard node.js / mongodb setup. On our Rackspace 1gb (of ram) cloud servers, we can handle a max of around 2000/second per box. Even a hefty Mongo setup won't be able to sustain that kind of load very long and the DB connections will start piling up and your servers will melt after a few minutes. With our setup of regular short polling every second (which is crazy) you'll want to scale things up around 200 simultaneous users.


Using Polling and Varnish 
The strategy here is simply to setup polling between set periods of time. So you can say get me everything that happened between this 10 second chunk and that 10 second chunk. Setup varnish to cache those calls , so everyone gets the same stuff. This puts the main responsibility for handling the load on the cacheing layer, which are usually built to handle a lot of load. Your database will only have to do one update every 10 seconds. It can handle that really easily. If there is some initial data you need to load to start your app that may get out of date, you can cache that bigger query for like 1 minute and again your database will be happy as pie. You can use Varnish here as a load balancer as well, but you probably will have to scale the load balancer before you'll need to scale up your app servers. A hefty Varnish box (say 8gb of ram) should be able to handle thousands of hits per second of cached data.

Using Socket.IO for polling

If your app server can safely handle ~2000 users per second, but your database cannot, you may want to try a setup like this. Let your app server "cache" the data from your database and push updates using web-sockets/long polling with socket.io. When the user initially connects to your page you can send down the cached data (or even a buffer of say the last 1000 messages). As the database gets updated using  normal POSTs and things the frequent polling of the database for updates can happen at the app-server (say one 5-second poll per app server), which will then send updates to all the users they know about. Obviously, this depends on how much data your pushing through (and how much ram you have), but with small amounts of stuff you can do the caching at the app level instead of on a special cache server, sparing both a new server and your database. Theoretically this setup would scale horizontally as well with multiple app servers, either through a load-balancer or some other round-robining approach. 

Jamund's Coding Blog

Tags:
4
Apr 12

This Week in Web – jQuery API, Python Video Archive, Symfony2 Beta, Heatmap.js

I Don’t Like [Django] Class Based Generic View

John DeRosa has written a blog post detailing why he does not like class based generic views (which were introduced in Django 1.3). He is of the opinion that generic views should be very simple and require a minimal amount of code to use. Class based generic views require you to subclass the generic view and override particular methods and properties (such the name of the template). This is in contrast to the old “function style” generic views where all you needed to do was call method and pass in the appropriate parameters.

jQAPI.com

The jQuery documentation is great, very complete, nicely written and with a lot of examples and demos. The only thing that bugs me is the way we have to find the right documentation for what we search for. Try to search for the .is() function for example. Over 100 matches before the actual function I am looking for?! And it is a fixed layout which means even on my big screen I have to scroll all the way down and have to scan for it. There have to be a better way, obviously.

Just to make it clear, I only coded the navigation and re-styled the documentation. The content is the same as in the official documentation and all credits belong to the jQuery team. Keep up the great work!

Symfony2 Beta 2&3 Released

Over the last week the Symfony project has released beta versions 2 and 3 of the Symfony2 PHP Framework. These releases have focused on fixing bugs and improving the documentation. The following tutorials have also been published:

Symfony2 can be downloaded from here.

Python Miro Community

python.mirocommunity.org is a video archive and aggregator for Python related videos. Currently they have videos from the last 3 years of Pycon, 2 years of Djangocon as well as other smaller Python conferences. You can subscribe to the RSS feed of latest videos added to the site here.

Heatmap.js

Heatmap.js is an open source Javascript library written by Patrick Wied that can be used to generate web heatmaps. “Heatmap instances contain a store in order to colorize the heatmap based on relative data, which means if you’re adding only a single datapoint to the store it will be displayed as the hottest(red) spot, then adding another point with a higher count, it will dynamically recalculate”. Heatmap.js is a standalone library (it doesn’t rely on any frameworks).

Query7

29
Mar 12

order of events on click on tag

So I have a normal link on my website, and I want to add tracking for it. I could envision a bunch of ways to do this, but I've settled on this as being really easy by writing a small jquery function, and dropping a small snippet in my tags:

<a href="newpage.html" onclick="saveClick(paramofpageclickhere);">click me!</a>

javascript:

function saveClick(someparamhere){
  $  .ajax({
   url: "somepage.php",
   data: {param:someparamhere}
  });
}

Now, I know my syntax might be bad, I'm just asking about the overall concept here. When you click the link, I want javascript to issue the call to saveClick which immediately makes an ajax call. There's no success handler because I don't really care if or what gets returned. I'll just have somepage.php log the event. Then, after all of that, I want the tag to go to it's href.

Is that the case? Will the ajax call be issued before the document goes to the other page? Will this work in all cases?

Has anybody ever done something like this? Any experience would be appreciated ....

active questions tagged jquery - Stack Overflow

Tags: ,
21
Mar 12

jQuery UI 1.8.15

The fifteenth maintenance release for jQuery UI 1.8 is out. This update brings bug fixes for Datepicker, Mouse and Slider, as well as support for jQuery 1.6.x. For the full list of changes, see the changelog. You can download it here:

Download

File Downloads

Svn (contains final files as they are in the zip, with @VERSION replaced with 1.8.15, all themes)

Git (contains source files, with @VERSION not yet replaced with 1.8.15, base theme only)

Google Ajax Libraries API (CDN)

Microsoft Ajax CDN (CDN)

Custom Download Builder

Changelog

See the 1.8.15 Upgrade Guide for a list of changes that may affect you when upgrading from 1.8.14. For full details on what’s included in this release see the 1.8.15 Changelog.

Thanks

Thanks to all who helped with this release, specifically: alexstack, be.davestein, bencoe, brettkiefer, chubyqc, Corey Frang, djmadcat, Encosia, enione, fedehf, jcm, jdufresne, kbwood, marcneuwirth, meh-cfl, peter@synerics.com, Richard D. Worth, Scott González, ThiefMaster, timn@bigfoot.com, TWD.

Comments

Note: please do NOT use the comments section of this blog post for reporting bugs. Bug reports should be filed in the jQuery UI Bug Tracker and support questions should be posted on the jQuery Forum.

If you have feedback on us doing our fifteenth maintenance release for jQuery UI 1.8, feel free to leave a comment below. Thank you.

jQuery UI Blog

Tags:
18
Mar 12

Can't listen on events within the jQuery UI Autocomplete menu

I've tried listening on several different types of events within the jQuery UI autocomplete menu, for example .on('click') and .on('submit').

None of the events are caught. In the case of the click event, the event isn't registered at all. And in the case of the submit, I try preventing default on the form id, but to no avail.

Essentially my use case for this is that I'm using the autocomplete to show possible options for an input, and appending an extra li to the menu on the open event with a button/form to add another option.

Can I simply not listen on events for some reason within autocomplete, other than the specified events like select?

active questions tagged jquery - Stack Overflow

15
Mar 12

jQuery 1.6 and .attr()

jQuery 1.6 and 1.6.1 are out the door. Congrats to the team and everyone that was involved with the release!

A relatively controversial change in 1.6 was regarding how attributes and DOM object properties were handled. In 1.6 we wanted to take the major step of completely separating the two, allowing us to create an .attr() method that wasn't quite so mealy-mouthed with regards to how attributes were handled. We did this in 1.6 because we felt that it was a substantial change (we only do major changes in the 1.x major releases of jQuery) and had the possibility of affecting people.

We did a considerable amount of testing on the code and we were quite confident that the amount of problems that people would encounter, while upgrading, would be quite minimal. The biggest pain points, we surmised, would be regarding how boolean attributes were handled (attributes like "disabled" or "selected"). However most of this would be mitigated and would likely have worked fine for users that consistently used .attr() to access and update their attributes.

After making the changes, and publishing 1.6, there were enough complaints that we had changed the API to cause us to reconsider and return .attr() to its sometimes-attribute, sometimes-property, state.

jQuery is in an incredibly tricky position now (and has been for some time). We very rarely add features to the library, for fear of bloat and added API maintenance overhead, and are rarely able to make any sort of API change, for fear of preventing people from upgrading.

Thankfully even though we've reverted some of the changes in 1.6, we've done it in a way that still maintains the performance gains that we achieved with the 1.6 release.

I wanted to try and summarize the .attr() method, to explain how it currently works in 1.6.1, but ended up writing up a sample function instead (note that this is a bit of an over-simplification, please read the code for more details):

function attr( elem, name, value ) {
  // Are we setting a value?
  if ( value !== undefined ) {
    // Make sure the element has the ability to set an attribute
    if ( typeof elem.setAttribute !== "undefined" ) {
      // If the user is setting the value to false
      if ( value === false ) {
        // Completely remove the attribute
        elem.removeAttribute( name );
     
      // Otherwise set the attribute value
      } else {
        // If the user is setting the value to true,
        // Set it equal to the name of the attribute
        // (handles boolean attributes nicely)
        elem.setAttribute( name, value === true ? name : value );
      }
   
    // If it doesn't, then we're likely dealing with window or document
    // (or some other object entirely)
    } else {
      elem[ name ] = value;
    }
 
  // Otherwise we're getting an attribute value
  // Check to see if the appropriate method exists
  // Also don't use getAttribute if a boolean property exists
  } else if ( typeof elem.getAttribute !== "undefined" &&
              typeof elem[ name ] !== "boolean" ) {
    return elem.getAttribute( name );
 
  // If no getAttribute method is present, or if we
  // wish to access the boolean property instead of the
  // attribute, then we fallback to the DOM object property
  } else {
    return elem[ name ];
  }
}

Ironically this isn't much shorter than the actual .attr() implementation, I recommend that you check it out.

There's a very good chance that your code, written targeting 1.5.2, will continue to work just fine in 1.6.1 using this particular technique.

However this point now begs the question: Why does .prop() exist?

In short, for two reasons:

  1. There are legitimate use cases for interacting with some DOM properties (such as nodeName, selectedIndex, or defaultValue) and we want to provide a simple solution for accessing, and mutating, them.
  2. Accessing properties through the .attr() method will be slightly slower than accessing them directly through .prop() (as .attr() calls .prop() internally in order to handle all property-related mutation).

In jQuery 1.5.2, and older, in order to access a DOM property you would have to do something like this:

var elem = $ ("#foo")[0];
if ( elem ) {
  index = elem.selectedIndex;
}

In 1.6+ you can just do:

index = $ ("#foo").prop("selectedIndex");

Summary: There's a good chance that your code won't be affected at all with the changes that've happened, especially so with the changes in 1.6.1, and jQuery now has a convenience method for handling DOM properties in a simpler, and slightly faster, manner.

Tangentially this reminds me of a common question that I hear: What will be in jQuery 2.0? I have no idea what will be in that release, should it ever arrive, but I do know what won't be in it: A massive API change of any sort. Even when we make, relatively minor, API changes like in the 1.6 release the amount of negative feedback that we get is monumental. If we've learned anything after doing 31 releases of jQuery it's that people like having stability in their API and will cherish that over everything else.

I do want to thank the community though for being so vocal and working to communicate with the team so actively. Without the community's communication and support it's doubtful that the team would be able to continue operating.

I would like to take this opportunity to encourage everyone to get involved with the development of jQuery. We hold active discussions every day in IRC and hold public meetings once a week. We also post weekly status updates if you wish to follow along. Right now we're working on the 1.7 release of the library and are actively encouraging contributions and feedback. If you want to help ensure the quality and stability of the next release of jQuery, the best way to do so is to get involved. Hope to see you around the bug tracker.


John Resig

Tags:
11
Mar 12
11
Mar 12

7 new techniques every web developer should know

CSS3 media queries

With the rise of mobile devices, and on the other hand, of very wide displays, creating a website that looks great in both big and small devices is definitely a challenge for web designers and developers. Happily, the CSS3 specification have a new feature which allow web developers to define styles for a specific display size only.

For example, the code below show how to apply a specific style only if the client display is smaller than 767px.

@media screen and (max-width:767px){
	#container{
		width:320px;
	} 

	header h1#logo a{
		width:320px;
		height:44px;
		background:url(image-small.jpg) no-repeat 0 0;
	}                           

}

More info: Create an adaptable website layout with CSS3 media queries

Font resizing with REMs

CSS3 introduces a few new units, including the rem unit, which stands for “root em”. If this hasn’t put you to sleep yet, then let’s look at how rem works.

The em unit is relative to the font-size of the parent, which causes the compounding issue. The rem unit is relative to the root—or the html—element. That means that we can define a single font size on the html element and define all rem units to be a percentage of that.

html { font-size: 62.5%; }
body { font-size: 1.4rem; } /* =14px */
h1   { font-size: 2.4rem; } /* =24px */

More info: Font resizing with REMs

Cache pages for offline usage

HTML5 introduces a great feature, offline caching. Basically, this feature allows you to tell the client browser to cache some pages so your visitor will be able to view it again, even if he’s not connected to the Internet.

Caching pages is pretty easy. The first thing to do is to add the following to your site .htaccess file:

AddType text/cache-manifest .manifest

Once done, you can create a file named, for example, offline.manifest, with the following directives:

CACHE MANIFEST

CACHE
index.html
style.css
image.jpg

And finally, link your .manifest file to your html document:

<html manifest="/offline.manifest">

That’s all, and your page will now be cached if the client browser supports this technology.
More info: How to create offline HTML5 web apps in 5 easy steps

Server-side JavaScript

Since the mid-90′s, JavaScript has been a very popular client-side language for web developers. But nowadays, JavaScript is becoming more and more used on the server side. Why? Because now we have powerful server-side JavaScript environments such as Jaxer, Node.js and Narwhal.

The code belows demonstrate how to create a simple Hello World using Node.js.

var sys = require("sys");
sys.puts("Hello World!");

More info: Learning Server-Side JavaScript with Node.js

HTML5 drag & drop

Thanks to new technologies such as HTML5, the web is becoming more and more user-friendly. Now, it is possible to easily implement drag and drop on your web pages. This is very useful, for example for a shopping basket.

In order to make an element draggable, you simply have to add it the draggable="true" attribute, as shown in the example below:

<div id="columns">
  <div class="column" draggable="true"><header>A</header></div>
  <div class="column" draggable="true"><header>B</header></div>
  <div class="column" draggable="true"><header>C</header></div>
</div>

Of course, after you made an element draggable, you have to use some JavaScript to control what it should do. I’m not going to explain how to do it (This may be a full article!) so you definitely have a look there if you’re interested in the topic.

Quick tip: If you want to prevent the text contents of draggable elements from being selectable, simply apply the following CSS rules:

[draggable] {
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  user-select: none;
}

More info: Cross Browser HTML5 Drag and Drop

Forms, the HTML5 way

The HTML5 specification introduces lots of new features regarding one of the most important element of a website: forms. For example, it is now possible to add date pickers, numeric spinners, as well as validating emails using regular expressions patterns.

The following code is pretty self-explanatory and shows most of the new forms-specific features introduced in the HTML5 specification.

<form>
	<label for="range-slider">Slider</label>
	<input type="range" name="range-slider" id="range-slider" class="slider" min="0" max="20" step="1" value="0">

	<label for="numeric-spinner">Numeric spinner</label>
	<input type="number" name="numeric-spinner" id="numeric-spinner" value="2">

	<label for="date-picker">Date picker</label>
	<input type="date" name="date-picker" id="date-picker" value="2010-10-06">

	<label for="color-picker">Color picker</label>
	<input type="color" name="color-picker" id="color-picker" value="ff0000">

	<label for="text-field">Text field with placeholder</label>
	<input type="text" name="text-field" id="text-field" placeholder="Insert your text here">

	<label for="url-field">Url field</label>
	<input type="url" id="url-field" name="url-field" placeholder="http://net.tutsplus.com/" required>

	<label for="email-field">Email field</label>
	<input type="email" id="email-field" name="email-field" placeholder="contact@ghinda.net" required>

	<button type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false">
	<span class="ui-button-text">Submit form</span>
	</button>
</form>

More info: How to Build Cross-Browser HTML5 Forms

CSS animations

Most modern browsers are now supporting CSS animations. Yes, CSS are now allowing you to create some simple animations, without the help of a client-side programming language such as JavaScript.

The following example shows how to make a background color change. As you can see, we have (for now) to use some proprietary properties such as -moz-keyframes.

#logo {
	margin: 15px 15px 0 15px;
	background: red;
	float: left;

	/* Firefox 4+ */
	-moz-animation-name: colour-change;
	-moz-animation-timing-function: linear;
	-moz-animation-iteration-count: infinite;
	-moz-animation-duration: 30s;

	/* Webkit */
	-webkit-animation-name: colour-change;
	-webkit-animation-timing-function: linear;
	-webkit-animation-iteration-count: infinite;
	-webkit-animation-duration: 30s;
}

@-moz-keyframes colour-change {
    0% {
		background: red;
    }
	33% {
		background: green;
    }
    66% {
    	background: blue;
    }
}

@-webkit-keyframes colour-change {
    0% {
		background: red;
    }
	33% {
		background: green;
    }
    66% {
    	background: blue;
    }
}

More info: Enhance Your Sites with CSS3 Animations


CatsWhoCode.com

Tags:
9
Mar 12

Building a Slimmer jQuery

jQuery is more than five years old now! Over that time it has evolved along with the browsers, web sites, devices, developers, and users that it serves. It has also, um, grown quite a bit over that time. jQuery has added a lot of useful features, but it’s also accumulated cruft that we’d prefer not to support into perpetuity. It may not be an issue on a desktop PC with a high-speed connection, but we want jQuery to be a good solution for mobile devices as well.

Along with our continuing push for higher performance, our priority for upcoming versions is a smaller gzipped file size. It’s hard to do that when every new feature or bug fix must also preserve all existing features and behavior. So today, we want to start a conversation about slimming down the jQuery API by deprecating some features. Here are our guidelines for deprecation:

  • We don’t believe the feature represents current best practice in the use of jQuery.
  • The feature has proven unpopular, confusing, inefficient, or ineffective in actual use.
  • It is not practical or feasible to enhance the feature or address its limitations.
  • Removing it at some future time could yield notable usability, size, or performance benefits.

Deprecation is just the first step in a process that you can participate in. It is our goal to:

  • Explain the reasons for deprecating a particular feature, as described above.
  • Give at least one major-point-version, and often more, between deprecation and removal.
  • Provide alternatives to deprecated features so that migration is not painful.
  • Listen to community feedback regarding deprecation and removal.

Occasionally, as in the situation with event.layerX/layerY in version 1.7, we will make a breaking change with shorter notice if we judge that it will cause less pain to remove the feature immediately than to leave it in. Those will hopefully be rare exceptions.

Version 1.7 Deprecations

With those things in mind, we consider the following features to be deprecated as of version 1.7. Existing code that uses them continues to work, but the recommended alternatives are a better choice for compatibility with future versions.

.live() and .die(): We continue to get many bug reports and see user confusion regarding the quirks of the .live() method. Common issues are now documented on its updated API page. We strongly advise the use of .on() or .delegate() for new code, since they are better APIs. Given its widespread use it’s unlikely we will remove this API in 1.8, but please do update your code as soon as possible.

Non-standard event properties: As part of our push to improve event handler performance, we are also deprecating the copying of several event properties from the native event object to the jQuery event object and will remove them in 1.8: attrChange, attrName, relatedNode, and srcElement. Instead of accessing these through event.NAME you can access them via event.originalEvent.NAME where needed.

$ .ajax() Deferred aliases: In version 1.5 we defined .error()/,success()/.complete() on the jqXHR object as aliases for the Deferred’s .fail()/.done()/.always() methods. Although that seemed like a good idea at the time, it makes jqXHR a non-standard Deferred. That’s not good. Whenever possible, use the deferred/promise method name in preference to the jqXHR one. We still have some work to do here to provide a full migration path, so we are likely to continue supporting the aliases past 1.8.

deferred.isResolved() and deferred.isRejected(): Now that Deferreds and Promises have progress notifications and a convenient .state() method, we are deprecating these older methods and will remove them in 1.8. Getting the state of an N-state object using N-1 Boolean methods is a cruel-code version of “Twenty Questions”. Deferred-based code rarely needs to inspect state, and the string returned now is more convenient for a debugging scenario where it’s often used.

.attr(“value”) on inputs: For backwards compatibility, we’ve been returning the current value here (as in “what is currently in the input box”) versus the real attribute (what the value attribute says in the HTML). That leaves us no way to provide the true attribute value, and is confusing since W3C selectors work on the attribute and not the current value. So we are deprecating this behavior and will remove it in 1.8. Always use the .val() method to get the current live value of an input element. Until we can reclaim the attribute, you can use $ ("selector")[0].getAttribute("value") except on IE 6/7 where that will still return the current value. (Our 1.8 solution will get the attribute value on all browsers and is another reason why we’re anxious to change this.)

.closest(Array) returning Array: This signature is a bit of a strange bird, it was created for use by the old live events code but it returns an Array rather than a jQuery object. As of 1.8 we plan to remove it. The other signatures of .closest() are here to stay and are not affected.

.data(“events”): jQuery stores its event-related data in a data object named (wait for it) events on each element. This is an internal data structure so in 1.8 this will be removed from the user data name space so it won’t conflict with items of the same name. jQuery’s event data can still be accessed via jQuery._data(element, "events") but be aware that this is an internal data structure that is undocumented and should not be modified.

$ .sub() as a plugin: Although $ .sub() can be useful for creating interference-free zones for plugins, it is not used by jQuery core and not widely used by other code, so we intend to transition it to a plugin in version 1.8 to save space.

Looking Towards jQuery 1.8

Given our push for a svelte jQuery, the filter for new features in 1.8 will be stringent. Even performance-related proposals need to be balanced against the space they use or save. Features that can be implemented via plugins, special events, attribute hooks, or other jQuery extension mechanisms are likely to stay outside core for now.

That brings up the question of what we could deprecate in 1.8 and eventually remove to simplify and streamline the library. Those things don’t have to totally disappear; they could move into a separate plugin, for example, and only be included when needed. Take a look at how you use jQuery, and talk about it with your colleagues.

Within a few weeks, we’ll be opening the call for your ideas concerning jQuery 1.8 with another blog post — so start thinking about it now!

Edit: No, we’re not removing IE6 support yet, and we can’t. As John Resig mentions at every jQuery Conference, most of the sins of IE6 are also visited upon IE7 and IE8, which together still have more than one-third of desktop browser market share. It doesn’t make sense to remove support for IE6 until we can whack IE7 and IE8 as well.


Official jQuery Blog

Tags: