Responsive images with srcset in WordPress

As a developer, I am somewhat conservative. I believe strongly in the importance of web standards, and I am reluctant to be an early adopter of any new techniques or, even worse, non-standard workarounds for limitations in existing standards. I’d rather live with the limitations until a proper standard — or at least a de facto standard — takes hold.

One of the latest issues to challenge my approach has been responsive images. I’ve settled into a pattern of going with “1.5x” quality images, trying to strike a balance between quality on large high-res displays and a reasonable file size. But it really doesn’t do either very well.

Today’s issue of A List Apart features an exciting article:

Responsive Images in Practice

Yes! In practice! Let’s do this!

There have been a couple of competing proposals for handling responsive image sets, and I am pleased to see the srcset attribute begin to emerge as the winner. The biggest plus it has for me is that it degrades gracefully for older browsers that don’t support it.

Well, before I had even finished reading the article I started thinking about how I could leverage the build-in image sizing mechanism in WordPress to use srcset. I haven’t looked around — I’m sure someone else has already created a plugin that perfectly nails what I am attempting to do here. And, to be honest, I haven’t extensively tested this code yet, although I did drop it into a site I’m currently working on, just to be sure it doesn’t throw a fatal error and that it actually does render the HTML <img> tag as advertised.

function img_with_srcset($attachment_id, $default_size='medium', $echo=true) {
  $output = null;

  // Get image metadata
  $image = wp_get_attachment_metadata($attachment_id);

  // Set upload directory for image URLs
  $upload_dir = wp_upload_dir();
  $upload_url = $upload_dir['baseurl'] . '/' . dirname($image['file']) . '/';

  // Build array of sizes for srcset attribute
  $sizes = array();
  foreach ($image['sizes'] as $size) {
    $sizes[$size['width']] = $upload_url . $size['file'] . ' ' . $size['width'] . 'w';
  }
  
  // Sort sizes, largest first
  krsort($sizes);

  // Get image alt text
  $image_alt = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);

  // Generate output <img> tag
  if (!empty($sizes)) {
    $output =  '<img srcset="' . implode(', ', $sizes) . '" ' .
               'src="' . $upload_url . $image['sizes'][$default_size]['file'] . '" ' .
               'alt="' . esc_html($image_alt) . '" />';
  }
  
  // Return/echo output
  if ($echo) {
    echo $output;
    return true;
  }
  else {
    return $output;
  }
}

Let’s just examine what’s going on here.

The function takes three input parameters. An attachment ID, a default size (for the old school src attribute), and a boolean for whether to echo the output or just return it.

First, we get the attachment metadata and put it into $image. You can see more about what the wp_get_attachment_metadata() function does here.

Next, we set up the $upload_url variable to be the full base URL to the WordPress uploads directory. That’s because the metadata output only includes the filename of each sized image, not its full URL.

Then we loop through all of the sizes in the metadata output, generating a series of strings containing the image URL and its width, for use in the srcset attribute. We put these into an array because we need to manipulate the list a bit: we need to sort it so the largest images come first, and then later we need to implode() this into a comma-separated string.

Of course we also need the image’s alt text, so we grab that with get_post_meta() which you can read more about here.

Finally, assuming we actually have some size data, we build the <img> tag, complete with srcset attribute! Then we either echo or return it, as determined by the $echo input parameter.

Something else I’d like to try with this is taking it a step further by adding a filter that processes page content, looking for <img> tags, and automatically inserts the appropriate srcset attribute.

There you have it. I welcome anyone who’s reading this to give the function a try in your WordPress site, and let me know how it goes!

The Something Manifesto, Part Two

Darts_in_a_dartboardThere have been plenty of manifestos over the years, perhaps the most famous being Marx’s The Communist Manifesto. The manifesto that has defined the first decade of the 21st century, or at least the decade’s online component, is without a doubt The Cluetrain Manifesto.

Defining Success

I have always harbored almost a knee-jerk disdain for Cluetrain, quite possibly just because I think its title is stupid. It doesn’t help that the first of its Lutheresque “95 theses” is:

Markets are conversations.

I don’t really believe this. Markets are places where people try to sell you stuff. Luring you into conversation is just a sales tactic. Everything that follows in Cluetrain is dependent upon this one central illusion: make the market look like it is two people engaging in a meaningful interaction, instead of simply exchanging money for goods and services. Even Homer Simpson’s inner voice knows the value of a $20 bill, and not since Ayn Rand has capitalism so effectively masqueraded as philosophy.

This doesn’t make the market evil, it just exaggerates the human value of the quest for profit. Which brings me back to the Jason Fried interview I linked to in part one. Fried says:

It really bothers me that the definition of success has changed from profits to followers, friends, and feed count. This crap doesn’t mean anything. Kids are coming out of school thinking, I want to start the next YouTube or Facebook. If a restaurant served more food than everybody else but lost money on every diner, would it be successful? No. But on the Internet, for some reason, if you have more users than everyone else, you’re successful. No, you’re not.

Fried is absolutely right about the dangers in the Internet era of equating popularity with success. But the original equation is no less dangerous. Does profit equal success? That depends. Is profit your goal?

Meeting your goals equals success.

The problem is that following this axiom requires that you have goals, and sadly that often seems too much to ask.

I think most people have an innate desire to matter. We want to feel like our lives are important, or at the very least, that they mean something. That’s been the essence of religion for thousands of years. Fame is an easy thing to latch onto in this regard: if everyone knows who I am, then I must be important. Eventually, though, this quest for fame is going to result in dissatisfaction, regardless of the outcome. Either you fail to become famous, languish in obscurity, and lament your lack of success, or you achieve the fame you seek, realize it’s a hollow victory, and continue to seek out one new fix after another. But they’re all the same, and you always come down.

The Freedom to Be Productive

Unwarranted hallowing of “The Market” aside, both Cluetrain and Jason Fried’s philosophy represent a prevailing attitude of this decade: that breaking down the old, rigid structures of the 20th century corporate world will produce happier, more productive employees/citizens/people. I agree. But there’s a major problem: it’s just really hard for a calcified corporate hierarchy to adapt to this kind of flexibility. Lots of companies have tried it, to be sure. I’ve been there. But the efforts are usually hampered by lack of enthusiasm and buy-in by the employees, lack of focus and direction by management, or sheer inertia.

At best small pockets — rogue departments — can collectively “break the rules” and implement a more flexible structure, but they’re destined to remain on the fringe. Or, a few of the principles will be implemented company-wide, but they’ll be so mutilated by that point that they result in absurdities like once-a-month “denim days” where employees have to pay (in the form of a charitable donation) for the “privilege” of dressing comfortably.

There’s another problem that doesn’t get stated explicitly in Inc.’s article on Jason Fried’s Facebook-like recitation of the daily minutiae of his life. He gets up before 7 AM. He does some work while he’s getting ready. He arrives at work (or works from home) around 10 AM, and stays until 6 PM. Then after his regimen of Fox TV, he may put in a few more hours of work at night. In other words, his job is his life. It’s integrated with other things, to be sure. He fits in plenty of non-work activities during the day. But work is always there. It’s no surprise that he’s single, no kids. There may not be a causal connection, and if there is, one can’t determine from the article in which direction it points. But the simple fact remains that a life this focused on work cannot simultaneously accommodate a relationship, much less kids.

This was the problem I had at my last job before I went freelance. In many ways, it was the ideal place for someone of my geeky persuasion to work. And I often lament that I am not a part of that world anymore. But the arrangement was unsustainable for me: developers pulling “all-nighters,” crashing on couches in the lobby, getting pizza delivered in at 10 PM, these are all standard practice. It’s a culture of work that expects a level of availability that someone who’s also responsible for two young children simply cannot afford to provide. But it’s an inherent element of the kind of “flexible” work environment these philosophies inspire.

And so it was that I set out on my own. The environment I’m attempting to create for myself is, in many ways, not unlike that which I left, or which I’ve been criticizing in the preceding paragraphs. The major difference is in the amount of time I am expected to devote to work (that is, billable hours) versus the other aspects of my life which, to many an employer’s chagrin, continue to exist. But this true freedom comes at a price: less billable hours means… less money. And not being on someone else’s payroll means I’m shouldering all of the risk of the operation. The business is mine to make into a success or to allow to become a failure. But at least it’s mine.

Call to action: Find ways to work that work for you.

To be continued…

The Something Manifesto, Part One

somethingI’ve been thinking a lot lately. Or, not so much thinking, but thinking it would be nice to have more time to think. Or more time to do anything. I want to be more productive, even if I’m not sure what I want to produce. I haven’t had time to figure that out yet.

I’ve noticed a convergence of ideas lately, both inside my own head and in the larger world, a world I increasingly interact with primarily via the Internet, despite the fact that I am fully capable of going outside and interacting with it directly. These ideas are mostly circling around a disturbing premise: the tools that are allowing us to share these ideas are consuming our ability to produce them in the first place.

I’ve become something of a Facebook and Twitter addict over the course of the past year. I need the constant affirmation they provide in the form of comments from acquaintances and strangers alike on the random scraps of brainstuff I frequently distribute via this medium. Comments tell me people know I exist. They make me feel important. Increasingly, they serve as a sterilized substitute for genuine human interaction.

But there may just be some hope yet: I’m seeing encouraging signs that I’m not alone in… uh… being alone. Joshua Wentz (of SIDEDOWN) laments the vacuous experience of Facebook. Jason Fried (of 37signals) tells Inc. how popularity on social networking sites does not equal success. Nick Kallen (of Twitter, no less!) discusses how our brains buckle under the sheer mass of information in the modern world.

And so, I present my manifesto. My statement of beliefs about… something. I’m just not sure what.

Family > Work > Social Networking

I need to prioritize. We all need to. What’s really the most important to us, or, more accurately, who is? Our interactions with the people who really mean something to us, who are a part of our daily existence, must come first. These people are our “family,” whether we’re related by blood or not, whether our relationships are legally recognized by the government or not.

Work is next. Work is what we do that matters to us. It’s not necessarily what we get paid to do — though if we’re lucky, we can sometimes make that happen. It’s what drives us and fulfills us.

Social networking? Well, now we begin to see its real place in the hierarchy of things. These tools can help us to reconnect with the people we care about but with whom we no longer share physical space. They can help us meet and develop meaningful relationships with people whose interests we share, but whose physical space we never have (and likely never will). But much of the time they simply provide needless distractions, inundating us with useless details about the lives of people who don’t really mean that much to us. Just because information exists, doesn’t mean it’s important.

Call to action: Delete your social networking bookmarks.

To be continued…