File: /var/www/delta/wp-content/themes/delta/vendor/timber/timber/docs/guides/gutenberg.md
---
title: "Gutenberg"
menu:
  main:
    parent: "guides"
---
## Using Gutenberg with Timber
Timber works with Gutenberg out of the box. If you use `{{ post.content }}`, Timber will render all the Gutenberg blocks.
## ACF Blocks
### What are ACF Blocks?
ACF Blocks are an alternative way to create content blocks without advanced JavaScript knowledge. If you want to learn more about them, read the article on [advancedcustomfields.com](https://www.advancedcustomfields.com/blog/acf-5-8-introducing-acf-blocks-for-gutenberg/).
### How to use ACF Blocks with Timber
Before you can start using ACF Blocks, you must install the Advanced Custom Fields 5.8.0-beta version or later.
To create a content block, you first have to register it in **functions.php** or in a separate plugin:
```php
add_action( 'acf/init', 'my_acf_init' );
function my_acf_init() {
    // Bail out if function doesn’t exist.
    if ( ! function_exists( 'acf_register_block' ) ) {
        return;
    }
    // Register a new block.
    acf_register_block( array(
        'name'            => 'example_block',
        'title'           => __( 'Example Block', 'your-text-domain' ),
        'description'     => __( 'A custom example block.', 'your-text-domain' ),
        'render_callback' => 'my_acf_block_render_callback',
        'category'        => 'formatting',
        'icon'            => 'admin-comments',
        'keywords'        => array( 'example' ),
    ) );
}
```
Next, you you have to create your `render_callback()` function:
```php
/**
 *  This is the callback that displays the block.
 *
 * @param   array  $block      The block settings and attributes.
 * @param   string $content    The block content (emtpy string).
 * @param   bool   $is_preview True during AJAX preview.
 */
function my_acf_block_render_callback( $block, $content = '', $is_preview = false ) {
    $context = Timber::context();
    // Store block values.
    $context['block'] = $block;
    // Store field values.
    $context['fields'] = get_fields();
    // Store $is_preview value.
    $context['is_preview'] = $is_preview;
    // Render the block.
    Timber::render( 'block/example-block.twig', $context );
}
```
You create an extra array called `$context` with three values:
- **block** - with all data like block title, alignment etc
- **fields** - all custom fields - also all the fields created in **ACF**
- **is_preview** - returns true during AJAX preview
Finally, you can create the template **block/example-block.twig**:
```twig
{#
/**
 * Block Name: Example block
 *
 * This is the template that displays the example block.
 */
#}
{% if is_preview %}
    <p>I will only appear in the editor.</p>
{% endif %}
<div id="example-{{ block.id }}" class="wrapper">
    <h1>{{ fields.title }}</h1>
    <p>{{ fields.description }}</p>
</div>
<style type="text/css">
    #testimonial-{{ block.id }} {
        background: {{ fields.background_color }};
        color: {{ fields.text_color }};
    }
</style>
```
If you would like to use an external stylesheet both inside of the block editor and the frontend you should add:
```php
function my_acf_block_editor_style() {
    wp_enqueue_style(
        'example_block_css',
        get_template_directory_uri() . '/assets/example-block.css'
    );
}
add_action( 'enqueue_block_assets', 'my_acf_block_editor_style' );
```
For more details about enqueueing assets read the [Gutenberg Handbook](https://wordpress.org/gutenberg/handbook/blocks/applying-styles-with-stylesheets/#enqueueing-editor-only-block-assets).
### Using repeaters
```
{% for field in fields.repeater %}
    Title: {{ field.title }} <br/>
    Url: {{ field.url }}
{% endfor %}
```
### Using groups
```
Title: {{ fields.group.title }} <br/>
Url: {{ fields.group.url }}
```