Marking Posts as New in WordPress

I was updating my bookmarks page and wanted a way to indicate the stuff that I’d added recently, which led me to thinking about how to identify posts from a particular timeframe.

The Question

How can I mark recent posts based on a particular timeframe?

The Result

I considered a couple of options (listed below) and ended up with a fairly simple solution using relative time, something WordPress has built-in. On the front-end, it just adds a little clock icon next to the title of any resource added within the last 30 days:

new resource indicator

Potential Solutions

My first thought was that I could use PHP to check whether the post date was within a certain range.

1. Compare Year and Month

I was thinking maybe I’d check the post year against the current year, then if it matched I’d check against the current month. However, I dismissed that before I got past about 20 characters of code because I realized that it would throw off the time frame of the results depending on where in the month we are. Oh well, we all have bad ideas sometimes.

2. Date Calculations

Then I was thinking I’d use PHP to check the date against a relative time frame, e.g. the last 30 days. Something like the reverse of this Stack Overflow question and solution.

That would work, but then I remembered that WordPress has relative post date built in, where you can display the time as “1 day ago” or “30 minutes ago” using the function human_diff_time (function reference). Hooray, even better!

3. Using Relative Time

So then I was thinking, with that relative time I just need to check and see if we’re in the right time frames to be what I’d consider “recent.” The numerical values returned won’t be useful but the words are definitely useful. I double checked when the transition in words happens by looking at the core code underneath that function. I was able to confirm that anything with a relative time in minutes, hours or days has been posted in the last 30 days, and I’d consider that recent.

Full Solution

Here’s the full solution I ended up with (limited to just the template code within the loop, since the rest of the template is irrelevant to the question):

<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
    <?php
        $postdate = human_time_diff( get_the_time('U'), current_time('timestamp') ); // get the post date in relative time
        $recentvals = array('min','mins','hour','hours','day','days'); // the values I consider "recent"
    ?>                          
    <li class="filterable">
        <a href="<?php the_field('url'); ?>">
            <span class="project-title"><?php the_title(); ?><?php foreach ( $recentvals as $recentval ) : if ( strpos($postdate, $recentval) !== FALSE) : echo ' <i class="fa fa-clock-o"></i><span style="display:none;">new</span>'; endif; endforeach; ?></span>
        </a>
        <span class="small"><?php the_field('description'); ?></span>
    </li>
<?php endwhile; ?>

The Breakdown

Let’s take a closer look piece by piece at what this code does:

Set Variables

First up, there are two pieces of information I want to use in my comparison. That’s this part of the code:

<?php
        $postdate = human_time_diff( get_the_time('U'), current_time('timestamp') ); // get the post date in relative time
        $recentvals = array('min','mins','hour','hours','day','days'); // the values I consider "recent"
    ?>

There are two variables set up here:

  1. The post’s relative publication date, meaning how long ago it was posted in words (e.g. “20 mins” or “2 days”)
  2. The time frames I want to include as “recent,” using the words provided by that relative time function (options are: “mins,” “hours”, “days,” “weeks,” “months,” and “years” and the singular of each of those)

For the first, I just used WordPress’s built-in function, straight off the Codex page except I’m assigning it to a variable rather than echoing it (displaying it) on the page.

For the second, I have created an array of the words I’ll accept as “recent,” using both the singular and plural forms. I’m actually not sure if it’s possible to just use the singular and I don’t feel like testing it so I’ve just used both for safety’s sake.

Compare the Two

Next, I need to figure out whether the current post date for each post contains any of the words in my array. I referenced this thread on Stack Overflow for this code:

<?php 
foreach ( $recentvals as $recentval ) : 
    if ( strpos($postdate, $recentval) !== FALSE) : 
        echo ' <i class="fa fa-clock-o"></i><span style="display:none;">new</span>'; 
    endif; 
endforeach; 
?>

This runs through each of the allowed time frame words in my array and compares them against the post date. If one comes up as a match, it prints out the code in the echo line.

Show the Icon, Plus Search

The printed HTML from that snippet is:

<i class="fa fa-clock-o"></i><span style="display:none;">new</span>

That creates the Font Awesome clock icon along with a hidden span (I know, I know, lazy inline CSS). The hidden span is there so that it’s possible to use the in-page “search” function to pull up the new posts.

Implementation Keys

If you’re going to implement this yourself, the key things to remember are:

  1. The code needs to be within the loop, including the bit where you set the variables.
  2. You’ll need to determine which words constitute “recent” and update your array accordingly.
  3. You’ll likely also need to update your icon/ display HTML to fit your purposes (whether it’s just displaying text or adding in an image or another icon font or whatever).

Display Top WordPress Posts by Page Views

A recent client project has a component that shows top posts by views, which took some figuring out. WordPress doesn’t log views by post out of the box, but the Jetpack plugin does so that’s what we used as our data set. There are a couple Stack Overflow threads that talk about querying the posts by view count using Jetpack but none of them have the full code necessary so I thought it’d be useful to share how I did it.

Posts by views carousel

the end result

The post display is done using a custom loop via WP_Query, and the carousel in this particular example is done with bxSlider, which I use all the time for sliders and carousels.

Full Template Code

Here’s the full code for that area, which would go in the template file for the particular page or area you’re displaying the posts within. In this case, they’re on every page in the header so they’re in the theme’s header.php file.

The first and last lines are a conditional that checks for the stats function. If it returns false because the function isn’t there (e.g. if there’s no Jetpack installed) then nothing else will happen, preventing errors or other weirdness.

The Breakdown

Let’s run through the pieces of that snippet. (I won’t be covering the CSS and jQuery in this tutorial, since the focus is on getting the content to appear on the page, but let me know in the comments if you’d like to see a tutorial on carousels.)

Grab Top Posts’ IDs

The first few lines are getting the posts by views as registered by Jetpack:

The first line pulls up the top posts by views, using the last 21 days’ worth of data (that’s the first parameter in the array). The -1 value means that we are not limiting the number of posts returned. In the client project, I used custom fields for the number of days so that the client can change that if they’d like, and I also set a high but not unlimited value for the items returned since unlimited seems kind of unnecessary (the default is 100 if you omit that parameter entirely).

Set Custom Query Arguments

The remaining lines in that snippet create an array of post IDs for the posts returned by that first line, which is key because we need that array to plug into the post__in parameter for our query:

If you’ve ever built a custom loop using WP_Query, the above snippet will likely be familiar. It’s the arguments for our query, the first of which, post_type specifies that we want to pull only posts (the stats will return both posts and pages).

Major hat tip to Greg Rickaby for helping me level this up by adding a transient, which is essentially like a cookie and stores the query for a specified length of time, which speeds things up.

The other two parameters are post/ page specifics. First, post__in (that’s two underscores in there) specifies that we only want to return posts with IDs in that array we just built. Finally, posts_per_page limits the number of posts displayed on the page, overriding any other pagination you may have going on (from your regular loop settings, for example). I gave the client a setting for that value as well, so that she can control the number of posts in the carousel herself.

Create The Loop

Finally, the rest of the code is a standard WordPress loop structure:

In this construct, each item is wrapped in an <a> element (could just as well be a <div>) that links to the post permalink, and then the post thumbnail and title are displayed. I’ve arranged the markup so that I can have the title appear over the thumbnail on hover using CSS.

And there you have it, a snippet that returns top posts by views!

Introducing Emi, a Gulp and Sass-ready WordPress Starter Theme

Hey, did you know that April is Autism Awareness Month? It’s true! One of my kids is autistic, and since autism occurs in approximately 1 in 68 individuals you probably also know someone with autism. If you’d like to learn more about what autism is, I recommend this description. The Thinking Person’s Guide to Autism is another great resource.

Now, on to Emi…

Emi WordPress Starter Theme

I recently quietly made the repo for Emi, my WordPress Starter Theme available to the public, but it’s about time I actually announced the release.

Emi is a true starter theme – it’s got a foundational set of files and codes to jump start theme development, but it is not meant to be used as-is. It isn’t meant to be used with child themes, either. Instead, Emi should be directly edited and modified for custom theme projects.

Features

Emi comes with a few features built-in. Note that these features may not be for everyone, but they’re in there since they are what we use in our workflow. While I’m happy to be making Emi public so others can use it, modify it, etc., at root it’s still a tool that I use regularly and so the feature set is specific to how I use it.

Template Files

Emi’s got the template files that I use most often, including:

  • 503.php, to be used with the Maintenance Mode plugin as a landing page during active development (tutorial here)
  • archive.php, with code for archive-specific page titles
  • functions.php, with some useful theme options enabled and some starter snippets for other common customizations
  • Page templates for full width layouts and two kinds of redirects

Folder Structure

We’re constantly revising and rethinking our folder structure based on best practices and what makes sense for our purposes, and I’m pretty happy with what we’ve got now. Most of the template files are in the main directory.

We’ve split out the Sass files in their own /scss/ directory, which has some additional directories for custom page styling and blog styling.

There’s also an /inc/ directory for modules or pieces of code, and a subdirectory at /inc/functions/ for modules that are specific to the functions.php file.

Finally, there’s an /assets/ directory that contains theme javascript and subdirectories for images and for any vendor files we add to the theme (e.g. jQuery plugins).

HTML5

The template files have been updated to use HTML5, with HTML5 Shiv to help out older browsers.

SASS

Emi uses Sass to make CSS authoring both easier and more powerful. The main actual Sass features in use are the file structure/ partials, variables, and nesting.

You’ll find the variable definitions in /scss/_base.scss and a few starter mixins (including a sticky footer and HTML5 input support) in /scss/_mixins.scss. All the partials are combined in /scss/style.scss.

We use Autoprefixer to automatically add all the necessary browser prefixes to newer CSS features, which is part of the Gulp task for processing our Sass.

Gulp

We’ve integrated Gulp into our theme work (we also tried Grunt but found Gulp to be much faster), so it’s integrated into Emi as well. Gulp is a task runner, and the gulpfile.js file in Emi is set up with the tasks we use in our workflow:

Sass Processing
The gulp styles task processes the Sass files and also runs Autoprefixer before spitting out the minified CSS into the theme’s main style.css file.

Image Compression
The gulp images task compresses images from the /assets/images/originals/ directory, spitting the compressed files into the main /assets/images/ directory.

Watch Task
Finally, the gulp watch task runs continuously, watching for new images or changes to the Sass files and triggering the appropropriate task automatically. It also is hooked up with LiveReload.


You can download Emi from GitHub, and it’s under an M.I.T. license so you’re welcome to do with it what you will.

We’re constantly tweaking and improving it and would love your help! You can submit bugs or suggestions for improvements via the GitHub issues tracker, and feel free to send pull requests if you fix any open issues.

Q&A: The Pinterest-Style Grid a.k.a Masonry

I’ve had a lot of clients and designers ask me about creating a “Pinterest-style” grid for their website, and when someone asked on Twitter earlier this week for a recommendation of a jQuery plugin to handle the effect, I thought it was probably time for a tutorial.

About the Technique

If you’re just kind of curious about this technique, this first section is probably all you’ll really want to read. The later portion of the post gets into a more in-depth tutorial with code, but let’s start by talking terminology and reasons you’d actually want to use this layout model.

Technical Terminology

The actual name for this style of cascading “grid” where images or boxes of varying heights and widths flow neatly together with even spacing is masonry layout or masonry grid. Underneath the name is the idea that the “bricks” of the layout can vary but the spacing between (where the mortar would be, or in layout terms, the margins) is always consistent.

Pinterest is definitely the best-known example but if you’re looking for wider information or examples of the technique, masonry is the broader term to use.

From a Strategy Perspective

When compared to more traditional grids with a fixed height and width for every item in the grid, masonry grids have the advantage of NOT limiting the images that can be displayed. Whereas traditional grids require images to be cropped to fit, with a masonry layout the person maintaining the content will never have to think about aspect ratio when uploading their grid images.

This is especially nice for photographers, who usually want to highlight their composition by displaying the complete image for each photo:

Sabra Lattos masonry grid

Sabra Lattos Photography, designed by small shop

It’s also a great technique for situations where you’ve got to use third-party graphics that may not be uniform, as in this example that showcases event posters:

Rare Device shows grid

Rare Device, designed by Meg Lewis of Ghostly Ferns for Aeolidia

And in this example showing products from a variety of websites:

The American Edit Must-Haves grid

The American Edit, designed by MAEMAE Paperie

Masonry grids are a nice way to break up a page layout and keep things feeling consistent while allowing for variety, as in this example, where longer quotes are accommodated without making the page feel unduly messy (also, note that the layout model works for both text and images):

GREER Chicago Press & Praise grid

GREER Chicago, designed by Meg Lewis of Ghostly Ferns for Aeolidia

Create Your Own Masonry Layout

Now for the technical part of the post, let’s look at how to actually make this kind of layout happen. There are a couple of different jQuery plugins out there for this, but my favorite is David DeSandro’s Masonry.

History Note

For those of you who are into this sort of thing, I am fairly certain that this Masonry plugin was the original inspiration/ tool behind Pinterest’s version. I’ve had that in my head for awhile now, but when I went to check Google to see if I could verify it as fact, the closest I could get was this old post where the author hints that Pinterest based theirs on his but specifies that they use their own version. So not totally conclusive, but pretty close.

Anyway, Step 1: Include the Scripts

As with any jQuery integration, one of the first steps is to actually include the scripts in your site.

Expand for WordPress Directions

In WordPress, it turns out Masonry is already bundled with WordPress core (as are a number of common scripts), so you don’t even have to upload the file yourself. However, the version bundled is currently a bit behind so you may want to handle it manually until that gets updated.

If you’re using the bundled version, all you’ll do is enqueue it using the name WordPress has given it:

/**
 * ENQUEUE SCRIPTS
 */
function emitheme_scripts_method() {
  wp_enqueue_script(
    "jquery-masonry",
    array("jquery")
  );
}
add_action("wp_enqueue_scripts", "emitheme_scripts_method");

The second parameter makes sure jQuery is loaded before Masonry, and while the current version of Masonry doesn’t actually require jQuery I believe the WordPress-bundled version does.

If you were only using Masonry on a particular page template, you could use a conditional to only enqueue the script on that page, e.g.:

/**
 * ENQUEUE SCRIPTS
 */
function emitheme_scripts_method() {
  if ( is_page_template( "page-masonry.php" ) ) :   
    wp_enqueue_script(
      "masonry",
      array("jquery")
    );
  endif;
}
add_action("wp_enqueue_scripts", "emitheme_scripts_method");

In case you’re wondering, Emi is the name of my starter theme, which will be released in the next week or so.

If you want to use the most recent version of Masonry, you’d download the file from the masonry site and then upload it to your theme and your enqueue snippet would look like this:

/**
 * ENQUEUE SCRIPTS
 */
function emitheme_scripts_method() {
  if ( is_page_template( "page-masonry.php" ) ) :   
    wp_enqueue_script(
      "masonry",
      get_template_directory_uri() . "/assets/vendor/masonry.pkgd.min.js",
      array("jquery")
    );
  endif;
}
add_action("wp_enqueue_scripts", "emitheme_scripts_method");

Note the added file path parameter.

Evidently, this version issue is on the radar to be fixed but that fix introduces some other interesting potential issues/ differences, which you can read about in the Trac ticket notes if you’re so inclined.

Expand to view Shopify directions

For Shopify, the snippet to include is:

{{ "masonry.pkgd.min.js" | asset_url  | script_tag }}

That goes in the theme.liquid file in the <head></head> section.

Make sure to actually upload the file itself as well – it’ll go into your theme’s assets directory.

If you’re using images in your layout, you will likely also want to include imagesLoaded in order to have the layout adjust to the images after they’re loaded.

WordPress Example

To do this, just upload that file to your theme (I put mine inside a /assets/vendor/ directory structure), and then add it to your enqueue function:

/**
 * ENQUEUE SCRIPTS
 */
function emitheme_scripts_method() {
  if ( is_page_template( "page-masonry.php" ) ) :   
    wp_enqueue_script(
      "masonry",
      get_template_directory_uri() . "/assets/vendor/masonry.pkgd.min.js",
      array("jquery")
    );
    wp_enqueue_script(
      "imagesLoaded",
      get_template_directory_uri() . "/assets/vendor/imagesloaded.pkgd.min.js",
      array("jquery")
    );
  endif;
}
add_action("wp_enqueue_scripts", "emitheme_scripts_method");

Shopify Example

Or add another line for it in Shopify:

{{ "masonry.pkgd.min.js" | asset_url  | script_tag }}
{{ "imagesloaded.pkgd.min.js" | asset_url  | script_tag }}

Step 2: Create the markup

The markup structure is pretty simple, just a container with a bunch of items in it. For example:

<div id="grid">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

If this were a grid of posts in WordPress, the loop might look something like:

<?php if ( have_posts() ) : ?>
  <div id="grid">
    <?php while ( have_posts() ) : the_post(); ?>
      <div class="item">
        <?php the_post_thumbnail(); ?>
        <h2><?php the_title(); ?></h2>
      </div>
    <?php endwhile; ?>
  </div>
<?php endif; ?>

It doesn’t have to be <div> elements in the group – it could be list items or just images.

As a note about images – I find it helpful to include the width and height in the image markup. In WordPress, this isn’t automatically there depending on which image template tag you use, so just something to keep in mind.

Step 3: Initialize Everything

Here is the snippet to initialize Masonry on your grid:

<script>
jQuery(document).ready(function($){
  var $container = $("#grid");
  // initialize Masonry after all images have loaded  
  $container.imagesLoaded( function() {
    $container.masonry({
      columnWidth: 150,
      itemSelector: ".item",
      gutter: 15
    });
  });
});
</script>

You can put that in a number of places depending on how you’re setting up your theme but a good place to start if you’re not sure would be in the footer, before the closing </body> tag.

If you are NOT using imagesLoaded then your snippet would be more like:

<script>
jQuery(document).ready(function($){
  $("#grid").masonry({
    columnWidth: 150,
    itemSelector: ".item",
    gutter: 15
  });
});
</script>

We’ve set three options in those snippets:

  • Column Width (adjust that to match your items/ layout)
  • Item Selector (the class on your grid items, or you could do something like #grid li if you were using a list)
  • Gutter, which is the horizontal spacing

All the various options are listed on the Masonry site.

Step 4: Style It

I typically give my items some basic CSS styling to get started:

.item {
  float: left;
  margin-bottom: 15px;
  text-align: center;
}

The bottom margin handles the vertical spacing, where the gutter option handed the horizontal spacing. Usually I want to center all the content in each grid item, so the text-align handles that as well.


There you have it, Masonry grids!

Q&A: Four Methods for Client Education & Training

Q&A: Client Education & Training

I’ve been asked a few different times how I handle teaching clients to manage and update their content once their site is finished. While I enjoy hearing from my clients after we’ve wrapped a project and often work with people ongoing to add templates or on new projects, it’s important to me that clients are able to manage all of their content without relying on me and my team.

In order to make that happen, I use four different methods for sharing information with clients and training them to use the content management system to manage their content and their site as a whole.

1. Documentation

For early decision points and also for general information on website concepts, I provide a lot of documentation in written format in one of two places.

Blog Posts on Common Topics

A lot of my documentation for clients is right here on my blog. Many of my posts are just elaborations on answers I’ve first sent to clients via email, which is great because once they’re published I can just send the link instead of re-answering the question.

My posts on backing up & updating WordPress, prepping images for the web and aspect ratios are all examples of blog posts that started out as client education emails.

Non-Post Documentation

This is for things that come up again and again in email conversation with clients but aren’t necessarily right for blog posts, I’ve started compiling additional documentation via HelpScout using their Docs feature.

Documentation via HelpScout

There is some overlap between this content and my FAQ page. The difference is that the HelpScout documentation, while not protected or completely hidden, is intended for clients, whereas the FAQ is more public-facing. The integration with HelpScout email (which I use for my general email inbox, shared with my business assistant) is partly what makes this a great system for us, as we can really easily insert links to the articles into emails.

2. Admin Structures

When we’re actually building a site, my team and I make sure to prioritize the content management experience of the end user, making it easy for the client to update their content even when it means a little more work for us.

While this is not explicitly part of client education, it is an approach that makes our client education needs down the line more manageable.

Example Admin Structures

In practice, this means we use tools like Advanced Custom Fields to create really clean, nice-looking, intuitive admin screens specific to each page template.

Scouted Recommendations Model

Click to zoom, from the Scouted NYC case study

You can see more examples of how we’ve done this for various sites by looking through my case studies.

3. General Tutorials

Since I use existing content management systems that already have great structures for many things a client will need to do, I also make make use of existing documentation where possible. This saves time but also ensures that clients get really really great information – better than I’d be able to provide.

WordPress Video Tutorials

For WordPress, I provide clients with access to WP101′s premium video tutorials, which I’ve licensed and share via a private area on my site:

WP101 page on ZoeRooney.com

These videos cover all the WordPress “basics” including working with blog posts, categories, comments, menus, widgets, and plugins. The videos are a higher quality than I’d be able to provide and are updated with changes to WordPress core.

Shopify Written Documentation

For Shopify, I link out to specific pieces of documentation in the Shopify manual and I’ve also been impressed with the third-party Shopify & You e-book (affiliate link), which is $39 and very very thorough.

4. Custom Tutorials

While those general resources have proven to be quite helpful, since we customize the admin to handle the various page templates we’re creating for clients I typically also create a informal video tutorial covering our customizations. I’ve found that video is great because the client can watch and re-watch it at their convenience, rather than feeling like they have to absorb all the information in real-time via a screen share or real-time training session.

Example Site-Specific Video Tutorial

Here’s an excerpt from a recent tutorial I created for Clara Persis:

That’s about half the video, and the rest of it walks through the remainder of the pages.

Underneath the Videos

You can see from watching that example that these videos are not rehearsed – it is just me talking through the pages and features one by one the same way I’d do it if I were sitting at the computer next to Clara. The informal, unscripted nature ensures that I can record these videos quickly, which keeps it feasible.

Technology-wise, I use Quicktime (the regular version that comes with Macs) to record along with the microphone built into my UrbanEars headphones. I then upload the video my Vimeo Pro account via the built-in Quicktime “Share” feature and email the review page link to the client, with permission set such that only people with the link can access the video, no sharing is allowed, and the client can download the file to their computer if they so choose.


So that’s it – the four methods I use to education clients and help them learn to use their site! Of course, I also try to be flexible to meet clients’ individual needs, so there have been times when I’ve supplemented these methods with phone and/or screen-share training, or even with in-person training for an entire team. Usually, though, the videos and written documentation are a great, lasting solution for both me and my clients.