Title: Extending the Custom CSS editor
Author: George Stephanis
Published: November 26, 2016

---

 [  ](https://profiles.wordpress.org/georgestephanis/) [George Stephanis](https://profiles.wordpress.org/georgestephanis/)
8:03 pm _on_ November 26, 2016     
Tags: [4.7 ( 124 )](https://make.wordpress.org/core/tag/4-7/),
[CSS ( 10 )](https://make.wordpress.org/core/tag/css/), [customize ( 67 )](https://make.wordpress.org/core/tag/customize/),
[dev-notes ( 648 )](https://make.wordpress.org/core/tag/dev-notes/)   

# Extending the Custom CSS editor

With the [Custom CSS project](https://make.wordpress.org/core/2016/10/11/feature-proposal-better-theme-customizations-via-custom-css-with-live-previews/)
[merging into WordPress Core](https://core.trac.wordpress.org/changeset/38829), 
some of y’all may be looking to extend it and do more advanced stuff.  Maybe you
help run an existing pluginPlugin A plugin is a piece of software containing a group
of functions that can be added to a WordPress website. They can extend functionality
or add new features to your WordPress websites. WordPress plugins are written in
the PHP programming language and integrate seamlessly with WordPress. These can 
be free in the WordPress.org Plugin Directory [https://wordpress.org/plugins/](https://wordpress.org/plugins/)
or can be cost-based plugin from a third-party. (like me) that has already provided
a Custom CSSCSS Cascading Style Sheets. input to WordPress coreCore Core is the 
set of software required to run WordPress. The Core Development Team builds WordPress.
and you’re now looking to migrate that data over.  Or maybe you want to change how
it outputs.  Here’s what I’ve found so far in my work converting Jetpack’s Custom
CSS module to be an enhancementenhancement Enhancements are simple improvements 
to WordPress, such as the addition of a hook, a new feature, or an improvement to
an existing feature. layer on top of the Core implementation, providing legacy feature
parity.

**Disclaimer:** This is just what I’ve found to be useful so far, the Jetpack update
is still a work in progress as I write this.

### Data Structure

Core’s data store is in a Custom Post TypeCustom Post Type WordPress can hold and
display many different types of content. A single item of such a content is generally
called a post, although post is also a specific post type. Custom Post Types gives
your site the ability to have templated posts, to simplify the concept. named `custom_css`,
and the CSS is stored in the `post_content`.  It sets up a new post for each theme’s
custom css, and only the active theme’s one is used.  There’s no accounting for 
parent/child themes — it uses the slug from the current stylesheet (child themeChild
theme A Child Theme is a customized theme based upon a Parent Theme. It’s considered
best practice to create a child theme if you want to modify the CSS of your theme.
[https://developer.wordpress.org/themes/advanced-topics/child-themes/](https://developer.wordpress.org/themes/advanced-topics/child-themes/))
as the `post_name`; that is, Custom CSS lookups are indexed by the return value 
of `get_stylesheet()`.  Core does not yet have have a UIUI User interface for displaying
the revisionsRevisions The WordPress revisions system stores a record of each saved
draft or published update. The revision system allows you to see what changes were
made in each revision by dragging a slider (or using the Next/Previous buttons).
The display indicates what has changed in each revision. for changes to Custom CSS
or a way display the saved Custom CSS of inactive themes, but **revisions are enabled**
on the post type, so no data is lost until the revision viewer makes its way into
core (or the user activates a plugin that provides similar functionality). Follow
[#31089](https://core.trac.wordpress.org/ticket/31089) for more on revisions in 
the customizerCustomizer Tool built into WordPress core that hooks into most modern
themes. You can use it to preview and modify many of your site’s appearance settings.,
for all settings not just for Custom CSS.

### Getting The Custom CSS

The generated CSS itself can be gotten via the `wp_get_custom_css()` function, which
just returns the CSS for the current theme as a string. This function is used in
the `wp_head` callback when the CSS is printed into a `style` tagtag A directory
in Subversion. WordPress uses tags to store a single snapshot of a version (3.6,
3.6.1, etc.), the common convention of tags in version control systems. (Not to 
be confused with post tags.).  One of the more useful functions in the Core implementation
for advanced development is [`wp_get_custom_css_post( $stylesheet = '' )`](https://github.com/WordPress/WordPress/blob/ad80e08c17491c870fc834ef382303dc7ac3cd63/wp-includes/theme.php#L1576-L1621)—
this will return either `null` or the `WP_Post` object if the site has any Custom
CSS saved for the current site.  If you’re building a custom revision viewer, this
will be the post you’ll key off of to fetch the revisions.

### Filters on Read and Update

The `wp_get_custom_css()` function applies a `wp_get_custom_css` filterFilter Filters
are one of the two types of Hooks [https://codex.wordpress.org/Plugin_API/Hooks](https://codex.wordpress.org/Plugin_API/Hooks).
They provide a way for functions to modify data of other functions. They are the
counterpart to Actions. Unlike Actions, filters are meant to work in an isolated
manner, and should never have side effects such as affecting global variables and
output. to the styles just before they’re returned.  This allows for targeted tweaks
such as minifying the output on the front-end before it’s echoed by stripping out
excess whitespace or the like.  This filter is _not meant_ for a theme or plugin
adding styles to the front-end of the site — for that, consider enqueueing your 
stylesheet normally and adding any dynamic bits via `wp_add_inline_style()` — this
way it will also handle if a child theme or plugin wants to dequeue the parent stylesheet.

Jetpack has historically provided LESS and Sass (SCSS) preprocessing for our Custom
CSS module.  We’re extending the Core implementation via [two filters](https://core.trac.wordpress.org/changeset/39209)
in the [`WP_Customize_Custom_CSS_Setting` class](https://github.com/WordPress/WordPress/blob/ad80e08c17491c870fc834ef382303dc7ac3cd63/wp-includes/customize/class-wp-customize-custom-css-setting.php)
by storing the pre-compiled code in `$post->post_content_filtered` — so it is versioned
correctly, but if the user disables Jetpack, the compiled CSS will still be available
in `$post->post_content` with no data loss for the user.

When implementing a pre-processor extension to the Custom CSS functionality in core
you have to do some swapping between the underlying setting value and the value 
that gets displayed:

 1. Replace the `post_content` with the `post_content_filtered` as the initial setting
    value via the `customize_value_custom_css` filter.
 2. Add a `wp_get_custom_css` filter in the customizer preview (when the `customize_preview_init`
    action triggers) to compile the value into CSS just-in-time.
 3. Override the default JavaScriptJavaScript JavaScript or JS is an object-oriented
    computer programming language commonly used to create interactive effects within
    web browsers. WordPress makes extensive use of JS for a better user experience.
    While PHP is executed on the server, JS executes within a user’s browser. [https://www.javascript.com](https://www.javascript.com/)
    live-preview functionality to instead register a partial for the `wp-custom-css`
    style element so that whenever the custom CSS is modified it can be re-compiled
    on the server and rendered via selective refresh.
 4. When the Custom CSS setting is saved in the customizer, send the saved pre-processed
    value to `post_content_filtered` and compile the value to store into `post_content`.

For a standalone example of building a pre-processor, see the [Custom SCSS Demo](https://github.com/xwp/wp-custom-scss-demo)
plugin on GitHubGitHub GitHub is a website that offers online implementation of 
git repositories that can easily be shared, copied and modified by other developers.
Public repositories are free to host, private repositories require a paid subscription.
GitHub introduced the concept of the ‘pull request’ where code changes done in branches
by contributors can be reviewed and discussed before being merged by the repository
owner. [https://github.com/](https://github.com/).

### Permissions

The Core implementation also is including only very basic sanitization, to the point
where it would be dangerous to allow users without `unfiltered_html` to edit CSS.
If your plugin is adding further sanitization to the saved CSS, you can broaden 
the user base by remapping the `edit_css` capabilitycapability A **capability** 
is permission to perform one or more types of task. Checking if a user has a capability
is performed by the `current_user_can` function. Each user of a WordPress site might
have some permissions but not others, depending on their role. For example, users
who have the Author role usually have permission to edit their own posts (the “edit_posts”
capability), but not permission to edit other users’ posts (the “edit_others_posts”
capability). ([which Core defaults to `unfiltered_html`](https://github.com/WordPress/WordPress/blob/3a449ea5439b547cf3f9119cbfe9503cadeaeedb/wp-includes/capabilities.php#L344-L353))
like so:

    ```
    add_filter( 'map_meta_cap', 'mycss_map_meta_cap', 20, 2 );
    function mycss_map_meta_cap( $caps, $cap ) {
      if ( 'edit_css' === $cap ) {
        $caps = array( 'edit_theme_options' );
      }
      return $caps;
    }
    ```

### Migrating an Existing `option` to Core CSS

Does your plugin or theme have a custom CSS option stored as an `option` or a `theme_mod`?
Consider migrating content from your custom setting to the core functionality and
hiding your custom UI. Here’s a general migrationMigration Moving the code, database
and media files for a website site from one server to another. Most typically done
when changing hosting companies. script, which can be located where you see fit 
in the context of your original code:

    ```notranslate
    if ( function_exists( 'wp_update_custom_css_post' ) ) {
    	// Migrate any existing theme CSS to the core option added in WordPress 4.7.
    	$css = get_theme_mod( 'custom_theme_css' );
    	if ( $css ) {
    		$core_css = wp_get_custom_css(); // Preserve any CSS already added to the core option.
    		$return = wp_update_custom_css_post( $core_css . $css );
    		if ( ! is_wp_error( $return ) ) {
    			// Remove the old theme_mod, so that the CSS is stored in only one place moving forward.
    			remove_theme_mod( 'custom_theme_css' );
    		}
    	}
    } else {
    	// Back-compat for WordPress < 4.7.
    ```

I hope some of this has been useful to folks interested in diving deeper into modifying
the Core Custom CSS editor.  It’s still somewhat early days for the feature, so 
please reach out in [#core-customize](https://wordpress.slack.com/messages/core-customize/)
on [Slack ](https://chat.wordpress.org/)with any unexpected use cases or concerns!

[#4-7](https://make.wordpress.org/core/tag/4-7/), [#css](https://make.wordpress.org/core/tag/css/),
[#customize](https://make.wordpress.org/core/tag/customize/), [#dev-notes](https://make.wordpress.org/core/tag/dev-notes/)

### Share this:

 * [  Threads ](https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/?share=threads)
 * [  Mastodon ](https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/?share=mastodon)
 * [  Bluesky ](https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/?share=bluesky)
 * [  X ](https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/?share=x)
 * [  Facebook ](https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/?share=facebook)
 * [  LinkedIn ](https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/?share=linkedin)

 1.  ![](https://secure.gravatar.com/avatar/6a97b9fdf799797b7e29604f11d3c6ba1da31e57f4fdb9f76dba09cb052770b1?
     s=32&d=mm&r=g)
 2.   [Joy](https://profiles.wordpress.org/joyously/)  8:25 pm _on_ November 28, 2016
 3.  Given that the Custom CSSCSS Cascading Style Sheets. in coreCore Core is the set
     of software required to run WordPress. The Core Development Team builds WordPress.
     is brand new, and it is output last, the migrationMigration Moving the code, database
     and media files for a website site from one server to another. Most typically 
     done when changing hosting companies. code you used:
      `$return = wp_update_custom_css_post(
     $core_css . $css );` probably should be `$return = wp_update_custom_css_post( 
     $css . $core_css );`
 4.   * ![](https://secure.gravatar.com/avatar/7fab7a27d6eb1e11d63e8a5963991d4adacce3ae704dc2fb7f53d97fad88edce?
        s=32&d=mm&r=g)
      *  [George Stephanis](https://profiles.wordpress.org/georgestephanis/)  8:50 
        pm _on_ November 28, 2016
      * But by that logic, shouldn’t it be coreCore Core is the set of software required
        to run WordPress. The Core Development Team builds WordPress. first, as that
        is what the user has set most recently?
      * In practice, it doesn’t make much difference. Most of the time, if things are
        updated promptly, the Core CSSCSS Cascading Style Sheets. will be empty as 
        it’s not been used yet.
 5.  ![](https://secure.gravatar.com/avatar/a166cdf71b4276f643ccb097340dc7926699eaa512770f8141e9bb11b811f19d?
     s=32&d=mm&r=g)
 6.   [Surbma](https://profiles.wordpress.org/surbma/)  9:50 pm _on_ March 19, 2017
 7.  Hi George,
 8.  I’d like to extend the capabilitycapability A **capability** is permission to 
     perform one or more types of task. Checking if a user has a capability is performed
     by the `current_user_can` function. Each user of a WordPress site might have some
     permissions but not others, depending on their role. For example, users who have
     the Author role usually have permission to edit their own posts (the “edit_posts”
     capability), but not permission to edit other users’ posts (the “edit_others_posts”
     capability). of the Custom CSSCSS Cascading Style Sheets. editor on my Multisitemultisite
     Used to describe a WordPress installation with a network of multiple blogs, grouped
     by sites. This installation type has shared users tables, and creates separate
     database tables for each blog (wp_posts becomes wp_0_posts). See also **network**,**
     blog**, **site** install to all administrators and I’m using your example code
     to do it, but it is not working as expected.
 9.  When I load the CustomizerCustomizer Tool built into WordPress core that hooks
     into most modern themes. You can use it to preview and modify many of your site’s
     appearance settings., the Custom CSS tab is showing up, but when the website finishes
     to load, the tab disappears, it gets the display: none; style.
 10. So the tab is still not visible to administrators, only for a few seconds.
 11. Do you have any idea? Did you test your code on a Multisite install?
 12. Thank you!

Comments are closed.

# Post navigation

[← Preferred Languages: Research](https://make.wordpress.org/core/2016/11/25/preferred-languages-research/)

[Video Headers in 4.7 →](https://make.wordpress.org/core/2016/11/26/video-headers-in-4-7/)