Categories
Random

Disqus Comments and Thematic

The Disqus comment platform is a very popular plugin for WordPress, it just happens to work great with the Thematic theme framework. If you aren’t careful though, you may not notice that there is one sneaky problem.

Disqus Comments and Thematic

Thematic will still insert the #comments ID on two different sections postfooter_postcomments and postfooter_postconnect of your child theme, but the ID will no longer exists with the Disqus plugin installed. You will need to modify the php on both to change the ID in the link from #comments to #disqus_thread to provide a correct jump to location on the pages for people clicking on a link to leave comments.

Disqus is a great cheater way to install a nice looking comment system (with features) and not have to spend a ton of time styling the comments section, which can be a pain for a novice. So consider these two different snippet options for using Disqus on a Thematic child theme the ultimate cheat. Just insert one of the below methods in the functions.php of your child theme.

Thematic Option 1

This version removes the postfooter_postconnect completely, it isn’t really needed. With that gone, postfooter_postcomments just needs an override with the correct ID’s and done.


// override existing and kill the postconnect from single pages, unecessary baggage
function childtheme_override_postfooter() {
  global $id, $post;
  if ($post->post_type == 'page' && current_user_can('edit_posts')) { /* For logged-in "page" search results */
    $postfooter = '<div class="entry-utility">' . thematic_postfooter_posteditlink();
    $postfooter .= "</div><!-- .entry-utility -->\n";
  } elseif ($post->post_type == 'page') { /* For logged-out "page" search results */
    $postfooter = '';
  } else {
    if (is_single()) {
      $postfooter = '<div class="entry-utility">' . thematic_postfooter_postcategory() . thematic_postfooter_posttags();
    } else {
      $postfooter = '<div class="entry-utility">' . thematic_postfooter_postcategory() . thematic_postfooter_posttags() . thematic_postfooter_postcomments();
    }
    $postfooter .= "</div><!-- .entry-utility -->\n";
  }
  echo apply_filters( 'thematic_postfooter', $postfooter );
}

// override existing and change #comments to #disqus_thread to provide correct jump location.
function childtheme_override_postfooter_postcomments() {
  if (comments_open()) {
    $postcommentnumber = get_comments_number();
      if ($postcommentnumber > '1') {
      $postcomments = ' <span class="comments-link"><a href="' . apply_filters('the_permalink', get_permalink()) . '#disqus_thread" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
      $postcomments .= get_comments_number() . __(' Comments', 'thematic') . '</a></span>';
      } elseif ($postcommentnumber == '1') {
      $postcomments = ' <span class="comments-link"><a href="' . apply_filters('the_permalink', get_permalink()) . '#disqus_thread" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
      $postcomments .= get_comments_number() . __(' Comment', 'thematic') . '</a></span>';
      } elseif ($postcommentnumber == '0') {
      $postcomments = ' <span class="comments-link"><a href="' . apply_filters('the_permalink', get_permalink()) . '#disqus_thread" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
      $postcomments .= __('Leave a comment', 'thematic') . '</a></span>';
      }
  } else {
    $postcomments = ' <span class="comments-link comments-closed-link">' . __('Comments closed', 'thematic') .'</span>';
  }
  // Display edit link
  if (current_user_can('edit_posts')) {
    $postcomments .= ' <span class="meta-sep meta-sep-edit">|</span> ' . thematic_postfooter_posteditlink();
  }
  return apply_filters('thematic_postfooter_postcomments',$postcomments);
}

Thematic Option 2

This version removes the postfooter_postconnect completely also, but the example also moves the author from the post header to the post footer along with fixing the ID. I am only including this one based on that the last 3 sites I have done all had no author, or had it moved below to the post footer.


// move author from postheader to postfooter, removed post edit also, appears in postfooter also.
function childtheme_override_postheader_postmeta() {
  $postmeta = '<div class="entry-meta">';
  $postmeta .= thematic_postmeta_entrydate();
  $postmeta .= "</div><!-- .entry-meta -->\n";

  return apply_filters('thematic_postheader_postmeta',$postmeta);

}

// add author into the footer entry-utility instead, also kill the post_connect
function childtheme_override_postfooter() {
  global $id, $post;
  if ($post->post_type == 'page' && current_user_can('edit_posts')) { /* For logged-in "page" search results */
    $postfooter = '<div class="entry-utility">' . thematic_postfooter_posteditlink();
    $postfooter .= "</div><!-- .entry-utility -->\n";
  } elseif ($post->post_type == 'page') { /* For logged-out "page" search results */
    $postfooter = '';
  } else {
    if (is_single()) {
      $postfooter = '<div class="entry-utility">' . thematic_postmeta_authorlink() . ' <span class="meta-sep meta-sep-author"> | </span>' . thematic_postfooter_postcategory() . thematic_postfooter_posttags();
    } else {
      $postfooter = '<div class="entry-utility">' . thematic_postmeta_authorlink() . ' <span class="meta-sep meta-sep-author"> | </span>' . thematic_postfooter_postcategory() . thematic_postfooter_posttags() . thematic_postfooter_postcomments();
    }
    $postfooter .= "</div><!-- .entry-utility -->\n";
  }
  echo apply_filters( 'thematic_postfooter', $postfooter );
}

// override existing and change #comments to #disqus_thread to provide correct jump location.
function childtheme_override_postfooter_postcomments() {
  if (comments_open()) {
    $postcommentnumber = get_comments_number();
      if ($postcommentnumber > '1') {
      $postcomments = ' <span class="comments-link"><a href="' . apply_filters('the_permalink', get_permalink()) . '#disqus_thread" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
      $postcomments .= get_comments_number() . __(' Comments', 'thematic') . '</a></span>';
      } elseif ($postcommentnumber == '1') {
      $postcomments = ' <span class="comments-link"><a href="' . apply_filters('the_permalink', get_permalink()) . '#disqus_thread" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
      $postcomments .= get_comments_number() . __(' Comment', 'thematic') . '</a></span>';
      } elseif ($postcommentnumber == '0') {
      $postcomments = ' <span class="comments-link"><a href="' . apply_filters('the_permalink', get_permalink()) . '#disqus_thread" title="' . __('Comment on ', 'thematic') . the_title_attribute('echo=0') . '">';
      $postcomments .= __('Leave a comment', 'thematic') . '</a></span>';
      }
  } else {
    $postcomments = ' <span class="comments-link comments-closed-link">' . __('Comments closed', 'thematic') .'</span>';
  }
  // Display edit link
  if (current_user_can('edit_posts')) {
    $postcomments .= ' <span class="meta-sep meta-sep-edit">|</span> ' . thematic_postfooter_posteditlink();
  }
  return apply_filters('thematic_postfooter_postcomments',$postcomments);
}
Categories
Posts

Front-End Development and SEO on the Go

There are occasions where I am asked to check out a webpage and review ways it could be stronger. While this can be a fairly in depth process, you usually can see a lot at a quick glance and it definitely helps to have the right tools. The problem is I frequently get asked when I am not home with the comfort of all my front-end development or search engine optimization tools I have come to rely on.

Recently on a family visit that was suppose to last a few days, those days quickly turned in to a months time. It was painful to not have all my tools available that I use daily. That is when I recalled reading a article about creating an SEO Thumbdrive by a SEOmoz.org user, while the article focuses on SEO tools, I also needed the front-end side of things.

Enter Portableapps.com

Portableapps.com is a free resource which allows you to use free/open source applications such as web browsers, email applications, and a bunch of other useful tools.

The installer sets everything up perfectly, just make sure to install and search for the apps through its application interface so it knows to handle the updating when updates become available. The fact it will auto update the applications is by far one of the handiest parts.

While my checklist might be a little big, I did end up grabbing a bunch of stuff I might need eventually, obviously these would be some good suggestions.

Customizing Firefox Portable

With the apps installed, next up is customizing Firefox. Still, after all this time, Firefox is my go to choice when it comes to developing, mostly because I am more comfortable with Firebug and other familiar add-ons. Make sure be in your Firefox Portable version while snagging your needed add-ons. I would suggest having a few of these favorites.

Other Portable Friendly Tools

Last but not least, I couldn’t forget my last two must have tools, both which happen to run perfectly on a USB flash drive also. Just make sure to drop them in the /PortableApps/ folder so they are usable from the PortableApps interface, the only thing is they won’t auto update obviously.

Sublime Text 2

By far the greatest thing I have done in a while is switching to the text editor Sublime Text 2, it is bad ass and I still have a ton more to learn. However, it installs beautifully on a USB flash drive, and combined with Dropbox you can set up your Sublime Text user settings at home so you can import them to keep them up to date when needed.

Xenu Link Sleuth

Still an amazing tool after all this time, Xenu Link Sleuth is the perfect link checker which also provides a ton of data. Fast and Easy.

I have a feeling I will update this with a few more tidbits of information, but this resource of links will surely save me a ton of time when I lose or need to create another portable drive.

Anything I missed?

Categories
Posts

Thematic and Modernizr

The Thematic Theme Framework for WordPress is getting older, but if you don’t absolutely need a HTML5 site, there really isn’t any reason not to use it for custom theming. A recent project of mine required CSS3 transitions, but older browsers like IE 6-9 won’t do transitions. That is where the powerful little Modernizr comes in handy, it helps provide a clean and easy way to provide a fallback to keep the page functional.

CSS Transform Fallback

In the above image from PatriotReview.net I can use the latest and greatest CSS3 techniques on the left to turn the text with transitions, but still have graceful fallback on the right for older browsers.

While Modernizr can do a lot more, it is perfect for using with Thematic for CSS fallbacks.

Using Modernizr with Thematic

Snag the script from the Modernizr.com custom build section and check off the CSS features you need to detect, in my case it is CSS3 Transitions. You can select to test for all features which may help when developing, but for production include only what is needed (for speed). Remove the extras which are typically for HTML5 builds, click generate and in your child themes /js/ folder, if you don’t have one, make one and save the file as modernizr.js.

Once you have your script in place, drop this in your functions.php in your child theme. This snippet will work for adding Modernizr to any WordPress installation, not just Thematic.


// script manager template to register and enqueue files
function childtheme_script_manager() {
    
    // wp_register_script template ( $handle, $src, $deps, $ver, $in_footer );

    // registers modernizr script, stylesheet local path, no dependency, no version, loads in header
    wp_register_script('modernizr-js', get_stylesheet_directory_uri() . '/js/modernizr.js', false, false, false);

    // enqueue the scripts for use in theme
    wp_enqueue_script ('modernizr-js');

}
add_action('wp_enqueue_scripts', 'childtheme_script_manager');

Update: 2012-14-6 Previously I was just using wp_enqueue without registering the script, but it is better to both register and enqueue. Minor, but changed to promote best practices.

What the enqueue snippet is doing.

The snippet above is handy also acting as a template to manage scripts, so you can add all your scripts in this one “script_manager” and use the template portion to know the correct order, for more information there is a good article on the correct way to enqueue. Cake.

Is it working?

If you were to right click on the source code, you won’t see it. If you use Firebug, and look in the html code tag, you should see the replacement looking something like this, depending on what classes you selected to add.


<html lang="en-US" dir="ltr" class=" js flexbox canvas canvastext postmessage no-websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients no-cssreflections csstransforms no-csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache">

So now that you have a CSS class to target, you can target that html class and if it isn’t present, it won’t be applied, just like the graphic above. There is a bunch more to Modernizr I am omitting, but I just haven’t had the opportunity to use the more powerful features.

Thematic Sideways Date

So with Modernizr working, I can now take my non-sideways Thematic post date styling article, and change it up by targeting that specific .csstransitions class to only do the fancy CSS3 styling, if it is available. Otherwise just do the default styling which is nothing but displaying the date the date normally, because if you use IE 6, 7 or 8, you deserve it.


.csstransforms .entry-date { position: absolute; top: 60px; left: -65px; width: 96px; heigth: 26px; text-align: center; padding-left: 5px; background: url(images/content-date.png) no-repeat; -webkit-transform-origin: 0 0; -moz-transform-origin: 0 0; -ms-transform-origin: 0 0; -o-transform-origin: 0 0; -webkit-transform: rotate(-90deg); -moz-transform: rotate(-90deg); -ms-transform: rotate(-90deg); -o-transform: rotate(-90deg); }
.csstransforms .entry-date span { font: 14px/26px Tahoma, Verdana, Segoe, sans-serif; color: #f1f1f1; text-align: center; text-transform: none; letter-spacing: 1px; }
.csstransforms .entry-date .year, .csstransforms .entry-date .sep { display: none; }

Thematic 2.0 “no-js” Class

If you need to add the no-js class to Thematic 2.0 for Modernizr to change to js, you can do that with this snippet.


function childtheme_html_class( $class_att ) {
    $class_att = "no-js";
    return $class_att;
}
add_filter( 'thematic_html_class', 'childtheme_html_class' );

This just throws up a class you can use for CSS to detect if JavaScript is enabled, for example on a mobile navigation, since the toggle for the button is what invokes the drop down, if no JavaScript is present, you won’t be able to see the list. With Modernizr if you set up your CSS correctly it will automatically display the list if no JavaScript is available.

If you needed to do this with Thematic 1.+ versions, maybe look into how I did it with Faking the HTML5 Boilerplate conditional classes with Thematic.

Categories
Posts

Faking HTML5 Boilerplate Header with Thematic

I have faked the HTML5 Boilerplate header styling on my Thematic Theme Framework child themes for a while now. I say faking only because this header is typically associated with HTML5 layouts and while Thematic is a solid framework, the code is just not as modern as it could be. Using the HTML5 Boilerplate header method adds a little functionality, while looking cleaner and more modern to the untrained eye when viewing the source code.

HTML5 Boilerplate Header for Thematic

Originally I would pull the header.php from Thematic into my child theme and comment out 2 lines which felt very dirty by creating one more file. Eventually after a little thought, I figured out it is possible to do this all in the functions.php of your child theme.


// recreates the doctype section, html5boilerplate.com style with conditional classes
// http://scottnix.com/html5-header-with-thematic/
function childtheme_create_doctype() {
    $content = "<!doctype html>" . "\n";
    $content .= '<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" dir="' . get_bloginfo ('text_direction') . '" lang="'. get_bloginfo ('language') . '"> <![endif]-->' . "\n";
    $content .= '<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" dir="' . get_bloginfo ('text_direction') . '" lang="'. get_bloginfo ('language') . '"> <![endif]-->'. "\n";
    $content .= '<!--[if IE 8]> <html class="no-js lt-ie9" dir="' . get_bloginfo ('text_direction') . '" lang="'. get_bloginfo ('language') . '"> <![endif]-->' . "\n";
    $content .= "<!--[if gt IE 8]><!-->" . "\n";
    $content .= "<html class=\"no-js\"";
    return $content;
}
add_filter('thematic_create_doctype', 'childtheme_create_doctype', 11);

// creates the head, meta charset, and viewport tags
function childtheme_head_profile() {
    $content = "<!--<![endif]-->";
    $content .= "\n" . "<head>" . "\n";
    $content .= "<meta charset=\"utf-8\" />" . "\n";
    $content .= "<meta name=\"viewport\" content=\"width=device-width\" />" . "\n";
    return $content;
}
add_filter('thematic_head_profile', 'childtheme_head_profile', 11);

// remove meta charset tag, now in the above function
function childtheme_create_contenttype() {
    // silence
}
add_filter('thematic_create_contenttype', 'childtheme_create_contenttype', 11);

HTML5 Boilerplate Style Header Benefits

  • While not as important to some, for me having the cleaner look to the document source is refreshing. It just looks cooler and more modern from a front-end developer perspective.
  • Thematic already provides the ability to read what browser you are using and provides a body class for you, but using a caching plugin completely kills the functionality. Instead this uses the conditional classes on the html tag giving you the ability to target those old pesky Internet Explorer versions.
  • It adds the no-js class for using Moderinizr, most people working with Thematic won’t probably need this, but it allows for the ability to the latest CSS3 techniques while still providing fallback support for older browsers, again, usually versions of IE.
  • 4-26-2012 – Now includes the meta viewport tag for correct scaling for responsive Thematic child themes. This is also the default for non-responsive themes and shouldn’t affect them at all.

New HTML5 Boilerplate Header Style

This is how the new HTML5 style code will appear in the header of the web page.


<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" dir="ltr" lang="en-US"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" dir="ltr" lang="en-US"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" dir="ltr" lang="en-US"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js" dir="ltr" lang="en-US">
<!--<![endif]-->
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Dev Site | Just another WordPress site</title>

Old XHTML Thematic Header Style

This is just for reference so you can see the differences between the above HTML5 version, and the XHTML version.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head profile="http://gmpg.org/xfn/11">
<title>Dev Site | Just another WordPress site</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

In short, I can’t see any reasons not to use this on every one of my child themes function.php files from here on out. If you aren’t using Modernizr, you can remove the no-js classes from the above HTML5 header. Keep an eye out for my next post which will take care of adding Modernizr to the Thematic Framework, it’s just a little overwhelming to include here.

Update: Added the meta viewport tag to aid in responsive child themes for Thematic. Also updated the formatting to the Thematic 0.9.8 svn version, it will work for the 0.9.7 versions, but is better formatted (no tabs/spaces in php) for the new version.

Update: Now works with the Thematic HTML5 Plugin by Karin at invistruct.com.

Update: This is no longer needed for Thematic 2.0+, however because it is such a pain in the ass to do if you need it, I will keep this information up just in case someone needs it.

Categories
Posts

Modifying the Thematic Date Format

While helping someone recently with the Thematic Theme Framework for WordPress, I finally took the extra step and modified the date format (better known as postmeta_entrydate) to be easier to work with. Essentially all I did was modify the date for Thematic to include a few extra span tags that can easily be targeted with CSS. While this is a highly requested feature, I just haven’t had to implement it yet, so after putting it off for long enough, here it is in 3 default styles.

With the current setup, it is intended to be a copy paste solution for starting a Thematic Child Theme and the styling is by no means mandatory. With a little CSS love, you could easily achieve tons of variations since the PHP is all that is required to give you the needed hooks for styling the date.

PHP for Modifications to Thematic’s Date

Insert into your functions.php in your child theme folder.


function childtheme_override_postmeta_entrydate() {
	$entrydate = '<span class="meta-prep meta-prep-entry-date">' . __('', 'thematic') . '</span>';
	$entrydate .= '<span class="entry-date"><abbr class="published" title="' . get_the_time(thematic_time_title()) . '">';
	$entrydate .= '<span class="month">' . get_the_time('M ') . '</span>';
	$entrydate .= '<span class="day">' . get_the_time('d') . '<span class="sep">, </span></span>';
	$entrydate .= '<span class="year">' . get_the_time('Y') . '</span>';
	$entrydate .= '</abbr></span>';

	return apply_filters('thematic_post_meta_entrydate', $entrydate);
}

With the code inserted you won’t see any changes, remember all we are doing here is inserting span tags to style the date and give it some life. The code does not pull the date out of the .entry-meta div tag, it will remain in the markup right where it is intended which is the default setup, shown below.

Thematic Default Date Image

Styling your Thematic Date

I chose as a default to set the date on the outside of the post off to the left, to do this you will need to remove the overflow: hidden; out of the CSS, or override it using overflow: visible;. This is already included in the snippets below, but be sure to check out the examples below for some different styling techniques. Currently there are no images used, all the styling is done through CSS alone.

Custom Thematic Date Style 1

Thematic Calender Style Date Image

Insert into your style.css in your child theme.


#main, #content { overflow: visible; }
.entry-meta { position: relative; }
.entry-date { position: absolute; top: 0; right: 100%; width: 100px; background: #ccc; border: 1px solid #ccc; margin-right: 20px; border-radius: 10px; box-shadow: 0 2px 5px rgba(100, 100, 100, 0.2); background-clip: padding-box; }
.entry-date span { display: block; font: 18px/24px "Helvetica Neue", Helvetica, Arial, sans-serif; color: #666; text-align: center; }
.entry-date .month { background: #ccc; border-radius: 10px; }
.entry-date .day { font-size: 44px; line-height: 50px; background: #333; color: #eee; text-shadow: 2px 2px 2px #888; }
.entry-date .year { background: #ccc; border-radius: 10px; }
.entry-date .sep { display: none; }

I would refer to this example as a Calender Style Date format, it is pretty common and can easily be modified if you choose to use a little more robust graphic.

Custom Thematic Date Style 2

Thematic Circle Style Date Image

Insert into your style.css in your child theme.


#main, #content { overflow: visible; }
.entry-meta { position: relative; }
.entry-date { position: absolute; top: 0; right: 100%; width: 75px; height: 75px; margin-right: 20px; border-radius: 40px; background: #ccc; box-shadow: 2px 2px 3px rgba(100, 100, 100, 0.2), 2px -2px 3px rgba(100, 100, 100, 0.2); border: 5px solid #f6f6f6; }
.entry-date span { display: block; font: 16px/22px Verdana, Arial, Helvetica, sans-serif; color: #666; text-align: center; }
.entry-date .month { margin-top: 5px; }
.entry-date .day { font-size: 30px; color: #eee; font-weight: bold; text-shadow: 1px 1px #333; }
.entry-date .year {  }
.entry-date .sep { display: none; }

This circle is created through CSS, I would highly recommend checking all the available shapes you could change this to by looking into The Shapes of CSS by CSSTricks.com.

Custom Thematic Date Style 3

Thematic Foghorn Style Date Image

Insert into your style.css in your child theme.


#main, #content { overflow: visible; }
.entry-meta { position: relative; }
.entry-date { position: absolute; top: 0; right: 100%; width:100px; margin-right: 20px; border:1px solid #e6e6e6; border-bottom:1px solid #e3e3e3; padding:10px 0; text-align:center; letter-spacing: 1px; box-shadow: inset 0 8px 30px 8px rgba(0, 0, 0, 0.25); margin-bottom:20px; text-shadow: 0 1px rgba(255, 255, 255, 0.8); }
.entry-date span { display: block; font-size: 18px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight:bold; color: #666; font-style: normal; text-align: center; }
.entry-date .month { }
.entry-date .day { font-size:40px; line-height:48px; }
.entry-date .year { }
.entry-date .sep { display: none; }

This style is modeled after the Foghorn WordPress Theme, you may have noticed that Foghorn is the base my current child theme is set up on. So really the credit for this style goes to Devin Price who produced the heart of the theme I use, be sure to check out his site, he does have some awesome WordPress Plugins, like the Options Framework Plugin.

Finishing off customizing the Thematic Meta

In the images, you may notice after the Author section there is now an extra | in the code. This is just the way the Thematic PHP is setup, you can either modify the postheader_postmeta function to remove it through PHP. Or just just set the .meta-sep-entry-date class to display: none;. If you need copy and paste solutions, choose one or the other below. I would recommended the CSS way just because it is by far easiest.

Remove meta separation from PHP


function childtheme_override_postheader_postmeta() {
  $postmeta = '<div class="entry-meta">';
  $postmeta .= thematic_postmeta_authorlink();
  $postmeta .= thematic_postmeta_entrydate();
  $postmeta .= thematic_postmeta_editlink();
  $postmeta .= "</div><!-- .entry-meta -->\n";
  return apply_filters('thematic_postheader_postmeta',$postmeta);
}

Or, remove meta separation through CSS


.meta-sep-entry-date { display: none; }

Any questions, just leave a comment. You can also find more information for Thematic Resources and Thematic Snippets, although both are still under construction and need some TLC, but are very useful nonetheless.

Categories
Posts

WordPress Columns Shortcode

A few months ago, I received a call asking if I knew how to make column shortcodes for a WordPress theme. I answered “No”, but quickly followed up with a explanation of how it should be fairly easy. The hunt for shortcode columns was on, after researching column shortcode examples, I noticed the ones out there were not very flexible when it came to styling. I kept thinking there has to be a better way and it wasn’t until making another shortcode for boxes that I figured out the columns and boxes could be merged into one single shortcode for a developer who wants total control with CSS.

This set of snippets can easily be modified into a plugin, take a look at creating a custom functions plugin for end users for directions. Also hopefully you have your basics down before tackling something like this, not recommended for anyone who doesn’t understand CSS and PHP, although the links in this article should help.

The PHP Columns Shortcode

Insert into your functions.php in the WP theme folder.


function snix_shortcode_columns( $atts, $content = null ) {
    extract(shortcode_atts(array(
	'size'  => 'full', // full width 100% is default
	'color' => '',
	'type'	=> '',
	'align'	=> '',
	'float'	=> '',
	'text'	=> '',
    ), $atts));

	$size = ($size) ? ''.$size : '';
	$color = ($color) ? ' '.$color : '';
	$type = ($type) ? ' '.$type : '';
	$text = ($text) ? ' text'.$text : '';
	$align = ($align) ? ' align'.$align : '';
	$float = ($float) ? ' float'.$float : '';

	if (strpos($size, "last") === false) {
	// if last is not found
	return '<div class="' .$size.$color.$type.$align.$float.$text. ' awesome-box"><span class="box-icon"></span><span class="box-content">' .do_shortcode($content). '</span></div>';
	}
	else {
	// if last is found
	return '<div class="' .$size.$color.$type.$align.$float.$text. ' awesome-box"><span class="box-icon"></span><span class="box-content">' .do_shortcode($content). '</span></div><span class="clearboth"></span>';
	}
}
add_shortcode('box', 'snix_shortcode_columns');

The CSS for the Shortcode Columns

Insert into style.css in the WP theme folder.


/*
	column box sizing - size=""
	default is full width 100%
----------------------------------------------------*/
.one_half, .one_half_last { width:48%; }
.one_third, .one_third_last { width:30.66%; }
.two_third, .two_third_last { width:65.33%; }
.one_fourth, .one_fourth_last { width:22%; }
.three_fourth, .three_fourth_last { width:74%; }
.one_fifth, .one_fifth_last { width:16.8%; }
.two_fifth, .two_fifth_last { width:37.6%; }
.three_fifth, .three_fifth_last { width:58.4%; }
.four_fifth, .four_fifth_last { width:67.2%; }
.one_sixth, .one_sixth_last { width:13.33%; }
.five_sixth, .five_sixth_last { width:82.67%; }
.one_half, .one_third, .two_third, .three_fourth, .one_fourth, .one_fifth, .two_fifth, .three_fifth, .four_fifth, .one_sixth, .five_sixth { float: left; margin-right: 4%; }
.one_half_last, .one_third_last, .two_third_last, .three_fourth_last, .one_fourth_last, .one_fifth_last, .two_fifth_last, .three_fifth_last, .four_fifth_last, .one_sixth_last, .five_sixth_last { float: left; margin-right:0;  clear: right; }
.full.awesome-box { clear: both; }
.clearboth { clear: both; display: block; font-size: 0; height: 0; line-height: 0; width:100%; }
/*
	column box defaults
----------------------------------------------------*/
.awesome-box { border: inset 1px solid #fff; margin-bottom: 20px; background: #f4f4f4; position: relative; -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); border-radius: 5px; }
.awesome-box span.box-content { padding: 10px; display: block; }
.box-content h1, .box-content h2, .box-content h3, .box-content h4, .box-content h5, .box-content h6 { padding-top: 0; }
/*
	column box type - type=""
        alert is a custom box example
----------------------------------------------------*/
.none.awesome-box { border: none; background: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; border-radius: none; }
.alert.awesome-box span.box-icon { position: absolute; top: 25px; left: -10px; height: 46px; width: 48px; background: url(../images/icon.png) no-repeat 0 -46px; }
.full.alert.awesome-box span.box-icon { position: absolute; top: -5px; left: -10px; height: 46px; width: 48px; background: url(../images/icon.png) no-repeat 0 -46px; }
.alert.awesome-box span.box-content { padding-left: 30px; }
/*	
	column box colors - color=""
----------------------------------------------------*/
.blue.awesome-box { background: #2daebf; }
.green.awesome-box { background: #2fc950; }
.grey.awesome-box { background: #a7a8a7; }
/*	
	column box float - float=""
----------------------------------------------------*/
.floatright.awesome-box { float: right; margin-left: 4%; margin-right: 0; clear: none; }
.floatleft.awesome-box { float: left; margin-right: 4%; clear: none; }
/* 
	coluumn box align - align=""
----------------------------------------------------*/	
.aligncenter.awesome-box { clear: both; display: block; margin-left: auto; margin-right: auto; float: none; }
.alignleft.awesome-box { display: block; margin-right: 4%; float: left; }
.alignright.awesome-box { display: block; margin-left: 4%; float: right; margin-right: 0; }
/*
	column box text - text=""
----------------------------------------------------*/
.textcenter.awesome-box { text-align: center; }
.textleft.awesome-box { text-align: left; }
.textright.awesome-box { text-align: right; }

The CSS shows possible options, but with fairly minimal styling. The shortcode attribute of size=”” will control the flexible widths, type=”” will allow you to have specific variations from your original default boxes. The type=”” attribute comes with 2 basic set ups for examples, .alert which inserts a icon and .none which overrides the CSS of the default to not show any options. The rest is fairly self explanatory, color, float, text and align which are just more CSS hooks so these boxes can do damn near anything.

You can download the image used for the icon type, it really isn’t necessary though since you will obviously want your own and really this is just a place holder. If you want it for a quick example, place the image in the root directory of your WordPress theme in the images folder.

Fixing wpautop in shortcodes

Insert into functions.php in the WP theme folder.


// clean up formatting in shortcodes
function snix_clean_shortcodes($content) {   
	$array = array (
		'<p>[' => '[', 
		']</p>' => ']', 
		']<br />' => ']'
	);

	$content = strtr($content, $array);
	return $content;
}
add_filter('the_content', 'snix_clean_shortcodes');

As mentioned in my WordPress Shortcode Buttons post, the little snippet above is needed only once to fix formatting on all shortcodes the auto line breaks <br> and empty paragraphs <p></p> inside the shortcodes without disabling wpautop and wptexturize completely. I would not recommend completely disabling the wpautop and wptexturize feature because all paragraphs and line breaks will need to be manually inserted which is a major hassle, especially for clients.

Drawbacks you should know

One thing you should absolutely know about is you can not nest these columns inside each other. Nested shortcodes get a little more complicated, if you needed nesting technically you could just reuse the PHP again, rename the shortcode from box to inner-box, the key is the PHP shortcode needs to have a different name to nest correctly.

You will need to manually insert the HTML into the boxes, so if you need a header and paragraph, these tags will need to be manually inserted. I really think this is half of what makes them very powerful though, so it just depends how you look at them. If you strip out the shortcodes you will still have correctly formatted text, careful attention was paid to keep these a styling element and not to promote poor coding practices summed up nicely on a article by Justin Tadlock called Dealing with Shortcode Madness. Pay close attention to his mention of the “lock in” effect which some other shortcode columns for do, ones with a “Title” as an attribute which handles headers in the columns would be perfect example.

Update: Justin Tadlock has created a Grid Columns shortcode plugin which trumps everything out there.