Advanced Layout Templates In WordPress’ Content Editor

Advertisement

As a Web designer, I often find myself building WordPress-based websites that will ultimately be updated and maintained by clients who have little to no experience working with HTML. While the TinyMCE rich-text editor is great for giving Web content managers of any skill level the tools they need to easily style and publish their posts to a degree, creating anything beyond a single column of text with a few floated images generally requires at least a basic understanding of HTML.

multi-col-layout-featured

This article shows you an easy-to-implement trick that enables even the least tech-savvy of clients to manage multi-column content layouts within the comfort of the WYSIWIG editor. And for you advanced users, it’s still a great way to standardize and streamline your content entry.

Creating A Custom Layout

All we’re really going to do here is inject a few HTML elements into the editing window and style them. WordPress’ default_content filter allows us to insert set content into any post as soon as it’s created so that our clients don’t have to. This filter is also great for adding boilerplate text to posts.

The Back End

By adding the following to functions.php, each new post we create will come pre-stocked with two divs, classed content-col-main and content-col-side, respectively. I should note now that this code has been tested only in WordPress version 3.0 and up:

<?php
   add_filter( 'default_content', 'custom_editor_content' );
   function custom_editor_content( $content ) {
   $content = '
      <div class="content-col-main">

      This is your main page content

      &nbsp;

      </div>
      <div class="content-col-side">

      This is your sidebar content

       &nbsp;

      </div>    
   ';
   return $content;
   }
?>

A couple of things to note:

  • The default_content filter is fired only when a new post is created; any posts or pages that existed before you added this code will not receive this content.
  • The line spacing and additional &nbsp; are not essential, but I’ve found them to be useful for preventing a few of TinyMCE’s little quirks.

Now we just need to give it some style. Add the following to functions.php:

<?php
   add_editor_style( 'editor-style.css' );
?>

The add_editor_style() function looks for the specified style sheet and applies any CSS it contains to the content in our TinyMCE editing window. If you don’t specify the name of a style sheet, it will look for editor-style.css by default, but for the purpose of this article, I’ve written it out. Create a style sheet named editor-style.css, and place it in the theme folder, with the following styles:

body {
   background: #f5f5f5;
}

.content-col-main {
   float:left;
   width:66%;
   padding:1%;
   border: 1px dotted #ccc;
   background: #fff;
}

.content-col-side {
   float:right;
   width:29%;
   padding:1%;
   border: 1px dotted #ccc;
   background: #fff;
}

img { /* Makes sure your images stay within their columns */
   max-width: 100%;
   width: auto;
   height: auto;
}

Now, when you create a new post, you will see two columns that you can type or paste your content into:

Example of a multi-column template in WordPress’ TinyMCE editor
This basic multi-column template will now appear any time you create a new page or post.

And there you have it: a simple multi-column template in your content editor. You can go back and edit the default_content and editor-styles.css to adapt the content layout to your needs:

Example of an advanced multi-column template in WordPress’ TinyMCE editor
Use this technique to create your own layout templates, customized to your content.

The Front End

When your post is displayed on the front end of the website, the content will still appear in a single column, as before. The styles you wrote out in editor-style.css do not get passed to the front end of the website. However, by viewing the page source, you’ll see that the divs we created with our custom_editor_content() function have been passed through and are wrapping the different sections of the content. Simply open style.css (or whatever style sheet you’re using for your theme) and style to your heart’s desire.

Example of a WordPress post designed with a customized multi-column layout
This technique applies not only to the visual layout of content. Use JavaScript to target specific containers to make on-the-fly slideshows and other dynamic effects.

Get More From Your Templates

Beyond just opening up new styling possibilities, this technique can also be used to create objects to target later with JavaScript.

Example of a WordPress advanced layout post using different sections for Javascript-enabled tabs

In the example above, we were able to turn a series of content areas into more easily digestible tabbed sections for the user, while still allowing the administrator to update all of the information on one page. These are just a few of the many ways you can take your WordPress templates further.

Templates For Templates

The code above will simply apply the same layout and styling to all of your posts, pages, custom posts… anywhere the TinyMCE editor appears. This is probably not ideal. By adding conditional statements to the custom_editor_content() function above, you can serve a different default layout template to each of your post types:

<?php
   add_filter( 'default_content', 'custom_editor_content' );
      function custom_editor_content( $content ) {
         global $current_screen;
         if ( $current_screen->post_type == 'page') {
            $content = '

               // TEMPLATE FOR YOUR PAGES

            ';
         }
         elseif ( $current_screen->post_type == 'POSTTYPE') {
            $content = '

                // TEMPLATE FOR YOUR CUSTOM POST TYPE

            ';
         }
         else {
            $content = '

               // TEMPLATE FOR EVERYTHING ELSE

            ';
         }
         return $content;
       }
?>

You can style all of your default content elements in the editor-style.css file, but if you’d like to use a different style sheet entirely for each post type, you can do so with this snippet from WPStorm1:

<?php
   function custom_editor_style() {
      global $current_screen;
      switch ($current_screen->post_type) {
         case 'post':
         add_editor_style('editor-style-post.css');
         break;
         case 'page':
         add_editor_style('editor-style-page.css');
         break;
         case '[POSTTYPE]':
         add_editor_style('editor-style-[POSTTYPE].css');
         break;
      }
   }
   add_action( 'admin_head', 'custom_editor_style' );
?>

Add the above to your functions.php file, and then create the editor-style-[POSTTYPE].css files to use different style sheets for the corresponding post types. Just replace [POSTTYPE] with the name of your custom post type. Extend the code above by adding new cases for each additional post type.

Alternatively, you could use the following code to automatically look for a style sheet named editor-style- followed by the name of the post type that you’re currently editing. Again, just make sure that the suffix of the new style sheet you create matches exactly the name of the post type.

<?php
 function custom_editor_style() {
   global $current_screen;
   add_editor_style(
   array(
      'editor-style.css',
      'editor-style-'.$current_screen->post_type.'.css'
    )
   );
 }

 add_action( 'admin_head', 'custom_editor_style' );
?>

(In this snippet, editor-style.css will also be included on all post-editing pages, in addition to the style sheet that is specific to that post type, which will be named editor-style-[POSTTYPE].css.)

Conclusion

While this method does have its drawbacks — it assumes you already know the layout that your client wants to give their content, and the layout structures cannot be easily edited by the client themselves — it does enable you to create more interesting sandboxes for your client to play in, while encouraging a standardized format for the content.

If the client decides they don’t want to use a pre-defined container for a particular post, they can simply click inside the container and hit Backspace until all the content is gone, and then hit Backspace once more, and TinyMCE will delete the div wrapper, leaving a clean slate for them to work with.

I hope you’ve found this little technique useful. I’m excited to see all of the ways you guys will customize and improve it for more dynamic layouts.

Additional Resources

(al)

↑ Back to topShare on Twitter

  1. 1

    Zachary Schuessler

    October 14, 2011 7:41 am

    Great post David!

    I had a layout that required a nested div on one of the columns, and it seems TinyMCE was trying to be too helpful and ran into problems. So my solution was to get the contents of each column (I have three) and then display them on the page/post as I needed, so I may apply markup.

    My solution requires PHP DOMDocument, which requires PHP 5. Note, you can also do this with any DOM parser:
    http://pastebin.com/5Xn17yKT

    Would be nice to make a plugin so you can use each column similar to the_content(). I may work on this if others have interest in it?

    Cheers.

    0
  2. 2

    An interesting technique, but definitely one to file under “Use if nothing else works” rather than to be seen as another good trick for developing a theme. I think most situations where this might be used would be better served using additional custom meta boxes with mulitple TinyMCE fields (both techniques are pretty straight-forward these days, given either one of many plugins or a quick Google). Putting presentational markup into the post content obviously mixes up, er… presentation and content! We all end up mixing these a bit, but I think the above technique goes too far, especially given there’s other options for tackling the same issue in a more flexible and future-proof way.

    0
    • 3

      Thanks Steve,

      On an ideological level, I agree with both what you’ve said, and the separation between presentation and content concept as a whole. Personally, I also prefer entering more complex content like this in custom fields.

      However, in practice, I’ve often run into clients who are easily overwhelmed by rows of custom fields and multiple editor windows that correlate to different columns, and they could care less about my arguments for “a better web”. They just want a truer “What-You-See-Is-What-You-Get” experience, similar to what you’d find in programs like DreamWeaver. And while I’m also well aware of the messiness those programs have cause over the years, I’ve developed this technique in the hopes to find a balance between the two.

      0
      • 4

        It’s definitely a “way to go” for clients…Custom Meta boxes are really tricky for them,
        Nice article,
        Thx

        0
      • 5

        David, I have to agree with you. Ideally, clients would easily understand that entering content into the custom meta data boxes will fill out their pages, but in my experience that’s not the case. Your approach provides non-technical people with a visual guide through the build out of a given page. It creates a more approachable and easy-to-understand interface that will encourage users to come back and create new content. As developers providing our clients with the ability to manage their own content, we need to make that process as simplified as possible.

        0
      • 6

        You’re so rigth David. There is always more than one way to solve needs but the most “client level” should be the first avoiding precisely that the post sale support become a pain in the ass. I personally found this a really good solution and still semantic and standards complaining if the client does not mess the code later.

        Thanks a lot for your post.

        0
  3. 7

    Actually i think this is extremely handy…Thanks for showing this, guys!

    Its simple for the client to ‘get’, easily made awesome by some simple jquery, DOES NOT use any plug-ins which is great, leverages the default hooks of WP, can be bundled with a themes functions.php, is undo-able by a simple backspace, and by being able to target post-types, is very useful for some clients.

    It makes the clients life easier, and the coders too. Whats not to LOVE!?

    One question…Is there any way to target custom page templates’ default content? That way regular pages are left alone, and multiple layouts are possible, for pages at least?

    0
    • 8

      Thanks for your response Sam — glad you find it useful :)

      As is, you would not able to target the default content to a specific Page Template using the methods I described above. The problem is that the default_content filter we’re using is only fired when a page or post is first created, and at that time, the page will have no template associated with it to look for.

      In order for these custom layouts to be targeted to Page Templates, you’d have to wait until you select a page template and save the post before firing our function, or possibly grab that selection event with some AJAX (making sure in both cases to only insert the default content if the editor window is empty, or risk deleting good content).

      0
      • 9

        Hi David,

        Thanx for the post and all the cool code, but have you get a solution to use a different ‘custom_editor_content’ depending of the Page Template that the page select. No matter if have to be after or before save de page. Because I can´t find a way to specify in the code the Page Template name.

        0
        • 10

          A plugin like TinyMCE Templates when combined with some good use of editor-styles.css can be very useful, and has the added advantage of being repeatable, or even of being able to add multiple template in different combinations. The ‘quirks of TinyMCE’ will always persist though.

          0
  4. 11

    wow , i had no idea this was possible. I typically try to layout my pages in a more strict fashion with meta fields and calling them in my template pages. However, this could be super useful in lots of situations, especially when tabular data needs to be displayed.
    gonna give it a try for sure.

    0
  5. 12

    Cool tips, I’m going to be needing this very soon. Before, I used [shortcode] which may not be the easiest method for clients to adapt to. Multiple write panels are better but they make the edit page looks congested

    0
    • 13

      Hi Iwani. Any idea of can I create TinyMCE toolbar buttons that generate shortcodes and if possible even with parameters?

      Thanks in advance.

      0
      • 14

        Here you can see how I add custom buttons for custom shortcodes in TinyMCE. I have given one shortcode example for a “Tabs” tabbed box and then the functions for adding all the custom buttons used (Soundcloud, YouTube, Vimeo, Tabs).

        You would have one shortcode function for each button, but since I added the buttons in an array you can see how to add multiple buttons in the example. Then just make a function for each button to specify how it’s shortcode works.

        http://snipt.org/xolx

        Hope this helps you. I have used this in WordPress 3+

        0
  6. 15

    Very very cool – this is a bit of a gamechanger for wordpress in my opinion – being able to manipulate the content editor like that is fantastic for clients!!

    Great post – I rarely reply unless something really wows me, and this was is – fantastic!!

    Thank you :)

    0
  7. 17

    Can’t agree more to what Rob Fenech said. This is very helpfull for clients that always have problems -and fear- working with WP (any) administration. Thanks for sharing!

    0
  8. 18

    I’ve been using shortcodes to define areas like content and sidebar but the formatting in the editor can get ugly.

    This awesome article has brought some much needed light on the subject. Thank you!

    0
  9. 19

    If I knew this technique I would save a lot of time for many projects of mine!

    I think we can find a solution for the custom wysiwyg editor to be shown only a specific custom page template. Can we?

    0
  10. 20

    I didnt know this feature existed but its preety cool. I like it. Using this with the power of custom meta boxes makes wordpress even more flexible.

    0
  11. 21

    Hi David

    Seem like a good solution, but I hope you wouldn’t mind if I ask.

    Is there any caveat ?

    0
    • 22

      Hi Paul,

      Besides the limitations I listed in my conclusion, my main caution would be not to try to get too fancy with it. While I’ve found it useful to allow clients to easily manage simple 2- or 3-column layouts, or creating sections for tabbed or carousel content, anything beyond that may get messy. Remember, hand-crafted code will always be cleaner than anything produced through a WYSIWYG editor.

      Also, before going this route, always ask yourself whether the content may be better suited for a custom field / custom metabox solution. If you want to separate your content for more functional purposes, like sorting and filtering, custom fields are the way to go. If you are separating your content for purely presentational purposes, this method may be a better alternative.

      Hope this is helpful :)

      0
  12. 23

    Very nice, found this handy.

    0
  13. 24

    Thanks for this article David, which came serendipitously for me, and from comments above, quite as an epiphany for others.

    I confess to setting up several client sites base on woothemess “canvas” theme/framework. And although it ships with some sweet shortcodes for creating columns in a post, for some of my clients and apparently others, even that simple invocation from the tinyMCE fields presents a bit of a mental block.

    This by default, seems like an excellent workaround for client sites who’s posts would require plug and play styling afforded by your technique.

    So again, thanks!

    Michael

    0
  14. 25

    This was absolutely fantastic. I’ve been looking for an article like this for quite some time.. thanks so much!

    0
  15. 26

    I’ve been dabbling with some elements that this articles deals with but I had no idea all this could be achieved………. Can’t wait to put it into action…….

    Thanks for such a great post!

    :-p

    0
  16. 27

    Great tip, thanks a lot David. Who knew? :)

    I have a question…is there way to make this work with post format on the Admin side? That is, pick a post format and get the WYSIWYG to present the appropriate default_content “layout”?

    I would think there’s a way to get javascript to pick up the format select and then populate the WYSIWYG content area with the appropriate “layout” framework. Mind you, I’m no JS genius, but something like that would be pretty powerful, yes?

    0
    • 28

      Hi Mark,

      In concept, this shouldn’t be too difficult, though we we’d still have the same issues I described in my reply to Sam above about loading a specific template when you select a different Page Template. Rather than using WordPress’ “default_content”, which is only run when a post is first created (before you’d ever get a chance to assign a post format to it), you would use Javascript as you described to detect that selection event and insert your html accordingly — making sure not to overwrite any content already in the editor window. I’m not sure if there are any existing hooks we could use for this, or if it’d have to be completely custom, but this is something I may look into for future projects.

      Thanks for reading!

      0
      • 29

        Couldn’t a button be used in the editor that would load what’s needed? Like buttons for one, two, three column layouts similar to shrtcodes but using the editor styling?

        0
  17. 30

    Thanks for this post! I love the idea of different layouts for each template. I am going to start hammering through this little beauty right now!

    0
  18. 31

    Nice, I didn’t know this was possible. Before shortcode was the way to go, but this opens a new door of opportunity. Thanks for sharing!

    0
  19. 32

    This is a great post! I will certainly use this from now on. One note though, the default wordpress editor renders html/css horribly, I would recommend using CK Editor for wordpress. My clients love it!

    0
  20. 33

    I’m definitely gonna try this. It looks something I could use. Thanks for sharing.

    @Andrew – I forget CK editor, thanks for reminder.

    0
  21. 34

    Love it~ open my eyes, will definitely to use in the next project, thanks! You are awesome!

    0
  22. 35

    Web Design Automaton

    October 16, 2011 8:17 pm

    I always do this for least tech savvy of my clients, when you can only describe how to work a wysiwyg so many times this becomes almost second nature to implement on projects.

    0
  23. 36

    Hey, great article! Thanks for sharing it.

    Anyone found solution to apply editor style per page template?

    0
  24. 37

    This is great, but I wonder if you could get it to load this custom editor layout, based on the page template they select. For example if they select the 3 column template, it would change the editor to reflect that?

    This would allow you to keep it working within pages & posts (if needed), without having to separate it out as a custom post type.

    0
  25. 38

    This was some seriously great stuff :) I’m always concerned with how the client will interact with the backend and this way it would be so clear I could cry

    0
  26. 39

    Mika Andrianarijaona

    October 17, 2011 4:18 am

    Thank you very much, that’s really interesting and helpful!!

    0
  27. 40

    Good for a developer, bad for a client. With my experience, a client, unfortunately, will probably wind up deleting a “div” or all the “div’s” when editing content, and become really frustrated. Using Advanced Custom Fields plugin is the safest and best option when setting up a page with multiple columns. That’s my 2 cents. :)

    0
  28. 41

    This is really cool thanks David, will def come in handy for many of our less techy clients & save some backup buddy time for us….now to find some of this ‘tactical bacon’: )

    0
  29. 42

    Very interesting, I can see this technique in my next project to empower the client further. Thanks.

    0
  30. 43

    Fantastic post…very ‘real-world’! Quick one, though: how would you implement this for a specific post template or custom post type? So for example I might have a product post type, a blog post type and a news post type. What is the syntax to implement three different custom templates on the backend via functions.php?

    0
  31. 44

    Realy realy REALY amazing !

    Thanks for that tutorial ;)

    Creamotion

    0
  32. 45

    David – this is first rate, definitely plan to use. Thanks!

    0
  33. 46

    thanks David, very helpful!… This fixes a lot of issues from the root, instead of trying complicated solutions…..

    0
  34. 48

    This is very helpful. And just in time as I needed this solution. I’ve used another meta box with editor for similar purposes, but this is simpler and yes, more client-friendly. Lots of thanks.

    0
  35. 49

    Great post! This has been such a limitation in my mind on being able to format pages the way my customers would like them to be formatted. FYI, the TinyMCE Advanced version allows you to insert tables (and edit them) in the WYSIWYG editor. http://wordpress.org/extend/plugins/tinymce-advanced/ Just wanted to mention this in case you didn’t know about it. Now I’m curious which might be better to implement for my customers – that, or your CSS method! (My customers mostly being folks who could never grasp HTML, nor do they want to)

    0
  36. 50

    Very usefull, thanks!!!

    0
  37. 51

    As a lot of other have said, some clients aren’t all the comfortable dealing with multiple meta boxes so this provides another solution to handle those trickier layout problems. Great Post David. Thanks :-)

    0
  38. 52

    Javier Villanueva

    October 29, 2011 1:06 pm

    Nice tip, is there a way to load the styles depending on the page template instead of doing it on every page?

    0
  39. 53

    This is a horrible solution in my opinion. Custom meta boxes yield far more predictable results.

    0
  40. 54

    Hello David –
    Neat idea. But need a tweak related to default content.

    I’ve been searching for couple days for an answer to this and hope you can help. First, the above code works without a hitch. My question: How can I apply this to only ONE type of whatever?

    Specifically, I have a custom post type, Recipes, which is the only place I want default text. I’ve tried what little I know, like putting a conditional
    if(is_singular(‘Recipes’)) {
    around the function. No go. Is there a way to do this?

    Thanks, Mike

    0
  41. 55

    Awesome tutorial, David!
    In which license your tutorial released?
    May I use for my projects? And still with your name in the credit for this part.

    0
    • 56

      Hi Jimmy,
      This tutorial follows only the license and terms-of-use guidelines imposed by the Smashing Magazine site. You are free to use for your client projects and are not required to credit me. Thanks!

      0
  42. 57

    This is quite an eye-opener, although I fear that clients removing elements by accident would be a very common problem. Would it be possible to make certain elements “indestructible”? Or only removable when you’re in HTML mode.

    0
    • 58

      This is so useful! indeed Jonas I wonder too how to prevent the div in the editor to be deleted??? anybody has some suggestions?

      0
  43. 59

    It seems really interesting (havn’t tried it out yet).. but im curious, what if i want more templates for postype = page. Lets say i want the “end-user” to have 3 different types of content to add.

    A 3 column structure, a 2 column structure, a tabbed (javascript) structure.

    As far as I have seen, this code means for “all pages” and all “posts” or am i incorrect? Ifso, how can the end user select the template he wants?

    0
  44. 61

    Very cool technique, though definitely not extremely practical for the vast majority of sites out there which would need some flexibility in post layouts.

    It would be great to have a range of content layouts, and then using a custom wp editor button populate the editor with a layout for product, custom blog post, etc any type of layout based on the site’s needs.

    Once of the problems I find with using custom field data for custom post structures is that when the site is repurposed, the theme changed, or fed to RSS, mobile theme etc custom fields don’t get sent along with the_content.

    I’ve found a few plugins which help adding custom field data via shortcodes, but these also, require manually adding those shortcodes in each time.

    Still looking for the ideal post layout, custom fields data combination solution which still allows opting out for general posts without special layout and custom fields.

    0
  45. 62

    Hi, I tried the code in the functions.php file and it is not working for me. After I put the code in and go to the site, the site is off line.

    Does this code work on wp 3.3 and if it does, I must be putting the code on the wrong line, could you please tell me what line I should start the code on.

    Thanks a million, love you site, has being very helpful to me.

    0
  46. 63

    Amazing…but how i can apply to a single page or post?

    0
    • 64

      True. I would like to know how do it in single page.

      0
    • 65

      Hi Gioska,

      To add a custom template to a single post or page, simply follow the steps to create and import the editor_style.css; then, instead of inserting the markup to all posts via the “default_content” filter, just place your template markup directly into that post via the “HTML” tab in the editor.

      0
  47. 66

    A true multi-column environment would allow text to flow from one column to the next depending on: browser window size, client’s browser font settings and padding. It looks as though in this article all have agreed that column endings are hard coded using the /div tag. To me, this is not in character with modern day web page presentation.

    WordPress needs to step up to the next generation of text editors and integrate Edit-in-Preview-Mode, real time editing. The author can select while in preview mode, predefined page layouts, text color, image positioning, text and image padding. Columns are elastic or snap to grid, columns may be even, or unbalanced, text flows from one column to the next on-the-fly.

    So while the solution stated in this article is grand, the solution is a band aide for WordPress lack of implementing new technologies that are available. WordPress needs to step up to the next generation of content management systems. Currently the implementation of Drag-In-Drop on a live page among other things (like taxonomy) is sorely lacking.

    0
  48. 67

    Its just wonderful stuff. I tried it both with a custom content type, and without it for ‘post’ type.

    My problem is that I want to use custom content editor layouts for different categories. And all wordpress gives us are the 5 standard post types or the option of custom post types. Right now, all new posts show the same layout. It would be fantastic if I could somehow load seperate content layouts (and text) for categories.

    0
  49. 68

    Just what I am looking for!
    Simple and no plugins needed.
    But can you tell me how to display a certain Custom Field inside a and how to control its appereance with CSS?

    Thanks!

    0
  50. 69

    Hello Dave,

    What if I only want 1 page to have this layout? How can I do ? I have added this page filter ‘if ( $current_screen->post_type == ‘page’)’ and I have 2 custom pages default page and 2 column page. I want only to affect 2 custom page

    Thanks a lot!
    Mike

    0
  51. 70

    Amazing tutorial! I wonder what is the “fix” if you follow a path where: you have a theme; you want to edit its home page layout by adding a place where to display a featured article; a space between the slidershows and the widget area like in this hompage: http://i.imgur.com/bqa4HWI.png
    Thank you a lot.

    0
  52. 71

    I spent six hours on google until I got here :)). And what you have explained here I looking for almost 3 years … but I never knew how to search :))

    Thank you David!!!!

    0

↑ Back to top