0

I have a shortcode that iterates through a list of custom post types and, as part of displaying them, creates a block. In HTML5, it is illegal to have a style block outside the header (maybe in other versions too, but we are using HTML5).

I am looking for a way that my shortcode can insert its block into the head. Any suggestions?

This is the page: http://2011.solarteam.org/sponsors/gift-recognition/view-of-living-room

The shortcode is called twice on a page.
Once like this [interactive slug='sponsor-map-living-room' show="image"]Select an item to learn more about its sponsor.[/interactive] to make the image.
Once like this [interactive slug='sponsor-map-living-room' show='list' headertitle='WaterShed Featured Sponsors: Living Room' /] to make the list at the bottom.

I can't put it in the template because the template does not know which slug goes on which page.


Here is a simplified version of the shortcode processing code:

<ul><?
foreach($map->points as $point){
    $result = "";
    if(!in_array($point->pointer_type, $all_styles['regular'])){
        $all_styles['regular'][$point->pointer_type] = "
            .pointer_style_" . $point->pointer_type . " {
                width: " . $point->pointer_width(). "px;
                height: " . $point->pointer_height(). "px;
                background: transparent url('/images/interactive/pointers/" . $point->pointer_URL() . "');
            }
        ";
    }
    ob_start(); ?>
    <li class="tag_point sponsor_data_point pointer_style_<?php echo $point->pointer_type?>" id="point_<?php echo $point->ID ?>" data-in="#point_<?php echo $point->ID ?>_info" data-hover-style="pointer_s_style_<?php echo $point->selected_pointer_type?>" style="left:<?php echo $point->x - ($point->pointer_width()/2) ?>px;top:<?php echo $point->y - ($point->pointer_height()/2)?>px;">
    <div class="tag_info" id="point_<?php echo $point->ID ?>_info">
        <div class="donation-title"><?php echo $point->contribution ?></div>
        <div class="donation-contribution"><?php echo $point->description ?></div>
    </div>
    <?
    $result .= ob_get_clean();
    $result .= "</li>\n";
    echo $result;
}
?>
</ul>
<style type="text/css">
    <?php echo join("\n", $all_styles['regular']); ?> 
</style>

The <style> tag is not allowed there in HTML5, so I want to get it into the head of the page.

4 Answers 4

3

hook the_posts and inspect each post to see if your shortcode is present, you can use wp_enqueue_style at that point if it is. maybe a bit of regex to check for the presence of the shortcode is the way to go, unfortunately i'm not very good with regex!

function wpse27772_has_shortcode($posts) {
    if ( empty($posts) )
        return $posts;

    $has_shortcode = false;

    foreach ($posts as $post) {
        //check for your shortcode in $post->post_content
        //set $has_shortcode = true if it's found
    }

    if($has_shortcode === true):
        wp_enqueue_style( 'mystyle', get_template_directory_uri().'/mystyle.css' );
    endif;

    return $posts;
}
add_action('the_posts', 'wpse27772_has_shortcode');

EDIT - quick example from my comment below...

function wpse27772_output_styles(){
    global $posts;
    foreach ($posts as $post) {
        // inspect $post->post_content;
        // echo "<style type='text/css'></style>";  
    }
}
add_action('wp_head', 'wpse27772_output_styles');
3
  • I voted this up because it looks useful and shows some thought, but I am not sure if it is the right answer for my question. When I run my shortcode, it loops through a number of elements and outputs their styles. I want to aviod running the loop too many times. I just posted the code that is inside the shortcode processor which should show exactly what my problem is.
    – yakatz
    Sep 6, 2011 at 1:06
  • @yakatz - you can hook wp_head and inspect the global $posts and echo inline styles directly within head, but regardless, when the shortcode is parsed it's simply too late to get anything into the document head, i think you're just going to have to do things twice.
    – Milo
    Sep 6, 2011 at 1:31
  • Good proof of concept, but wish there was a better way to do this...
    – Dave Kiss
    Aug 19, 2013 at 20:54
1

I happen to know a little more about the requirements of this project so here's my suggestion.

There are a whole bunch of elements that each need the following styles: - Background - Size - Color - Hover behavior - Position

All of these except the position can be saved in a separate stylesheet because they are the same for all the elements.

Pages with this shorttag are also all using a particular template. You can use wp_enqueue_style to include the CSS file on those pages only.

For the few bits of style (the position) that can't be in the separate file because they come from the database, they can be inline, for example <div style"..."></div>.

0

Couldn't you you save your shortcode as a file?

Example: Open a blank text document and paste your shortcode into it. Next save it as my_shortcode.php. Upload it to your themes root directory, then use

<?php get_template_part('my_shortcode'); ?>

By placing it before the closing head tag it should work. I've never tried it so I'm not positive, but it's worth a shot.

3
  • I can't really do that since the shortcode has different arguments on different pages. I edited the question to show the usage.
    – yakatz
    Sep 5, 2011 at 22:40
  • So how do yo plan on placing the shortcode inside the <head> tag as you've mentioned in the question title if not adding it to the header.php file? If you plan on making separate header files to include with specific templates, you could just place the code I've suggested into those custom headers. You don't really need separate header files though if you make use of the options available for specifying the different templates provided by WordPress. If you're not sure what I'm talking about, open up the TwentyTen or TwentyEleven header.php files and take a look at the code. Sep 6, 2011 at 0:26
  • I changed the title to be more clear. I want css to be inserted in the header based on the shortcode that is in the page body.
    – yakatz
    Sep 6, 2011 at 0:41
0

I realize this is an old question, but I recently needed to do just this. My solution was to hook into wp_head and run any shortcodes in the post content. This works because the shortcodes I'm dealing with call wp_enqueue_script and wp_enqueue_style when they are processed.

The code looks something like this:

function  example_shortcodes() {
    global $posts;

    foreach ( $posts as $my_post ) {

        ob_start(); // just in case
        do_shortcode( $my_post->post_content );
        ob_end_clean();
    }
}
add_action( 'wp_head', 'example_shortcodes', 5 );

Performance is a concern because this means you are running shortcodes twice, and there might be unintended side effects if a shortcode "does" something when it runs. Given that, it might be wise to only process specific shortcodes that you know will not be an issue with this technique.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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