Building pages in Drupal with Panels

When finished this site will implement several different layouts: blogposts, "static" pages, short "nuggets", blog archives, taxonomy listing and probably a bespoke front page. Although these will all have the same underlying seven-column layout, that can still present some problems that are usually solved in Drupal with many different theme files and a lot of "regions" in which you can put "blocks" of content.

Regions and blocks have serious limitations, though. For example, any one block---say the most recent posts from the blog, or a feed from Twitter---can only be placed in one region, although it can then be made to appear and disappear on other pages based on URL or (dangerously) bespoke PHP embedded in the database. There are modules which replicate blocks, to try to circumvent such problems. Following merlinofchaos' great talk at, once again, DrupalCon Paris 2009, I decided to use Panels and panes instead of the core Drupal region/block system.

It was touch and go initially as to whether I was going to scrap it all and start again with blocks and regions or not. I managed fairly quickly to assemble custom pages for nodes of a few different types, but then had real trouble working out the subtleties of getting custom pages together for existing non-single-node content. Panels and its associated CTools developer framework concentrate far more on front-end functionality than ease of backend user experience. That's a shame, as the most important take-home message of prioritizing user experience is that hidden functionality might as well be no functionality at all. But as with most of these springs to mind here---the first time is the worst, and once you know what you doing, you, well, know what you're doing.

Panels lets you divide up a page into just those panels. A set of standard URL matches come with Panels as "pages" you can enable, but you can also add new pages at new URLs. In terms familiar to Drupal templaters they take over the $content variable in the page templates, leaving your existing block regions available if you still want them. So when you enable panels, you get an extra menu item under Site Building called predictably "Panels". This takes you to a dashboard where you can enable or disable panels support for existing URL schemata (e.g. the node URLs at /node/%) and create variants which take into account e.g. the node type, so your blogposts can look different from your events. 

Slightly more subtly, though, if you want to enable panels on an existing view page... you can't. There's no mechanism for overriding the existing view page at e.g. /blog, like you can with a node page, and if you try to create a new panels page at that same URL then the system complains and won't let you do it. Instead, you have to create a whole new page and eventually discard or at any rate mothball the view's own page. Assuming you have a view at /blog, create a panels page at /blog_new; you can then add the view as a panel pane. You can use any one of the view's configuration variants (default, page, block etc.), not just the standard page variant. When everything looks happy, move your view to /blog_old and your new panels page to /blog.

Drupal also provides taxonomy listings at /taxonomy/term/term-id , which with Pathauto get aliased to /category/vocabulary-name/term-name. If you want to override a taxonomy listing, you can... but again there's a catch. Panels doesn't seem to provide you with any way of replicating the original content as far as I can see, and instead you have to build a view to replace the behaviour of the original taxonomy listing, and then put that into a pane where you'd want the original dumb taxonomy content to go.

When you create the view, you give it a first argument of "term ID". Then, when you add the view to the panel, in the modal lightbox titled "Configure view NAME (Defaults)", under the "Override title" box, you should have a setting where you can choose what to pipe through into your argument. Set that to term ID too. What you end up with is, as seems to always be the case with Panels, more functional and configurable than before, but it's harder to get to. Not just harder than letting core handle it: that's to be expected. But harder than you'd expect a GUI-rich many-developer-hour content-driven application to be.

Here's a summary of my panels the configuration:

Site building > Pages


  • System > node_view enabled
  • System > term_view enabled
  • Custom > page_blog created for the blog archives
Node template
  • Node type = blog and Node type = page variants
  • Two-column layout
  • Blog: node content in right column, with custom module providing tags in left column
Taxonomy term template
  • Two-column layout, no variants
  • Term description pane, then  taxonomy-filtering view pane, with view arguments taken directly from /taxonomy/term system URL
Custom view template
  • At URL=blog
  • Paging configured on view
  • View has its own page display variant, at another URL, to provide consistent formatting
  • Override all core column widths: these are a pain (whoever wants 33:34:33 columns?)
  • Custom CSS classes on some panels and panes, with custom module to also strip down markup


Overall Panels has made me feel like I have total control over what I want to appear where on my site. But the learning curve is steep and doubtless puts some people off; some of the greatest advantages come from being happy to get your hands dirty with PHP and the plugin architecture too, which I'll cover at a later date, and that's not possible or advisable for most Drupal end users. If I'd not had the luxury of stepping back for a few days every once in a while I'd probably have done it all in templating with regions and blocks. I'm glad I didn't, though, and I'm looking forward to iterating and perfecting my site's use of Panels.