6

I wrote a WordPress theme for a non-profit where I use templates to style individual pages. I select the template for an individual page in the editor on the right:

Template selection in editor

For styling of a template page, I simply add a css class to the outer most element in the template and style the rest based on the presence of this class - in this example layout-krankenbett-gruen:

templates/KrankenbettGruen.php:

<?php /* Template Name: Krankenbett grün */ ?>

<?php get_header(); ?>
    <main class="layout-krankenbett-gruen">
        <?php if ( have_posts() ) : while ( have_posts() ) : the_post();
            get_template_part( 'content', get_post_format() );
        endwhile; endif; ?>
    </main>
<?php get_footer(); ?>

I can style the page similar to the display in the editor using this code in functions.php

// enable style sheet for normal page display also in editor
add_theme_support('editor-styles');
add_editor_style('style.css');

such that all styles that get applied to the page get also applied in the editor.

I want to have the editor also show the templates as they look on the page later. But somehow the css tag which I add for the template is not present in the editor and therefor the display of the template in the editor is not correct.

How can I recognize a template in the editor such that I can display it in the editor in the same style as on the page?

Update:

I saw that the Twenty Twenty Theme also has Templates (Standard-Template, Cover-Template and Template for wide pages). If I change the template in this Theme, the page in the editor does not change, but the page itself does. Is that intended behavior? I feel like the user would like to see how a template looks (in the editor) before he applies it. Am I getting it wrong?

3 Answers 3

1

welcome to this forum. :-)

I'm not an expert, BUT I did do something similar by following the instructions and tutorials I found at these links below, hopefully these will help guide you.

In a nutshell, you have to go beyond just enabling the stylesheet in the editor, you have actually add a stylesheet specifically for the editor (editor-styles.css) and declare your styles in that (being sure to keep them the same as your front-facing style.css file).

Also, way below I put my own code if it also helps to serve as an example.

Good luck!!

Tutorials:

https://codex.wordpress.org/TinyMCE_Custom_Styles

https://developer.wordpress.org/reference/functions/add_editor_style/

http://wplift.com/how-to-add-custom-styles-to-the-wordpress-visual-post-editor (note this last link is a great tutorial but adding the style declarations that way didn’t work, I had to use the code below)

More tutorials: https://www.wpkube.com/add-dropdown-css-style-selector-visual-editor/

http://www.wpbeginner.com/wp-tutorials/how-to-add-custom-styles-to-wordpress-visual-editor/

My use:

// Unhides the Styles drop down selector in the 2nd toolbar in Visual Editor
function bai_tinymce_buttons( $buttons ) {
  //Add style selector to the beginning of the toolbar
  array_unshift( $buttons, 'styleselect' );

  return $buttons;
 }
add_filter( 'mce_buttons_2', 'bai_tinymce_buttons' );

// Adds some styles to the visual editor formats (styles) dropdown, styles are in editor-style.css
function bai_mce_before_init_insert_formats( $init_array ) {
// Define the style_formats array
$style_formats = array(
    // Each array child is a format with it's own settings
    array(
        'title' => '.pull-right',
        'block' => 'blockquote',
        'classes' => 'pull-right',
        'wrapper' => true,
    ),
    array(
        'title' => '.tips',
        'block' => 'blockquote',
        'classes' => 'tips',
        'wrapper' => true,
    ),
    array(
        'title' => '.nutshell',
        'block' => 'div',
        'classes' => 'nutshell',
        'wrapper' => true,
    ),
);
// Insert the array, JSON ENCODED, into 'style_formats'
$init_array['style_formats'] = json_encode( $style_formats );
return $init_array;
}
add_filter( 'tiny_mce_before_init', 'bai_mce_before_init_insert_formats' );
4
  • I couldn't make your code run. Where should the new classes actually appear on the page? I didn't find them. Your resources look quite interesting, I have to dig deeper into that - but that will take some time. Apr 11, 2021 at 15:22
  • The styles go into both your Theme's style.css file AND in your editor-styles.css file, and they should match so that your back-end preview matches your front end display. The code goes into your (Child Theme's) functions.php file, or a custom plugin file if you prefer to use that instead of the Theme's file.....then you'll see the new styles in a dropdown in your Editor, although in some cases you may need to toggle the second row if you're using the Classic Editor.
    – Trisha
    Apr 11, 2021 at 16:43
  • When I add the method add_filter( 'mce_buttons_2', 'bai_tinymce_buttons' );, it doesn't change anything in my admin edit window. What is supposed to be happening when I add it? Apr 12, 2021 at 19:36
  • It adds a "Formats" dropdown to the second row of buttons in the old Visual Editor, I don't use the Blocks/Gutenberg Editor so I don't know where it would get added there, but in the old Visual Editor the rightmost button on the top row toggles the display of the second row on/off. It may appear elsewhere in the Gutenberg or Blocks Editor. Of course, until you have some styles to display there, which you do by adding your editor-styles.css as show above, the dropdown would have nothing to show, and might not appear. So you first add your styles, then enable the Formats dropdown.
    – Trisha
    Apr 13, 2021 at 18:39
1

Welcome!

I had a simliar problem. You can set the class in the editor using javascript. Load a javascript file in functions.php.

add_action('admin_enqueue_scripts', 'prf_admin_enqueue');
function prf_admin_enqueue(){
    global $pagenow;
    /* Replace 'page' with the post type you want */
    if (( $pagenow == 'post.php' ) || (get_post_type() == 'page')) {
        global $post;
        $current_template = get_post_meta( $post->ID, '_wp_page_template', true );
        wp_enqueue_script('css-editor-enqueue', get_template_directory_uri() . '/js/admin-do-set-class.js', array('jquery'));
        wp_localize_script('css-editor-enqueue','adminDoSetClass',array('current_template' => $current_template));
    }
}

Then in this javascipt file do the following:

jQuery(function($){
    /* The template on page load as arranged in the function.php file. */
    var currentTemplate = adminDoSetClass.current_template;
    /* See whether we are on Gutenberg or on the old editor */
    var onTinyMCE = !!$('#content_ifr').length;
    /* Track which class was set last */
    var classSetEarlier = '';
    /*  When we enter the page, set the class and add an event listener. */
    if(onTinyMCE){
        /* For TinyMCE we just need to use the event that they provided */
        $( document ).on( 'tinymce-editor-init', function( ) {
            setClassOnEditor(currentTemplate);
        });
        /* Listen for changes and set new value accordingly. */
        $('#page_template').change(function(){
            var newValue = $('#page_template').val();
            setClassOnEditor(newValue);
        });
    }
    else if(!onTinyMCE){
        /* For Gutenberg there is probably also an event/Promise, but I cannot find that, so we try again and again until the editor-styles-wrapper element is there. */
        var intervalID = setInterval(function(){
            if($(".editor-styles-wrapper").length){
                /* Set class on page load */
                setClassOnEditor(currentTemplate);
                clearInterval(intervalID);
                /* Add event listener to body so we can wait until the selctor gets avaitable. */
                $('body').on('change', '.editor-page-attributes__template .components-select-control__input', function(){
                    var newValue = $('.editor-page-attributes__template .components-select-control__input').val();
                    setClassOnEditor(newValue);
                });
            }
        },100);
    }
    /* Function to set the right class on the editor body */
    function setClassOnEditor(newTemplateValue){
        var newClass = '';
        if(newTemplateValue === 'templates/KrankenbettGruen.php'){
            newClass = 'layout-krankenbett-gruen';
        }
        /* Remove any class set earlier and add the new class to the editor */
        if(onTinyMCE){
            setClassTinyMCE(newClass);
        }
        else if(!onTinyMCE){
            setClassGutenberg(newClass);
        }
        classSetEarlier = newClass;
    }
    /* The two function to set the class on the editor, one for the old editor and one for Gutenberg */
    function setClassTinyMCE(newClass){
        $("#content_ifr").contents().find("body").removeClass(classSetEarlier);
        $("#content_ifr").contents().find("body").addClass(newClass);
    }
    function setClassGutenberg(newClass){
        $(".editor-styles-wrapper").removeClass(classSetEarlier);
        $(".editor-styles-wrapper").addClass(newClass);
    }
},jQuery);

EDIT: edited above code. The Gutenberg editor is now also included, not only the old editor.

4
  • Hmmm, I understand your idea. The page_template id is in my editor inspector-select-control-0 I'm not sure whether that would change sometimes. Also what is the id content_ifr you are using? I didn't find that on my page. Yes I use the newest WordPress version with Gutenberg. I couldn't make your code run in my system. Apr 11, 2021 at 15:21
  • I rewrote the code to include the Gutenberg editor. This should actually be done more from the React side, I presume...
    – Klaassiek
    Apr 11, 2021 at 20:24
  • Thanks! Still not working for me. In the prf_admin_enqueue method when calling get_current_screen() the attribute parent_base is always empty, it's never 'edit', so the if-clause is not parsed ... Apr 12, 2021 at 19:33
  • I see. Sorry about that. I updated that part of the code. As you can see, you can check for the post type in case you need it on a different post type than 'page'. Hope it works for you.
    – Klaassiek
    Apr 13, 2021 at 12:07
0

If you're using the new block editor you can add the template name as a css class to the body tag in admin using the admin_body_class filter in your functions.php

    function wpdocs_admin_classes( $classes ) {
        $template = get_page_template_slug(); // get template file name
        if ($template) {
            $class = explode('.', $template)[0]; // discard .php extension
            $classes .= ' template-' . $class;
        }
     
        return $classes;
    }
    add_filter( 'admin_body_class', 'wpdocs_admin_classes' );

Then you can use the class selector in the editor CSS like this:

    body.template-file-name .your-element {
        color: blue;
    }
2
  • I doubt that adds the style to the editor view though, which is what the question is about.
    – Rup
    Aug 21, 2022 at 16:06
  • @Rup You're right. It will work with the block editor, not with TinyMCE. Edited the answer to make it clear. Even though it's not exactly the OP context, it may help someone. Aug 21, 2022 at 19:12

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.