---
title: "Reading content records"
manual: "TypoScript Explained"
version: "13.4"
permalink: "https://docs.typo3.org/permalink/t3tsref:guide-content-records@13.4"
source: "Guide/Content/Index.rst"
rendered: "2026-09-27T06:56:59+00:00"
---

# Reading content records {#guide-content-records}

> [!NOTE]
> The following chapter aims at explaining the relationship between database
> content and frontend output via TypoScript. The TYPO3 Core and system
> extension `fluid_styled_content` already contain definitions for the TYPO3
> Core content element rendering. You do not have to add anything yourself.
>
> If you wish a content element to be rendered differently or if you program
> an extension with new content elements, it will be necessary to understand
> this relationship to be able to design your own TypoScript properly.

Obviously entering all content for the website would be terribly tiresome,
although possible from a theoretical point of view.

What we want is to have a TypoScript which gathers the content automatically.
The example below creates a page on which, for each content element on that
page, the headline and the text is displayed.

After creating the [PAGE](https://docs.typo3.org/permalink/t3tsref:page@13.4) object, we use the [CONTENT](https://docs.typo3.org/permalink/t3tsref:cobj-content@13.4) object to retrieve content from the database. For each
content element we use the [TEXT](https://docs.typo3.org/permalink/t3tsref:cobj-text@13.4) object to perform
the actual rendering:

**EXT:site_package/Configuration/Sets/Main/setup.typoscript**

```typoscript
page = PAGE
page.typeNum = 0

# The CONTENT object executes a database query and loads the content.
page.10 = CONTENT
page.10.table = tt_content
page.10.select {

  # "sorting" is a column from the tt_content table and
  # keeps track of the sorting order, which was specified in
  # the backend.
  orderBy = sorting

  # Only select content from column "0" (the column called
  # "normal") and quote the database identifier (column name)
  # "colPos" (indicated by wrapping with {#})
  where = {#colPos}=0
}

# For every result line from the database query (that means for every content
# element) the renderObj is executed and the internal data array is filled
# with the content. This ensures that we can call the .field property and we
# get the according value.
page.10.renderObj = COA
page.10.renderObj {

  10 = TEXT

  # The field tt_content.header normally holds the headline.
  10.stdWrap.field = header

  10.stdWrap.wrap = <h1>|</h1>

  20 = TEXT

  # The field tt_content.bodytext holds the content text.
  20.stdWrap.field = bodytext

  20.stdWrap.wrap = <p>|</p>
}

```

The [CONTENT](https://docs.typo3.org/permalink/t3tsref:cobj-content@13.4) object executes an SQL query on the
database. The query is controlled by the `select` property, which - in
our case - defines that we want all records from the column 0 (which is the
column called "NORMAL" in the backend), and that the result should be sorted
according to the field called "sorting".

The `select` property has a `pidInList` which can be used to
retrieve elements from a specific page. If it is not defined
\- as in our example - elements are taken from the current page.

The `renderObj` property defines how each record gets rendered. It is
defined as [COA (Content Object Array)](https://docs.typo3.org/permalink/t3tsref:cobj-coa@13.4), which can hold
an arbitrary number of TypoScript objects. In this case, two [TEXT](https://docs.typo3.org/permalink/t3tsref:cobj-text@13.4) objects are used, which are rendered one after the other
(remember that the order of the rendering is not controlled by the order in
TypoScript, but by the numbers with which they are defined). The [TEXT](https://docs.typo3.org/permalink/t3tsref:cobj-text@13.4) object "10" will be created first and the [TEXT](https://docs.typo3.org/permalink/t3tsref:cobj-text@13.4) object "20" will be rendered after it.

The challenge is to render all content elements like the web designer
predetermined. Therefore, we have to create TypoScript definitions for every
single database field (e.g. for images, image size, image position, link to
top, index, etc.).

# Insert content in a HTML template {#insert-content-in-a-html-template}

Although we now know how to render content, we do not
have a real website yet.

Again everything could be done using TypoScript. That would be pretty complex
and error prone. Furthermore if a HTML template file is prepared by a designer
for the website, it would be a shame not to reuse it as is as much as
possible. It would also make further corrections to the HTML template much
harder to apply.

TYPO3 CMS provides the [FLUIDTEMPLATE](https://docs.typo3.org/permalink/t3tsref:cobj-fluidtemplate@13.4)
object, with which we can use Fluid template and render our website with it:

```typoscript
10 = FLUIDTEMPLATE
10 {
  templateName = Default

  templateRootPaths {
    0 = EXT:site_package/Resources/Private/Templates/Pages/
  }
  partialRootPaths {
    0 = EXT:site_package/Resources/Private/Partials/Pages/
  }
  layoutRootPaths {
    0 = EXT:site_package/Resources/Private/Layouts/Pages/
  }
}

```

In your template file you can now replace the parts that should be filled by
TYPO3 with references to the TypoScript configuration objects you defined
earlier.

For example to render a template with the menu we defined add:

```html
<nav>
  <f:cObject typoscriptObjectPath="lib.textmenu" />
</nav>

<div class="container">
  <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{pageUid: '{data.uid}', colPos: '0'}" />
</div>

```

# The various content elements {#the-various-content-elements}

The setup we just defined is pretty basic and will work only for content
elements containing text. But the content elements are varied and we also need
to render images, forms, etc. and we do not want to define everything in
TypoScript - using HTML templates would be more convenient.

The type of a content element is stored in the column
`CType` of table "tt_content". We can use this information
with a [CASE](https://docs.typo3.org/permalink/t3tsref:cobj-case@13.4) object, which makes it possible to
differentiate how the individual content element types are rendered.

The following code is the default TypoScript rendering definition as taken from
the TYPO3 Core. The default `renderObj` of a table is a TypoScript
definition named after that table. In case of content in TYPO3 the table is
called `tt_content` therefore the default `renderObj` is also called
`tt_content`:

**Content element rendering taken from typo3/sysext/frontend/ext_localconf.php**

```typoscript
tt_content = CASE
tt_content {
  key {
    # The field CType will be used to differentiate.
    field = CType
  }
  # Render a error message in case no specific rendering definition is found
  default = TEXT
  default {
    field = CType
    htmlSpecialChars = 1
    wrap = <p style="background-color: yellow; padding: 0.5em 1em;"><strong>ERROR:</strong> Content Element with uid "{field:uid}" and type "|" has no rendering definition!</p>
    wrap.insertData = 1
  }
}

```

The basic extension for rendering content in TYPO3 since TYPO3 v8 is
`fluid_styled_content`. The example shows how
`fluid_styled_content` is set up: It defines a basic content element based
on the content object `FLUIDTEMPLATE` which is able to render html
templates using the Fluid templating engine. For every content element,
the basic template, layout and partial parts are defined. As you can see by
looking at the lines starting with `10 =` there is the possibility to
add your own templates by setting the corresponding `constant` (in the
`Constants` section of a TypoScript record):

**Taken from typo3/sysext/fluid_styled_content/Configuration/TypoScript/Helper/ContentElement.typoscript**

```typoscript
lib.contentElement = FLUIDTEMPLATE
lib.contentElement {
  templateName = Default
  templateRootPaths {
    0 = EXT:fluid_styled_content/Resources/Private/Templates/
    10 = {$styles.templates.templateRootPath}
  }
  partialRootPaths {
    0 = EXT:fluid_styled_content/Resources/Private/Partials/
    10 = {$styles.templates.partialRootPath}
  }
  layoutRootPaths {
    0 = EXT:fluid_styled_content/Resources/Private/Layouts/
    10 = {$styles.templates.layoutRootPath}
  }
  # ...
}

```

Each content element inherits that configuration. As an example take a look at
the content element definition of the content element of type `header`:

**Taken from typo3/sysext/fluid_styled_content/Configuration/TypoScript/ContentElement/Header.typoscript**

```typoscript
# Header Only:
# Adds a header only.
#
# CType: header
tt_content.header =< lib.contentElement
tt_content.header {
  templateName = Header
}

```

First, all configuration options defined in `lib.contentElement` are
referenced. Then the `templateName` for rendering a content element of
type `header` is set - in this case `Header`. This tells fluid to
look for a
`Header.html` in the defined template path(s) (see above, by default in
`EXT:fluid_styled_content/Resources/Private/Templates/`).

To adjust how the default elements are rendered you can overwrite the templates
in your own site package extension and set the TypoScript constants defining
the paths (see above). In your own templates you have the data of the currently
rendered content element available in the {data} fluid variable. For example
take a look at how the text element is rendered:

**Taken from typo3/sysext/fluid_styled_content/Resources/Private/Templates/Text.html**

```html
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:layout name="Default" />
<f:section name="Main">
  <f:format.html>{data.bodytext}</f:format.html>
</f:section>
</html>

```

The database field `bodytext` from the `tt_content` table (which is
the main text input field for content elements of type `text`) is
available as `{data.bodytext}` in the Fluid template. For more
information about `fluid_styled_content` see its [manual](https://docs.typo3.org/c/typo3/cms-fluid-styled-content/13.4/en-us/Index.html).
