---
title: "Configure custom backend preview for content element"
manual: "TYPO3 Explained"
version: "12.4"
permalink: "https://docs.typo3.org/permalink/t3coreapi:configurece-preview@12.4"
source: "ApiOverview/ContentElements/CustomBackendPreview.rst"
rendered: "2026-10-21T15:29:37+00:00"
---

> [!WARNING]
> **Attention**
>
> TYPO3 v12 has reached end-of-life as of April 30th 2026 and
> is no longer being maintained. Use the version switcher on the top
> left of this page to select documentation for a supported version of TYPO3.
>
> Need more time before upgrading?
> You can purchase Extended Long Term Support (ELTS) for TYPO3 v12 here:
> [TYPO3 ELTS](https://typo3.com/services/extended-support-elts).

# Configure custom backend preview for content element {#configurece-preview}

To allow editors a smoother experience, all custom content elements and plugins
should be configured with a corresponding backend preview that shows an
approximation of the element's appearance in the TYPO3 page module. The
following sections describe how to achieve that.

A preview renderer is used to facilitate (record) previews in TYPO3. This
class is responsible for generating the preview and the wrapping.

The default preview renderer is `\TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer`
and handles the Core's built-in content types (field `CType` in table `tt_content`).

## Extend the default preview renderer {#extend-the-default-preview-renderer}

There are two ways to provide previews for your custom content types:
via page [TSconfig](https://docs.typo3.org/permalink/t3coreapi:configurece-preview-pagetsconfig@12.4) or [event listener](https://docs.typo3.org/permalink/t3coreapi:configurece-preview-eventlistener@12.4).

### Page TSconfig {#configurece-preview-pagetsconfig}

This is the "integrator" way, no PHP coding is required. Just some page TSconfig
and a Fluid template.

**EXT:my_extension/Configuration/page.tsconfig**

```typoscript
mod.web_layout {
  tt_content {
    preview {
      # Your CType
      example_ctype = EXT:my_extension/Resources/Private/Templates/Preview/ExampleCType.html
    }
  }
}
```

In the Fluid template, the following variables are available:

-   All properties of the `tt_content` row (for example `{uid}`, `{title}`, and `{header}`)
-   FlexForm settings as array in `{pi_flexform_transformed}`

For more details see the [TSconfig Reference](https://docs.typo3.org/m/typo3/reference-typoscript/12.4/en-us/PageTsconfig/Mod/WebLayout.html#pageweblayoutpreview).

### Event listener {#configurece-preview-eventlistener}

This requires at least some PHP coding, but allows more flexibility in
accessing and processing the content elements properties.

<!-- TODO: no Markdown rendering for "versionadded" -->

Since version 12.0 this technique replaces the former hook
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']

The event `PageContentPreviewRenderingEvent` is being dispatched by the
`StandardContentPreviewRenderer`. You can listen to it with your own
event listener.

Have a look at this [showcase implementation](https://docs.typo3.org/permalink/t3coreapi:pagecontentpreviewrenderingevent@12.4).

For general information see the chapter on [implementing an event listener](https://docs.typo3.org/permalink/t3coreapi:eventdispatcherimplementation@12.4).

## Writing a preview renderer {#writing-a-preview-renderer}

A custom preview renderer must implement the interface
`\TYPO3\CMS\Backend\Preview\PreviewRendererInterface` which contains
the following API methods:

-   **interface PreviewRendererInterface**

    -   *Fully qualified name:* `\TYPO3\CMS\Backend\Preview\PreviewRendererInterface`

    Interface PreviewRendererInterface

    Contract for classes capable of rendering previews of a given record
    from a table. Responsible for rendering preview header, preview content
    and wrapping of those two values.

    Responsibilities are segmented into three methods, one for each responsibility,
    which is done in order to allow overriding classes to change those parts
    individually without having to replace other parts. Rather than relying on
    implementations to be friendly and divide code into smaller pieces and
    give them (at least) protected visibility, the key methods are instead required
    on the interface directly.

    Callers are then responsible for calling each method and combining/wrapping
    the output appropriately.

    -   **renderPageModulePreviewHeader(\\TYPO3\\CMS\\Backend\\View\\BackendLayout\\Grid\\GridColumnItem $item)**

        Dedicated method for rendering preview header HTML for
        the page module only. Receives the the GridColumnItem
        that contains the record for which a preview header
        should be rendered and returned.

        -   *param $item:* the item

        *Returns:* `string`

    -   **renderPageModulePreviewContent(\\TYPO3\\CMS\\Backend\\View\\BackendLayout\\Grid\\GridColumnItem $item)**

        Dedicated method for rendering preview body HTML for
        the page module only. Receives the the GridColumnItem
        that contains the record for which a preview should be
        rendered and returned.

        -   *param $item:* the item

        *Returns:* `string`

    -   **renderPageModulePreviewFooter(\\TYPO3\\CMS\\Backend\\View\\BackendLayout\\Grid\\GridColumnItem $item)**

        Render a footer for the record to display in page module below
        the body of the item's preview.

        -   *param $item:* the item

        *Returns:* `string`

    -   **wrapPageModulePreview(string $previewHeader, string $previewContent, \\TYPO3\\CMS\\Backend\\View\\BackendLayout\\Grid\\GridColumnItem $item)**

        Dedicated method for wrapping a preview header and body
        HTML. Receives $item, an instance of GridColumnItem holding
        among other things the record, which can be used to determine
        appropriate wrapping.

        -   *param $previewHeader:* the previewHeader
        -   *param $previewContent:* the previewContent
        -   *param $item:* the item

        *Returns:* `string`

Implementing these methods allows you to control the exact composition of the
preview.

This means assuming your preview renderer returns `<h4>Header</h4>`
from the header render method and `<p>Body</p>` from the preview content
rendering method and your wrapping method does
`return '<div>' . $previewHeader . $previewContent . '</div>';` then the
entire output becomes `<div><h4>Header</h4><p>Body</p></div>` when
combined.

Should you wish to reuse parts of the default preview rendering and only change,
for example, the method that renders the preview body content, you can extend
`\TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer` in your custom
preview renderer class - and selectively override the methods from the API
displayed above.

## Configuring the implementation {#configuring-the-implementation}

Individual preview renderers can be defined by using one of the following
approaches:

1.  Any record

    ```php
    $GLOBALS['TCA'][$table]['ctrl']['previewRenderer']
        = MyVendor\MyExtension\Preview\MyPreviewRenderer::class;
    ```

    This specifies the preview renderer to be used for any record in `$table`.
1.  Table has a type field/attribute

    ```php
    $GLOBALS['TCA'][$table]['types'][$type]['previewRenderer']
        = MyVendor\MyExtension\Preview\MyPreviewRenderer::class;
    ```

    This specifies the preview renderer only for records of type `$type` as
    determined by the [type field](https://docs.typo3.org/m/typo3/reference-tca/12.4/en-us/Types/Index.html#types) of your table.
1.  Table and field have a `subtype_value_field` TCA setting

    If your table and field have a
    [subtype_value_field](https://docs.typo3.org/m/typo3/reference-tca/12.4/en-us/Types/Index.html#types-properties-subtype-value-field) TCA
    setting (like `tt_content.list_type` for example) and you want to
    register a preview renderer that applies only when that value is selected
    (assume, when a certain plugin type is selected and you can't match it with
    the "type" of the record alone):

    ```php
    $GLOBALS['TCA'][$table]['types'][$type]['previewRenderer'][$subType]
        = MyVendor\MyExtension\Preview\MyPreviewRenderer::class;
    ```

    Where `$type` is, for example, `list` (indicating a plugin) and
    `$subType` is the value of the `list_type` field when the type of
    plugin you want to target is selected as plugin type.

> [!NOTE]
> The [recommended location](https://docs.typo3.org/permalink/t3coreapi:extension-configuration-tca@12.4) is in the
> `ctrl` array in your extension's [`Configuration/TCA/$table.php`](../../ExtensionArchitecture/FileStructure/Configuration/TCA/Index.md#file-extension-configuration-tca-tablename-php)
> or [`Configuration/TCA/Overrides/$table.php`](../../ExtensionArchitecture/FileStructure/Configuration/TCA/Index.md#file-extension-configuration-tca-tablename-php) file. The former is used
> when your extension is the one that creates the table, the latter is used
> when you need to override TCA properties of tables added by the Core or
> other extensions.

> [!NOTE]
> The content elements `text`, `textpic`, `textmedia` and
> `image` have their own `PreviewRenderer`. Therefore it's not
> sufficient to overwrite the `StandardContentPreviewRenderer` but
> you need to use the second approach from above for every single of
> these content elements.
