All Posts by Email, Once a Week

Media Temple logo

CSS-Tricks is brought to you in part by Media Temple, the web hosting that we both use and recommend.

Advanced Articles

Getting Started with the WordPress Customizer

The following is a guest post by Scott Fennell, a WordPress theme & plugin developer in Anchorage, AK and a regular contributor around here.

Let's say you have a client whose business is large enough to have several departments. Now let's say that this client wants each of their departments to have their own website on a dedicated domain. Each site is to have the same layout, but a different color scheme. This is a phenomenal use-case for the WordPress Customizer (aka the Theme Customization API), and I'd like to share a basic example of how to build it into a theme.

(more…)

Understanding JavaScript Constructors

The following is a guest post by Faraz Kelhini. Some of this stuff is out of my comfort zone, so I asked Kyle Simpson to tech check it for me. Kyle's answer (which we did during an Office Hours session) was very interesting. It was: 1) This article is technically sound. JavaScript doesn't really have classes in a traditional sense and this is the way most people shoehorn them in. 2) We may want to stop shoehorning them in. JavaScript has objects and we can use them in the way they are intended to do the same kinds of things. Kyle calls it OLOO (Objects Linked to Other Objects). Here's an intro. I'd think there is value in learning about both.

(more…)

Can You “Over Organize” JavaScript?

There's no question that on sites with lots of JavaScript, you need a strict organizational pattern to keep everything making sense and the code approachable. I've mentioned in the past I like grouping things into individual files each containing a functionality-specific object literal. Taking things a wee bit further, we can be strict about this pattern and make sure we group together all sectors in one place, all "init" functions in one place, all event binding in once place, and have the rest be little well-named mini functions that do very specific things.

I wonder though, is this too organized?

(more…)

Play Sound on Hover – Web Audio API Edition

I got an email from a Notary Sojac who saw my tutorial on playing a sound on hover. In that tutorial we had to resort to some fairly hackish behavior to get the sound to react nicely to our events. Notary Sojac had an update to make the existing code work better, but more importantly, was looking into the Web Audio API for doing stuff like this. I didn't even know that was a thing. Turns out it's not controlling HTML5 audio elements, it's deeper level access than that.

The following is a guest post by Notary Sojac explaining all that.

We're all impressed with the capabilities of HTML5 canvas. The idea of creating a standardized and logical way of performing 2d drawing operations opened the door to an amazing new world where one programmer could learn one language and develop amazing products that could be deployed to all relevant platforms! Think about how critical this is for a moment. Now think about who would want an amazing graphics application that has a buggy, glitchy sound system that only makes sounds moments after you clicked and sometimes forgets to make sounds all together? That's the kind of product you get (especially in mobile platforms) if you go the HTML5 <audio> element route. It's better in desktop browsers, but unfortunately will never be perfected due to reasons beyond the scope of this article. But as of now, for the desktop, there is still hope. And there is hope in the future for mobile applications as well. That hope is named...

Web Audio API

The web audio API is designed for high precision and low level access. You can literally write bits of data to the samples. I'm not 100% sure what a sample is, but I think it has to do with air pressure against a microphone (aka, the microphone's driver position) at a single moment in time. That's pretty low level if you ask me. In Google Chrome, all audio functions are handled by a separate thread to ensure non-wonkyness.

On August 21st, Mozilla began making public the fact that they're dropping their original, pioneering "Audio Data API" and are beginning to implement Google's "Web Audio API" in their browser. But that means, at the time of this writing, you'll need to use a fallback for Firefox.

You can hear a great deal of good information from this Google I/O talk by Chris Wilson:

How To Use It

Unfortunately you need to use a lot more JavaScript with the Web Audio API than you do with plain old HTML5 audio elements, but often times the precision of the Web Audio API is imperative.

First we need to load the sound, which can be done with a function like this:

// you'll put the PCM audio in here
var audioBuffer = null;  
var context = new webkitAudioContext();

function loadDogSound(url, variableToBufferSound) {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer';

  // Decode asynchronously
  request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
      variableToBufferSoundIn = buffer;
    }, onError);
  }
  request.send();
}

Then we play the buffer, with a function like this:

function playSound(buffer) {

  // creates a sound source
  var source = context.createBufferSource();

  // tell the source which sound to play
  source.buffer = buffer;          

  // connect the source to the context's destination (the speakers)           
  source.connect(context.destination);       
  
  // play the source now
  source.noteOn(0);                          
}

That's a heck of a lot more code than we need as designers, just trying to play simple mouseover sound effects. Luckily, I snapped together a little JavaScript framework for using the Web Audio API.

With this new API, all one needs to do is:

  1. Create an AudioContext
  2. Load a sound into that AudioContext
  3. Play the sound

All of these steps are one liners! Fallbacks to good old HTML5 are included!

<script src="javascripts/webAudioApiForDesigners.js"></script>

<script>
// 1
var context = initializeNewWebAudioContext();

// 2
context.loadSound('audio/beep.ogg', 'beep');

$("#nav-one a")
  .mouseenter(function() {
    // 3
   context.playSound('beep');
  });
</script>

View Demo

List of reasons why HTML5 audio elements may be a bad choice

  • Wonky latency problems where sounds are heard at wrong times
  • Unexplainable popping sounds when playing multiple sound files at once
  • Limit to number of HTML5 audio elements that can play simultaneously

Reasons why HTML5 might be more suitable to your project

  • Very simple and straightforward to use
  • Can play background music just fine
  • Eventually (wild guess: no sooner than within the next 3 years) the bugs will be ironed out of these sorts of html DOM elements

More Information

HTML5 Rocks has a solid introduction.

Custom Events are Pretty Cool

Let's say you are working on a web application in jQuery and you are tasked with writing an accordion suited to the needs of your web app. You decide to make it into a plugin. That way anywhere in this app that needs an accordion, they can load this plugin and call it upon semantic markup that is ready to become an accordion. Then ta-da, they have a lovely working accordion.

Now another developer is using your accordion and they want to be able to Ajax load some content into one of the sections of the accordion, but only when that section is opened. Together you decide that you should keep your code separate. The generic functionality of how an accordion works should be separate from code specific to one accordion on one page of an app.

Callbacks, the traditional way

One way to approach that would be to write "callbacks" into your plugin. The other developer would specify the name of a function that she wants run when certain actions happen on that accordion. So the calling of it might be like:

$(".accordion").accordion({
  panelOpen: myPanelOpenCallback,
  panelClose: myPanelCloseCallback;
});

And they would have created those callback functions themselves:

function myPanelOpenCallback() {
  // Do Ajax stuff 
}

Then the plugin itself would honor those callbacks in its related internal functions:

$.fn.accordion = function(options) {
    
	return this.each(function(i, el) {

	  var base = el;
	  
	  base.init = function() {
	  	// Do initialization stuff
	  };
	  
	  base.openPanel = function(panel) {
	  	// Open panel
		
		// Do callback
		options.panelOpen.call();
	  };
	  
	  base.closePanel = function(panel) {
	  	// Open panel
		
		// Do callback
		options.panelClose.call();
	  };
	  
	  base.init();
	       
	});
  
};

View Demo of Callback Model

Custom Events, a better way

Now let's say a third developer gets involved, and they also want to write a bit of JavaScript that reacts to a panel opening as well. For the sake of a use case, say what's inside the accordion panels are settings, and this developer wants to save those settings whenever keys are opened or closed automatically.

Now we're in an interesting position. We've already defined our callback for accordion panels opening and closing. So in the callback model, these developers are going to have to get together on that callback and run both of their code in that one callback. Not that big of a deal, but now we're forced to mix code when that might not be ideal. Remember we started this whole thing off by separating specific functionalities.

Here's where custom events are super rad. Instead of firing off a specified callback, the accordion functionality plugin fires off a custom event. Custom events are just like any other event (e.g. click) only they are only declared and called programmatically.

First, callbacks are gone, we just call the accordion plugin without them:

$(".accordion").accordion();

Now in place of where we called the callbacks, we'll trigger our Custom Event. Basically, just make up a name that makes sense (like you are naming a function).

// OUT
// options.panelOpen.call();

// IN
panel.trigger("panelOpen");

Now our other developers can bind their stuff to this custom event and do their own thing.

$(".panel").on("panelOpen", function() {
   // Developer 1: do Ajax stuff
});

// Meanwhile, in another part of town...
$(".panel").on("panelOpen", function() {
   // Developer 2: do saving stuff
});

Yay for freedom! Yay for separation of functionality!

In my opinion custom events are just better all around. I do think they require a bit more communication though. You'll probably have to write up some comments somewhere that explain what custom events are fired and when and make that easy to discover.

View Demo of Custom Events model

More Information

The scenario outlined above is very simple. The following two articles go way more into depth about Custom Events including more complex examples and more information on how they work.

Animated Knockout Letters

I was watching some commercial the other day and they had these letters fly in over a black screen and reveal an image beneath them. It was a pretty cool looking effect and it reminded me how WebKit has that cool -webkit-background-clip property which allows you to show background through text. So I set off on trying to see if I could do something like that. You can, but there are some interested stumbling points...

(more…)

Parent Selectors in CSS

Let's be clear here, just in case someone is finding this from a search engine: there are no parent selectors in CSS, not even in CSS3. It is an interesting topic to talk about though, and some fresh talk has surfaced.

Back in 2008, Shaun Inman suggested the syntax:

a < img { border: none; }

[Corrected the following sentence]: In this example, it would select a tags but only if they contained an img tag. (Aside: this would be a weird departure from the typical syntax where the actual elements being selected are on the right, this would be on the left).

Definitely read through the comments on that post, it is a super interesting thread, and contains some pretty signifiant reasons parent selectors don't exist yet. David Hyatt, a developer on the front-lines of implementing these kinds of things in WebKit, comments that:

With parent selectors it becomes extremely easy to accidentally cause a document-wide grovel. People can and will misuse this selector. Supporting it is giving people a whole lot of rope to hang themselves with.

Jonathan Snook resurfaced this topic and gives us lots of great background on how CSS rendering works. We've all heard before that the universal selector is the least efficient CSS selector. Jonathan says if there was a parent selector, that would then easily be the new top dog in inefficient selectors. The argument being that when elements are dynamically added and removed from the page, it may result in the entire document needing to be re-rendered (major memory usage concerns). Jonathan is still optimistic though:

What I've described is not technically impossible. In fact, quite the opposite. It just means that we'd have to deal with the performance implications of using such a feature.

Remy Sharp also gets in on the fun, and suggests this syntax:

a img:parent { background: none; }

The key difference being that the :parent syntax would only evaluate a single element, the parentNode available in the DOM for every element. This would be similar to forcing the :has selector to only evaluate children rather than all descendants.

So far everyone is in agreement:

  • There are huge performance concerns
  • Those concerns can be thought of as tradeoffs we should evaluate, not show-stoppers.
  • Want!

There's a whole bunch of content on CSS-Tricks.

Search for Stuff   •   Browse the Archives

Get the Newsletter ... or get the RSS feed