Category: WordPress

Organizing Your WordPress Theme’s CSS

Stylesheet files can get ridiculously long. The Twenty Eleven theme has over 2500 lines  of css (unminified). That can be a pain if you’re trying to make significant adjustments to a theme. Quite a few theme frameworks take a more modular approach to css and separate their CSS into different files. That is a big improvement, but it does come at a cost. The more files you import, the more requests you’re making to the server. Secondly, persons who have to work with the CSS now need to figure out what files contain what style specifications. Thirdly, the built-in editor in the administration screen is not that user-friendly when you have to hunt down specific files instead of editing the basic style.css file.

I use the LESS language these days which makes CSS management heaps easier. You can have multiple less files and you can generate a single css file from those files. The question now becomes: what’s a good way to organize the less files?

There are quite a few different ways to organize your CSS logically and the problem here is that you can easily run into overlap situations. Do you put your CSS targeted for small screens in a separate file, or do put them in the file that targets those specific elements? If we have a file dedicated to structure as well as for different content elements, from widgets, to post-formats, how do we make the separations? If you have CSS for your images, do you include them with the file that handles galleries, or do you put them in the file that addresses media elements. These are just a few examples.

So far, I haven’t come up with a system that has perfect clarity. I don’t think it’s possible. The conclusion I’ve come to is that you have to do what’s most in alignment with your workflow. If you have to figure out what file to make an adjustment, there should be no more than 2 obvious candidates to choose from, and they should be obvious. If I want to make an alignment adjustment to a widget area for tablet screens, I don’t want to have to check a widgets file, a structure file, an alignments file and a responsive file.

I’ve been taking advantage of the LESSphp library to get around some of these file organization dilemmas. You can drop in your media queries like you would do a mixin. That way you can keep all the CSS relating to a group of elements organized in one logical area. There is one downside at the moment: the output isn’t perfect yet since it can cause your CSS to contain a lot of redundant data (similar media query statements aren’t grouped automatically into a single media query). I’m working on a css post-processor (the Flawless Styles Compiler plugin) to fix this and make the output cleaner and lighter in general.

Here’s my current file organization setup for those that are interested:

  • variables.less
  • mixins.less
  • reset.less
  • structure.less
  • typography.less
  • general.less
  • navigation.less
  • header-area.less
  • footer-area.less
  • page-templates.less
  • post-formats.less
  • media-elements.less (images, video, audio etc)
  • form-elements.less (input elements, search box, contact forms etc)
  • ui-elements.less (button’s etc)
  • sliders.less
  • gallery.less
  • comments.less
  • states.less
  • print.less
  • widgets.less
  • misc.less

Potential tweaks to this organization? I’m thinking further separation of individual page templates and post formats. Post types can fall into either page template or post format category but it might make sense to have a dedicated file for post types as well.

LESS and convenient file organization make things a lot easier. But I want managing a site’s design to be even easier and this is why I’m building a plugin called ‘Flawless Styles Compiler’ which will take CSS development for WordPress to a whole new level.

How To Send Users To Different Welcome Pages Based On User Level In S2Member

A very common requirement for membership sites is the ability to send a user that is logging in to a specific home page. With S2Member there are a couple of ways to accomplish this. I came across some solutions involving javascript, which I think is a bad idea for a number of reasons. I’ll share one method here that is relies on some server side magic instead. To implement this you’ll need to write a little bit of code and insert it in your plugin file, your theme’s functions.php or your s2hacks.php file.

The first clue to redirecting users after logging is the UI S2Member provides under ‘General Options’. There is a section called ‘Login Welcome Page’, which is what we’re after. Here S2Member gives you the option to select an existing page from a dropdown. We don’t want that option because it will be the generic welcome page for all user levels/roles. To send users to different pages based on their membership level, we can make use of the field below the drop down.

 Or, you may configure a Special Redirection URL, if you prefer. You’ll need to type in the full URL, starting with: 

http://

A few Replacement Codes are also supported here.

It’s basically a text field that let’s you specify a url. The cool thing is that we can utilize dynamic variables in the url with replacement codes. The solution I’m using here involves using the %%current_user_role%% replacement code as a GET parameter in the url. What you get is a url that looks like

http://yourfabulousmembershipsite.com/?custom_welcome_page=%%current_user_role%%

The words custom_welcome_page can be replaced with a wording of your choosing (make it unique though) and the %%current_user_role%% will be dynamically replaced with the membership level of the user that is signing in.

For the next step, we are going to write the code that tells WordPress to interpret those parameters.

[php]function your_member_site_vars( $vars ){

$vars[] = “custom_welcome_page”;
return $vars;
}
add_filter( ‘query_vars’, ‘your_member_site_vars’ );[/php]

And now WordPress will interpret the parameter we’re using, we have to tell what to do when it is used next.

[php]

function my_login_redirect() {
if ( get_query_var( ‘custom_welcome_page’ ) ) {
$role = get_query_var( ‘custom_welcome_page’ );
// double check if user has that role
if( current_user_can( $role ) ){
wp_redirect( my_member_welcome_pages( $role ) );
exit;
}
}
}

add_action( ‘template_redirect’, ‘my_login_redirect’ );

[/php]

What the above code does is listen to the parameter custom_welcome_page in the url, if it  is found then it will try to redirect the user. To determine the page, we write another function that takes the membership level of the user and returns the appropriate url.

[php]function my_member_welcome_pages( $role ){

// Set the welcome pages in the following array

$welcome_pages = array(
‘subscriber’ => ‘http://www.yourfabulousmembershipsite.com/subscriber-welcome/’,
‘s2member_level1’ => ‘http://www.yourfabulousmembershipsite.com/level1-welcome/’,
‘s2member_level2’ => ‘http://www.yourfabulousmembershipsite.com/level2-welcome/’
);

if( $welcome_pages[$role] ){
return $welcome_pages[$role];
} else {
return ‘http://www.yourfabulousmembershipsite.com/your_default_welcome_page/’;
}
}
[/php]

These functions are the basic functionality needed to create your own custom welcome page redirects for your members.

Would you like to have a plugin with a simple user interface that does this for you? Drop me a line.

 

Check WordPress User Role By ID

While working on a membership site I wanted to retrieve a user’s role by their user id, but I couldn’t find a quick function to do this. WordPress does provide the WP_User object which gives us quick access to all user information, including user roles. To get the user role by a given ID we can do the following in php:

[php]

function get_user_roles( $id )  {
$user = new WP_User( $user_id ); // this gives us access to all the useful methods and properties for this user

if ( $user ) {
$roles = $user->roles; // returns an array of roles
return $roles;
}  else {
return false;
}

}

[/php]

It’s useful to note that it’s possible for a user to have multiple roles, even though most sites and plugins don’t utilize this possibility. What if you want to check if a user has a certain role? We can write a simple function for that as well. In my case I wanted to check if they have the custom role of teacher (a conditional function).

[php]
function user_has_role( $id, $role = ‘teacher’ ){
$roles = get_user_roles( $id ); // retrieves an array of roles
if ( $roles && in_array ( $role, $roles ) ) { // checks if specified role is listed
return true;
} else {
return false;
}
}
[/php]

Adding Drag And Drop Support To wp_editor / TinyMce Part 1

Since WordPress 3.3 a nice new drag and drop uploader was included. It works great because it has fallbacks for older browsers that don’t support the newer HTML5 api. Accessing the file uploader still requires bringing up the media uploader via the upload button. Wouldn’t it be even nicer if we could directly drag and drop our files into our WYSIWYG editor?

The newish wp_editor function also makes it easy to include additional tinymce editors for our plugins and themes. I was looking for a way to add the tinymce editor to P2 and include a quicker way to drag and drop files. Adding the editor is relatively easy now but and it even lets you add the media upload button to the front end, but I want to remove the need for clicking that button.

Possible solutions:

My first thought was to insert the new native uploader inline below the editor so that we could directly drop files into a dropzone without having to navigate to the media uploader. I’m sure it can be done, but it was going to take me too long to do it properly and cleanly.

My second idea was to look for existing plugins that could do all the work, but there don’t seem to be any functional ones in existence that are straightforward to implement and integrate. It also seems a bit overkill to include another uploader when WordPress already can do everything I need.

After that I thought about digging into the filereader api for HTML5 and making my own solution…but then I thought of a shortcut that would be the best of all worlds.

Providing you have the upload buttons enabled for your editor, it’s possible to detect a drag event when a file is being dragged into the editor and automatically fire the native media uploader.

The great thing about this is:

  1. It streamlines the uploading process without adding loading scripts unnecessarily.
  2. It removes one mouse click operation and feels more intuitive than navigating to the uploader manually.
  3. It relies on the native uploader which deals with all the complex stuff, such as fallbacks, inserting the file into the post, setting parameters, attaching the file to the post and so forth. No reinventing the wheel!
  4. It removes the need for a separate ‘drop zone’, which takes up space. Instead, the editor itself is the drop zone.

Implementation:

All we need is a few lines of javascript. What is needed:

– A way of detecting when a file is dragged into our editor that works across all modern browsers

– The id attribute of our editor

– A trigger event to activate the native uploader when a file drag (or drop) is detected. For this we need to know how to select the media upload button with a selector.

optional:

some extra magic to add some css styling during the drag and drop operation.

Part 2 will cover the actual code…which I haven’t written up yet. Want to see the final solution? Sign up to the newsletter and you’ll get a notification when it is published.

Access The Main Post ID Anywhere based on the Current WordPress Page

There’s a number of ways to retrieve the post id of a post, but what if your page has multiple loops and you want to retrieve the main post id of the page? In my case I wanted to insert social buttons only on the main content of the page. If you are using the_content filter to add the html for your social buttons, it will show every time any kind of post content is displayed. Some page designs often use several loops to display various pieces of content (especially front pages), so you could end up with an abundance of social buttons – not exactly ideal. My solution then involved checking to see if the currently outputted content was the main content of the page by comparing post ids.

So I looked to see if there was a simple way to access the main post id – even if we are inside a secondary loop. Surprisingly, there doesn’t really seem to be a function for this. The closest thing is a function called get_page_by_path, but that works just for pages. Another idea is to access the $wp_query global variable, but this can be altered when other queries are made. What we can do is store the ID in our global variable when we are certain that $wp_query contains the main post id.

[php]
function main_post_id() {
global $wp_query;
global $main_post_id;
if( is_singular () ) { // ignores index pages for posts, categories, tags, archives etc
$main_post_id = $wp_query->post->ID;
}
}
add_action( ‘wp_head’,’main_post_id’ );
[/php]

Now we can quickly access the post id anywhere on the page, even if you are in a custom loop.

[php]
ID ) {
// do stuff
}
?>
[/php]

Loading CSS mid-page, HTML5, WordPress & Passing Validation Part 2

With HTML5 it’s possible to declare CSS stylesheet inside the body tag. This gives WordPress developers a better solution for including CSS on the fly, such as via a shortcode. It instantly makes several workarounds redundant. The native WordPress function wp_enqueue_style can now be called mid-page, which will print a stylesheet in the footer. Two disadvantages arise from this method and here is an alternative solution that solves it.

In part 1 we learned that

<link>

elements inside the body tag don’t validate at the moment. While browsers handle them just fine, it’s always nice to pass validation without errors. An alternative to this was to alter the output and use the style tag with the new scoped attribute instead. Then, the code will show up valid like:

<style scoped>@import url(stylesheet.css); </style>

The second disadvantage is that our CSS now loads at the end of the page, after the content we want to style. This may cause some styling issues during pageload. Since we can load the CSS anywhere inside the body tag, there is no real reason why it needs to be printed in the footer. If we do that, we also limit the styling issues on pageload.

We can write a function that prints the stylesheet declaration immediately. Let’s say you have a shortcode that inserts a slider, your shortcode would include a special function that prints the CSS before the rest of the slider output. The easy way would be simply to write a function that outputs the required html directly and this is what many developers tend to do. WordPress has specific ways of dealing with styles and scripts to help reduce conflicts and redundancies, so it is important we take advantage of that. So what we are going to do is tap into the API WordPress uses.

The first step is to register your CSS stylesheet with wp_register_style by wrapping it into a function and loading it into the wp_enqueue_scripts hook. Here is an example where we are including the Media Element Player.
<pre>
function register_mediaelementjs() {
wp_register_script( ‘mediaelementjs’, get_bloginfo(‘template_url’).’/inc/mediaelementjs/mediaelement-and-player.js’, array(‘jquery’), ‘2.6.3’, true );
wp_register_style( ‘mediaelementjs’, get_bloginfo(‘template_url’).’/inc/mediaelementjs/mediaelementplayer.css’ );
}
add_action( ‘wp_enqueue_scripts’ , ‘register_mediaelementjs’ );

Next we want to make a function that runs through the styles API. In other words, we want to check if our style has been registered (this is important because a user might decide to deregister your style) and hasn’t been printed already. We also have to make sure that WP knows we printed the style to avoid duplication.

function print_inline_stylesheet( $handle ) {
	// continue only if the style has been registered and hasn't been printed yet. 
	if ( wp_style_is( $handle, 'registered') && ! wp_style_is( $handle, 'done' ) ) {
		// gain access the wp_styles object 
		global $wp_styles;
		// make sure the style is formatted with html 5 markup
		add_filter( 'style_loader_tag', 'html5_inline_stylesheet', 10, 2 );
		$print = $wp_styles->do_item( $handle );
		// set this style to 'done' status
		$wp_styles->done[] = $handle;
		// remove from to do just in case the style was invoked elsewhere for the footer.
		$to_do = $wp_styles ->to_do;
		if ( is_array( $to_do ) ) {
			foreach( $to_do as $key => $to_do_handle ) {
				if( $to_do_handle == $handle ) {
					unset( $wp_styles->to_do[$key] );
				}
			}
		}
	}	
}

If you are outputting functionality via a shortcode you will want to call print_inline_stylesheet before your output. The handle argument needs to be passed to it and coincide with the handle you passed to register_style for your stylesheet. All that is left here is our function for modifying the standard WordPress output.

function html5_inline_stylesheet( $output ) {
	$url = preg_match("/(href=')(.+)(' type)/", $output, $styleurl);
	$output = '<style scoped>@import url('.$styleurl[2].');</style>';
	return $output;
}

Notes:
– I haven’t tested this with CSS stylesheet dependencies – the code may need some alterations for that.
– If you are including the functions in your project, remember to add a prefix unique to your theme or plugin in front of all the functions.
– I haven’t tested this is in all browsers, but from what I’ve researched this should work universally.
– HTML5 is still in a working draft, the scoped attribute hasn’t been set in stone – it’s possible things may change.
– To validate, you need to make sure the validator is set to HTML5.

If you have thoughts on improving this solution or the code, please leave some feedback below!

UPDATE 5/05/2013
For copy pasters, in the above example I used Media Element JS which is now shipped by default with WP 3.6+. While the example was for demonstration purposes, if you are using media element js, don’t enqueue your own version, load the one that ships with WP.

Using CSS3 PIE with WordPress Plugins and Themes

UPDATE: I have posted an updated method for the latest version of PIE (v2)

CSS3 PIE is a fantastic tool to achieve support for CSS3 styles in versions of Internet Explorer, such as IE& and IE8. If you have been trying to include PIE with your WordPress project you might have had some problems with the way PIE is loaded. Below is an effective solution that works for plugins and themes without having to move “PIE.htc” into the root directory of a site and also without needing to dynamically insert the path to PIE using php in your CSS.

In our css, instead of using

[css]

behavior: url(PIE.htc);

[/css]

we use:

[css]

behavior: url(/?pie=true);

[/css]

If your website is located at http://yourwebsite.com/, the browser will look for the PIE file here http://yourwebsite.com/?pie=true, no matter what page you are on. What we need to do is make sure it retrieves the file based on that url. To do that we are going to add a Query variable for PIE and include a template redirect that checks to see if PIE is being called.

[php]

function css_pie ( $vars ) {

$vars[] = ‘pie’;

return $vars;

}

add_filter( ‘query_vars’ , ‘css_pie’); //WordPress will now interpret the PIE variable in the url

function load_pie() {

if ( get_query_var( ‘pie’ ) == “true” ) {

header( ‘Content-type: text/x-component’ );

wp_redirect( get_bloginfo(‘template_url’).’/inc/PIE.htc’ ); // adjust the url to where PIE.htc is located, in this example we are fetching in the themes includes directory

// Stop WordPress entirely since we just want PIE.htc

exit;

}

}

add_action( ‘template_redirect’, ‘load_pie’ );

[/php]

All you have to do is add the above functions in your functions.php or in your plugin file and adjust the path accordingly. If you are running into rendering issues in IE check with the other known issues documented on the CSS3 PIE site.

Updated 8 March 2012:

Changed example to use wp_redirect instead of an include statement.

How to truncate your WordPress RSS Feed at the More Tag

The More tag is a marker you can place in your WordPress posts that breaks up the post into two sections. It’s used to manually determine where the ‘read more’ link is placed when presenting a teaser of a post. WordPress doesn’t respect the More tag in RSS feeds by default, so if your rss feed is set to full or summary, it won’t break your posts as specified by the More tag. I have tried plugins that remedy this, but they fell short so I created my own function.
Read more

How To Query Multiple Custom Post Types with query_posts [WordPress Tip]

A very common WordPress function to modify the posts that are fetched on a page is called query_posts(). There are two ways to pass parameters to query_posts; you can pass an array or you can use the concatenated version. To display multiple post types on a page, the easiest way to do that is to pass parameters as an array argument to query_posts, like so:

$args = aray(
'post_type' => array ( 'post', 'page','event')
);
query_posts($args);

In some case you may want to use the concatenated version instead, for example because you are fetching posts using Ajax and are using GET variables. This is pretty straightforward if you are querying a single post type:

query_posts('post_type=event');

The question is, how do you query multiple post types? Looking at the WordPress codex, it doesn’t quite tell you how this works for post types. You could try similar examples for querying multiple category ids or tags, like this:

// like multiple category ids: doesn't work
query_posts('post_type=post,page,event');
// like multiple tags: also doesn't work
query_posts('post_type=post+page+event');

But you’ll quickly find neither of these examples work. I was about to give up and just use a serialized array for my use case, when I tried another simpler method for passing an array via a GET string:

query_posts('post_type[]=post&post_type[]=page&post_type[]=event');

Lo and behold, it works! In hindsight, this is a common way of passing arrays via a GET string, it just didn’t occur to me as an option because it wasn’t in the Codex.

If you have multiple post types on your WordPress site you can try it quickly by entering this as the url: ‘http://yoursite.com/?post_type[]=post&post_type[]=page’.