WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.54k stars 4.22k forks source link

Ability to extract Gutenberg CSS that has been inlined - For Headless #54510

Open xstaticwebdev opened 1 year ago

xstaticwebdev commented 1 year ago

What problem does this address?

This feature request is important to allow WordPress to act as a Headless CMS.

The rest api provides a "content" field for the raw HTML for a given post which is great, but it's sort of useless for display purposes unless we can access the corresponding CSS for that post. We used to be able to just import the Gutenberg CSS to our front end application with: import "@wordpress/block-library/build-style/common.css" import "@wordpress/block-library/build-style/style.css" import "@wordpress/block-library/build-style/theme.css"

Recently though, Gutenberg has started injecting inline CSS and dynamically adding CSS classes to Gutenberg blocks. For example:

In order to use WordPress as a Headless CMS we need to be able to extract this CSS somehow.

What is your proposed solution?

Since WordPress is dynamically generating this CSS already it should be fairly straightforward to create a function:

get_post_inline_css(post_id) - or something similar. With this function a headless implementer could create a custom rest api route that can be queried by the front end so we can display the post content correctly.

aristath commented 1 year ago

You should be able to get all of them by using wp_styles() to get an array of all stylesheet - and their inline additions

xstaticwebdev commented 1 year ago

Is there a way to get wp_styles() to get inline styles for a specific post? In my experiments I seem to only be able to get styles that apply to all posts.

So I'm almost there, but missing styles such as:

spencerfinnell commented 1 year ago

@xstaticwebdev your feedback and contributions would be appreciated in #53874

aristath commented 1 year ago

Posting an example of how you can use wp_styles() to get all the inline styles from a page. Please note that the code below is just a proof of concept for demonstration purposes and will need to be adapted to your use-case:

add_action( 'wp_footer', function() {
    $inline_styles = '';
    foreach ( wp_styles()->queue as $style ) {
        $inline_styles .= isset( wp_styles()->registered[ $style ]->extra['after'] )
            ? implode( '', wp_styles()->registered[ $style ]->extra['after'] ) 
            : '';
    }

    // The $inline_styles variable now contains all the inline styles on the page.
    // You can write them to a file, or do whatever your application requires.
}, 99999 );
xstaticwebdev commented 1 year ago

@aristath - this was very helpful and with some kung foo I was able to get most of the inlined css for a given post.

However... the dynamic CSS generated by some blocks, where a class name is added dynamically (i.e. - .wp-container-XXX) and is associated with the style with ID - 'core-block-supports-inline-css', is not included.

    <style id='core-block-supports-inline-css'>
        .wp-container-3.wp-container-3 {
            justify-content: flex-end;
        }

        .wp-container-7.wp-container-7 {
            grid-template-columns: repeat(3, minmax(0, 1fr));
        }

        .wp-container-4.wp-container-4,.wp-container-8.wp-container-8,.wp-container-14.wp-container-14 {
            justify-content: space-between;
        }
    </style>
youknowriad commented 1 year ago

This seems like a duplicate of #54047

augustl commented 1 year ago

Chiming in on this one :) I'm relatively inexperienced with Wordpress, but I just set up a self hosted instance that uses API + webhooks to keep a Next.JS based front-end up to date. The requirements for the page I built were pretty spartan, so I just manually implemented some of the CSS classes. No need for JS with image galleries, full support for all blocks, etc.

But, it would be nice if I could somehow add a dependency to my Next.JS app and then just have all the Gutenberg CSS + JS available there!

adisak1618 commented 10 months ago

@xstaticwebdev Did you try headless CMS with twenty twenty one theme. I see it has sass file in theme and we might can use it without worry about core-block-supports maybe?

MadtownLems commented 2 months ago

get_post_inline_css(post_id) - or something similar.

After implementing a version of this myself, I quickly realized why this isn't a viable solution: WordPress generates unique class names with each render, such as wp-elements-1234456789. When viewing the post in a traditional context, the appropriate inline css is added to the header or footer in