Convert a theme function into a Twig template

Needs revision -- Last peer review: 28 Jul 2019
In this lesson you will convert a theme function into a Twig template file

Convert a theme function to a template file & preprocess function:

  1. Identify the file your theme function came from ( a core/modules/color/?)
  2. Create a X.html.twig template file for your theme function:
    • Name your new file appropriately
    • Remove theme_ from the start of your function and end the file name in .html.twig
    • Convert underscores (“_”) to hyphens (“-”).
    • Examples:
      • theme_link() becomes link.html.twig
      • theme_user_signature() becomes user-signature.html.twig
  3. Place your new Twig template in the templates folder in the stark theme (in the sandbox):
    • for functions that came from specific module, stark/templates/comment, etc
    • for functions that came from, stark/templates/
    • for functions that came from, stark/templates/
  4. Go to the Drupal 8 API documentation and search for your function.
  5. Add a PHP-style docblock at the top of the file, and wrap it in Twig comments {# #}
    • Add an @file line at the very top.
    • Copy the definition of the function just below the @file line. Rewrite “Returns HTML ...” as “Default theme implementation ...”. Rewrite it to fit on one line.
    • Add an “Available variables:” line (replace the @param variables)
    • Copy the variables specified under ‘Parameters’ in docs on
    • Remove the @see template_preprocess() line, if it exists.
    • Add an @see template_preprocess_THEME_HOOK() line.
    • Add an @ingroup themeable line (see docblock example below).
  6. Copy the source code for your function below the doc block (see example below)
  7. Change the PHP code into mostly HTML and print statements
    1. Remove PHP code from around the HTML, examples:
      • function whatever() {
      • // …
      • return $output; }
    2. Remove PHP print statements and replace with {{ }}
      • Convert $variables into simple names:
        $variables['title'] becomes {{ title }}
      • Replace array syntax with dot syntax:
        $variables['page']['tabs'] becomes {{ page.tabs }}
    3. Remove PHP logic and replace with {% %} twig syntax.
      <?php foreach $items as $item ?> becomes
      {% for item in items%}
    4. Replace PHP comments with twig syntax comments: {# #}
    5. Replace t() functions around literals with the t filter:
      {{ 'text in quotes'|t }}
    6. Move all PHP logic for variables to a preprocess function. (for instructions on preprocessing, see below.)
  8. If, as you do this, you notice things you want to improve, like consolidating seemingly redundant templates into a single one, or improving the markup or variable names, make a note of that in this spreadsheet or create an issue on our sandbox. For example:

Convert or consolidate to preprocess functions


  1. Preprocess functions will replace all theme functions.
  2. If your template file has PHP logic in it that affects the variables that are being printed, that code will need to be moved to a preprocess function.
  3. If your template began as a theme function, the theme function will need to be converted to a preprocess function.
  4. In the case that some theme functions already have related preprocess functions, the variable handling code in those theme functions needs to be moved into preprocess.
  5. Do not add a line to your hook_theme implementation telling Drupal to use a template file instead of a theme function.


  1. Rename theme_YOURFUNCTION to template_preprocess_YOURFUNCTION.
  2. Pass the $variables by reference by adding an ampersand.  i.e. theme_select($variables) becomes template_preprocess_select(&$variables).
  3. Edit the function to handle only the variable processing logic; Remove any markup (i.e. $output).

If there are missing functions in your twig templates...

If you need access to a filter or function in your Twig template that is not working yet, please add it to this open issue. Keep in mind that most PHP or Drupal functions should be moved to preprocess functions instead. Only if you think a theme dev will need access to this function should it remain in the template.


PHP code from!includes!

function theme_link($variables) {
return '' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '';

Twig template (file name: link.html.twig)

* @file
* Default theme implementation to display a link.
* Available variables:
* - text: The link text for the anchor tag.
* - url: The complete URL being linked to, such as
* "/node/34" or "".
* - attributes: Remaining HTML attributes for the containing element.
* @see template_preprocess_link()
* @ingroup themeable
{{ text }}

Changes to system.module (preprocess function)

* Prepares variables for link templates.
* Default template: link.html.twig.
* @param array $variables
* An associative array containing:
* - text: The translated link text for the anchor tag.
* - path: The internal path or external URL being linked to.
* - options: An associative array of additional options.
function template_preprocess_link(&$variables) {
$variables['url'] = url($variables['path'], $variables['options']);

More up-tp-date information can be found here:

Lesson tags: