I want to output a google map div with a side panel in my drupal 8 moodule. So no need for blocks surrounding my main content.

The question is how do I tell Drupal to only render main content using a Twig template of my module without outputting the entire Drupal theme stuff a long with the menus and the blocks?

All online materials I found so far talks about concepts behind Drupal rendering mechanism and render arrays but none really tell something about their implementation.

Take for instance, the concept of page variants in the following link. HTMLRenderer fires an event to determine which type of page will be used to wrap the main content around: RenderEvents::SELECT_PAGE_DISPLAY_VARIANT. Its also says the SimplePageVariant, which will only output the main content, is suppose to be used by default but in case the Block module is enabled like my case, the BlockPageVariant kicks in to allow the placement of blocks in the regions around the main content. It continues, if you want, you can subscribe to this event in your own module and provide your own variant. However, I couldn't figure out how to do this subscribing.

I feel what I want is simpler than creating my own Page variant. I just want to output simple html with two divs in the Twig template of my own module.

Anyone has an idea what to do?


So there are two ways to do this as mentioned in the answer below, I will just summarize them and add a little more clarification of naming convention in drupal 8:

Return a basic Symfony response with out any drupal specific rendering:

$element['#title'] = 'Title';
$html = \Drupal::service('renderer')->renderRoot($element);
$response = new Response();
return $response;

Doing so, you will not be able to attach css or js libraries with render arrays. However, if you want to do that you can override the page.html.twig by following dupral 8 template naming conventions link with out returning "pure symfony" response and hindering drupal from finishing its theming.

2 Answers 2


There are two similar questions.

Problems creating a custom blank page with my custom module

How to output from custom module without rest of theme

You can use a symfony response or replace the page template with a blank twig in hook_theme().

  • Ran into another problem Using a pure symfony response it seems doesn't allow you to attach assets - JS or CSS files to the render array. Doing so: $build['#attached']['library'] = 'mymodule/my-lib'; with the render array should output an html head tag and js/css files with the page but the attached library gets neglected for some reason. Then what is inside the twig template only gets printed out, even <html> is not present. Tried many things but none worked. My fear is that I might need to use {% block javascripts %} in the twig template, how to reference my js files then? Any idea? Commented Apr 30, 2016 at 15:28
  • By using a pure symfony response there is no html template. From your comment it seems, that you want to keep the html template and only override the page template. Did you try the code in the second question, I mean the question itself, because the OP has updated the code in the question with what was discussed in the comments.
    – 4uk4
    Commented Apr 30, 2016 at 16:24
  • Thanks for your reply 4k4, but I don't understand what is the difference between the html template and page template. Are you referring to the website general theme vs the module twig template? In your previous answer what do you mean by: Override page.html.twig and html.html.twig, remove anything out of this templates and put only that in what you want. Where are both files? Commented Apr 30, 2016 at 18:07
  • What is really daunting is when using pure symfony response you could still use the twig template of your module and outputting stuff such as {{ name }} still works but when using {{ attach_library() }} function directly from twig, it gets totally bypassed... Commented Apr 30, 2016 at 18:14
  • ... bypassing the theme is why you would use a symfony response. And without a theme you don't have attach_library, but also hundreds of other things. Perhaps you only want to override page.html.twig. Normally you do this in the theme. I would start with this, because it is straightforward. To get a feeling for it, remove anything from page.html.twig, so you have no menu, no blocks, nothing and put back step by step parts of the original twig. When you have the result you want you can try to move the twig to the module. But you only need this, if you want to distribute it with the module.
    – 4uk4
    Commented Apr 30, 2016 at 22:08

If you need to render a piece of content with no regions or blocks, but just the piece of content, wrapped in valid HTML, with the ability to attach CSS/JS or whatnot you can do the following. In this example, I am going to wrap a field of a node in proper HTML (HTML tag, head tag, body tag etc), with nothing else at all. This content will be accessible at a route/path, so that it can be used in an iframe.


  • Node has: field_description - a textfield that needs to be rendered in a stand alone page
  • Goal is to render the description, alone as a stand-alone, valid HTML page.

Step 1: Create a route

Create a route that will be used for the description

  path: '/node/{node}/description'
    _controller: '\Drupal\example\Controller\Controller::descriptionRaw'
    _title: 'Description'
    _permission: 'access content'
    node: \d+
        type: entity:node

This route calls \Drupal\example\Controller\Controller::descriptionRaw() to generate the page response.

Step 2: Build the Controller Response

The next step is to build the controller response:

public function descriptionRaw(NodeInterface $node) {
  $page = [
    // Note - the view mode here is `standalone_description` - a
    // custom view mode (More to come later in the tutorial)
    'description' => $node->field_description->view('standalone_description'),
    // If you need CSS/JS, you can attach the library
    '#attached' => [
      'library' => 'example/description_raw',

  return $page;

At this point, the page will be rendered with all the regions/content etc, so the requirements aren't yet met.

Step 3: Create a New Page Template for the Standalone Description

The next thing is to create a theme suggestion for the audio player page, that will override the default page.html.twig template. This is done by implementing hook_theme_suggestions_page():

function HOOK_theme_suggestions_page(array $variables) {
  $suggestions = [];
  $route_name = \Drupal::routeMatch()->getRouteName();
  if ($route_name == 'node.description_raw') {
    $suggestions[] = 'page__description_raw';

  return $suggestions;

Now when accessing the route defined in step 1, the system will look for the template page--description-raw.html.twig in the active theme, and if it exists, it will use that template to render the page, rather than the default page.html.twig.

Step 4: Create the template to render the content

The next step is to create the template used to render the content, as defined in the theme suggestions in the last step. The content of this template is very simple. page--description-raw.html.twig:

{{ page.content }}

This is very simple, as only the content of the page should be rendered, and nothing else. In this case, the content of the page is the description field that was set in the controller.

Step 5: Adjust settings using view modes

There is still likely a lot of unwanted markup around the description from labels. In the controller, the field was set to use the view mode standalone_description. The first step is to create this view mode:

  1. Navigate to Admin -> Structure -> Display modes -> View modes -> Add view mode
  2. Click Content (for nodes)
  3. Enter Standalone Description (machine name standalone_description)
  4. Save

Next, the new view mode must be configured:

  1. Navigate to Admin -> Content types -> [Content Type] -> Manage Display
  2. Scroll to the bottom and expand 'Custom display modes'
  3. Check Standalone Description (the view mode just created)
  4. Save.
  5. Click on the newly created Standalone Description tab
  6. Hide all fields other than the description
  7. Set the label to be 'visually-hidden' (For the sight-impaired)
  8. Set the format to your desired settings
  9. Save

When this is all said and done, the field on the node is rendered in a stand-alone HTML page, and is customizable through the newly created view mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.