The main purpose of Drupal's Theme system is to give themes complete control
over the appearance of the site, which includes the markup returned from HTTP
requests and the CSS files used to style that markup. In order to ensure that
a theme can completely customize the markup, module developers should avoid
directly writing HTML markup for pages, blocks, and other user-visible output
in their modules, and instead return structured "render arrays" (see
Render arrays below). Doing this also increases usability, by ensuring that the
markup used for similar functionality on different areas of the site is the
same, which gives users fewer user interface patterns to learn.

@todo Check these links. Some are for Drupal 7, and might need updates for
Drupal 8.

Render arrays

The core structure of the Render API is the render array, which is a
hierarchical associative array containing data to be rendered and properties
describing how the data should be rendered. A render array that is returned
by a function to specify markup to be sent to the web browser or other
services will eventually be rendered by a call to drupal_render(), which will
recurse through the render array hierarchy if appropriate, making calls into
the theme system to do the actual rendering. If a function or method actually
needs to return rendered output rather than a render array, the best practice
would be to create a render array, render it by calling drupal_render(), and
return that result, rather than writing the markup directly. See the
documentation of drupal_render() for more details of the rendering process.

Each level in the hierarchy of a render array (including the outermost array)
has one or more array elements. Array elements whose names start with '#' are
known as "properties", and the array elements with other names are "children"
(constituting the next level of the hierarchy); the names of children are
flexible, while property names are specific to the Render API and the
particular type of data being rendered. A special case of render arrays is a
form array, which specifies the form elements for an HTML form; see the
Form generation topic for more information on forms.

Render arrays (at any level of the hierarchy) will usually have one of the
following properties defined:

#type: Specifies that the array contains data and options for a particular
type of "render element" (for example, 'form', for an HTML form;
'textfield', 'submit', for HTML form element types; 'table', for a table
with rows, columns, and headers). See Render elements below for more on
render element types.

#theme: Specifies that the array contains data to be themed by a particular
theme hook. Modules define theme hooks by implementing hook_theme(), which
specifies the input "variables" used to provide data and options; if a
hook_theme() implementation specifies variable 'foo', then in a render
array, you would provide this data using property '#foo'. Modules
implementing hook_theme() also need to provide a default implementation for
each of their theme hooks, normally in a Twig file. For more information
and to discover available theme hooks, see the documentation of
hook_theme() and the
Default theme implementations topic.

#markup: Specifies that the array provides HTML markup directly. Unless
the markup is very simple, such as an explanation in a paragraph tag, it
is normally preferable to use #theme or #type instead, so that the theme
can customize the markup. Note that the value is passed through
\Drupal\Component\Utility\Xss::filterAdmin(), which strips known XSS
vectors while allowing a permissive list of HTML tags that are not XSS
vectors. (For example, <script> and <style> are not allowed.) See
\Drupal\Component\Utility\Xss::$adminTags for the list of allowed tags. If
your markup needs any of the tags not in this whitelist, then you can
implement a theme hook and/or an asset library. Alternatively, you can use
the key #allowed_tags to alter which tags are filtered.

#plain_text: Specifies that the array provides text that needs to be
escaped. This value takes precedence over #markup.

#allowed_tags: If #markup is supplied, this can be used to change which
tags are allowed in the markup. The value is an array of tags that
Xss::filter() would accept. If #plain_text is set, this value is ignored.

See the Plugin API topic for general information
on plugins. You can search for classes with the RenderElement or FormElement
annotation to discover what render elements are available. API reference
sites (such as https://api.drupal.org) generate lists of all existing
elements from these classes. Look for the Elements link in the API Navigation
block.

Modules can define render elements by defining an element plugin.

Caching

The Drupal rendering process has the ability to cache rendered output at any
level in a render array hierarchy. This allows expensive calculations to be
done infrequently, and speeds up page loading. See the
Cache API topic for general information about the cache
system.

In order to make caching possible, the following information needs to be
present:

Cache keys: Identifiers for cacheable portions of render arrays. These
should be created and added for portions of a render array that
involve expensive calculations in the rendering process.

Cache contexts: Contexts that may affect rendering, such as user role and
language. When no context is specified, it means that the render array
does not vary by any context.

Cache tags: Tags for data that rendering depends on, such as for
individual nodes or user accounts, so that when these change the cache
can be automatically invalidated. If the data consists of entities, you
can use \Drupal\Core\Entity\EntityInterface::getCacheTags() to generate
appropriate tags; configuration objects have a similar method.

Cache max-age: The maximum duration for which a render array may be cached.
Defaults to \Drupal\Core\Cache\Cache::PERMANENT (permanently cacheable).

Cache information is provided in the #cache property in a render array. In
this property, always supply the cache contexts, tags, and max-age if a
render array varies by context, depends on some modifiable data, or depends
on information that's only valid for a limited time, respectively. Cache keys
should only be set on the portions of a render array that should be cached.
Contexts are automatically replaced with the value for the current request
(e.g. the current language) and combined with the keys to form a cache ID.
The cache contexts, tags, and max-age will be propagated up the render array
hierarchy to determine cacheability for containing render array sections.

Attaching libraries in render arrays

Libraries, JavaScript settings, feeds, HTML <head> tags and HTML <head> links
are attached to elements using the #attached property. The #attached property
is an associative array, where the keys are the attachment types and the
values are the attached data.

The #attached property can also be used to specify HTTP headers and the
response status code.

Placeholders in render arrays

Render arrays have a placeholder mechanism, which can be used to add data
into the render array late in the rendering process. This works in a similar
manner to \Drupal\Component\Render\FormattableMarkup::placeholderFormat(),
with the text that ends up in the #markup property of the element at the
end of the rendering process getting substitutions from placeholders that
are stored in the 'placeholders' element of the #attached property.

For example, after the rest of the rendering process was done, if your
render array contained:

Within the Symfony render pipeline, there is a Drupal render pipeline,
which handles controllers that return render arrays. (Symfony's render
pipeline only knows how to deal with Response objects; this pipeline
converts render arrays into Response objects.) These render arrays are
considered the main content, and can be rendered into multiple formats:
HTML, Ajax, dialog, and modal. Modules can add support for more formats, by
implementing a main content renderer, which is a service tagged with
'render.main_content_renderer'.

Finally, within the HTML main content renderer, there is another pipeline,
to allow for rendering the page containing the main content in multiple
ways: no decoration at all (just a page showing the main content) or blocks
(a page with regions, with blocks positioned in regions around the main
content). Modules can provide additional options, by implementing a page
variant, which is a plugin annotated with
\Drupal\Core\Display\Annotation\PageDisplayVariant.