I'm coding a plugin that adds a filter to single_template. The filter function successfully returns the path to my show-post-in-a-lightbox.php template.

As you can guess from its name, my template is intended to show a single post in a lightbox. Therefore I need to show only the post content and avoid the title bar, menus, sidebars, footers and so on. However, for the post content to show correctly, I need the usual <head> section with all the <link> tags to the required stylesheets and <script> tags.

My template code so far is:

 Template Name: show-post-in-lightbox


<div id="primary" class="content-area">
  <main id="main" class="site-main" role="main">
    global $post;
    // Start the loop.
    while ( have_posts() ) : the_post();

      $content = $post->post_content;
      $content = apply_filters('the_content', $content);
      $content = str_replace(']]>', ']]&gt;', $content);
      echo $content;

This works in that it shows the post content, but it also shows the heading banner above it, with the site logo, the title (I'm not talking about <title>, that one is ok, but I mean <header id="masthead" class="site-header">), and all the rest therein.

If I comment out the get_header(); line it outputs only the content, but without the required styles and scripts.

Is there a function that returns (or outputs) only the <head> tag (or only up to the </head> tag) of a given post?

  • Is the content of the lightbox in an iframe? – Jacob Peattie Jul 25 '17 at 10:49
  • @JacobPeattie yes it is, but it does not need to be, I can patch my code to make it become a <div> – Lucio Crusca Jul 25 '17 at 13:58

Front end styling is usually a theme territory that plugins should avoid. There is no simple way to know how anything is styled without actually doing the full styling, as some of it will depend on the content itself, and since the styling is basically random from the plugin author POV, you are unlikely to be able to have a general algorithm to adjust it to whatever you need in a reliable way.

Best approach that comes into my mind is to wrap the content with your own div, and use JS to hide everything else on the page. Still you will most likely get a mobile type of vies in your lightbox, which might not be what you are after.


You can use the wp_head() function, you just need to add the opening html and body tags, and the head tags:

 * Template Name: show-post-in-lightbox
<!DOCTYPE html>
    <?php wp_head(); ?>


<!-- Content here -->

<?php get_footer(); ?>

If your footer closes any elements/divs other than html and body, make sure to open them in this template.

Also, wp_head() doesn't necessarily include everything in the head element, check your theme's header.php file. It should have the wp_head() function itself, just check for anything that was added separately that you might need to include in the head.

Another option would be to copy header.php, rename it something like header-post.php, remove everything you don't want to appear on posts, and then in your cutstom template, use get_header( 'post' ); to use that version of the header:

 * Template Name: show-post-in-lightbox

get_header( 'post' ); ?>

<!-- Post content here -->

<?php get_footer(); ?>
  • I've tried your suggestions, but I can't make them work at least with the twenty seventeen theme. The post content is there, but is not being displayed correctly. That's a pity because your answer seems logical and it would have been the best solution to my problem. I'm afraid Mark Kaplun is right, there's no reliable (theme independent) way to do what I want. – Lucio Crusca Jul 27 '17 at 7:06
  • The problem is that you also need all the correct markup for the post template, or the styling won't apply quite right. This probably isn't the right way to go about this though. You should provide your own template and styling for posts inside the popup that's theme-agnostic. – Jacob Peattie Jul 27 '17 at 7:34

I've finally ended up with something similar to what Mark Kaplun had suggested in his answer, but, instead of using JS code, I opted for a CSS solution instead.

When my code creates the <iframe> link, it appends a extra HTTP parameter:

$lightboxlink = '/?p='.$postid.'&use-lightbox-css=1';

Then the plugin checks for that parameter, and, if present, it enqueues the extra CSS file.

And here is the CSS file contents:

header {
  display: none !important;

I know, I shouldn't be using !important. To avoid that, the plugin uses the lowest possible prority (PHP_INT_MAX) to the add_action call that register my function with the wp_enqueue_style call. That way, my extra CSS is loaded as the last one inside the <iframe> tag and it takes precedence over all the others (that's the Cascading meaning of CSS). Now I can strip the !important:

header {
  display: none;

That works only with themes that actually make use of the <header> tag, but for now it's good enough for my use cases. Anyway adapting it to other themes is only a matter of adding the required selectors to the CSS file, for example here is a first guess for the Wiz theme that I sometimes use:

header, .header-vh-wrapper, .navbar-inner, .nav-container, .logo, #title {
  display: none;
  • My answer was downvoted. No problem, but before accepting it I asked for feedback about possible pitfalls. Can you (= the one who downvoted) please explain what's wrong with it? Thanks. – Lucio Crusca Jul 29 '17 at 8:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.