How to Create a Simple Responsive Drupal 8 Theme From Scratch


Why create a D8 theme from scratch?

  1. Understand how drupal theming works - why there is such a step, why you need to have these files.
  2. Have your own base theme, rather than relying on the products of someone else.
  3. Improve Drupal theming skill. The most useful way to study is to practice and create one for yourself from the ground up.
  4. Learn the differences between Drupal 8 & Drupal 7 theming.

Understanding Theme Folder Structure & Theme Files

Before starting, we need to know how a complete D8 theme structure looks like. This is to help you have a visual image in your head to get your job easier in the the subsequent steps.

And below are the descriptions of the most common theme files & keys you can find in a D8 theme.
  1. .info.yml  -  this mandatory file gives information about your theme
  2. .libraries.yml  -  defines your libraries (mostly your JS, CSS files).
  3. .breakpoints.yml  -  defines the points to fit different screen devices.
  4. .theme  -  The PHP file that stores conditional logic and data preprocessing of the variables before they are merged with markup inside the .html.twig file.
  5. /css  -  where your css files lay. Must be defined in the info, and libraries file to operate.
  6. /js  -  where your js files lay. Must be defined in the info, and libraries file to operate.
  7. /images  -  where you theme images are stored. It is a good practice to put images in this folder.
  8. /includes  -  where 3rd-parties libraries (like Bootstrap, Foundation, Font Awesome,etc) are put. It is a good practice to store them in this folder
  9. /templates  -  where all your template files (ones that provide html markup of your theme page) are placed.
  10. logo.png  -  your theme logo if you're using one.
  11. favicon.ico  -  your theme favicon if you're using one.
  12. screenshot.png  -  your theme screenshot that will be displayed in the admin/appereance.

Your Theme Layout Display

We should decide how the website layout looks like first. We are going to make it really simple. As shown below, your Drupal template will consist a header, sidebar, content area, and footer.

After you have grasped some basic ideas about your template folder, its files, and the layout of your theme, let's move to the main part - create a simple responsive Drupal 8 template.

1. Create theme folders

The foremost thing you must know is that in Drupal 8, the theme folder lies in core/theme, not sites/all/theme like in Drupal 7 anymore. The basic theme folder will have sub-folders for images, CSS, JS, templates (this one holds twig templating files), and includes (to store 3rd-party libraries ). We will create a basic theme folder structure as follows:

  1. Theme    
Inside the folder 
  1. CSS      
  2. JS      
  3. templates      
  4. includes

2. Create the .info.yml file

How do Drupal templating engine scan for the information of your theme? The .info.yml file is the answer.
It is no denying that the .info.yml file is the most important file you need to include first.
Note that if you have been acquainted with Drupal 7 theming system, [theme_name].info is no longer applied. In D8, you must use .info.yml extension for the info file.

A compplete info.yml file will have these following keys:

  1. name (required)  -  The name of your theme, which will show up in the administration/appearance D8 admin
  2. description(optional yet recommended)  -  What you want to describe about your theme, which also appear in the Administration/Appearance
  3. version (optional)  -  The version of your theme. It will show behind the theme name.
  4. type (required)  -  Notify Drupal about the type of extension. E.g. Theme, Module, or Profile.
  5. core (required)  -  The major version of Drupal core that is supported
  6. base theme (optional yet recommended)  -  Indicate what base theme your custom theme will inherit. If not defined, Drupal will use “Stable” as your base theme.
  7. region (optional)  -  Define the regions of the theme where you place your blocks. If not declaring any regions in the .info.yml file, Drupal will use the default regions of the core. Keep in mind that if you define the regions even just one, default regions are no longer applied. “content” region is required to exist if you define regions in the info file
Now for your .info.yml file, we'll include these values

name: Basis
type: theme
base theme: classy
Description: "A modern & responsive Drupal 8 Theme"
package: custom
core: 8.x


  •       headline: headline
  •       header: header
  •       content: content
  •       sidebar: sidebar
  •       footer: Footer

headline, header, content, sidebar, footer have been included in the region section. This is to notify Drupal templating machine that your theme will have these regions.

However, defining them here is not enough. These regions still do not show up. You must also include them in the page.html.twig file. (which we will cover in step 4).

Notice that classy is used as the base theme. In D8, there are 2 default base themes - Stable & Classy. We have explained the differences of the two in our past post. Basically,

Stable: minimal markup and very few classes
Classy: provides some default markups with sensible classes for styling
We like to use Classy as it has given some predefined proper classes that make the styling job more convenient.


This is a change in D8. While in D7, you will indicate all your libraries (like styling - css & scripts - js) in the .info file, now you have to define them in a separate file - the .libraries.yml file.

In the case of your theme, we will use style.css for styling, and the Bootstrap library for responsive display. So we will place the style.css file in the core/css folder. The bootstrap libraries (bootstrap.css) will lie in the includes/bootstrap/css directory.

   version: VERSION
       includes/bootstrap/css/bootstrap.css: {}
       css/style.css: {}



If you're asking how Drupal renders the html of your theme, the answer is the template files. They are all named with the extension .html.twig.

This is a new update in D8. Since in D8 Twig replaces PHP engine of D7, all of the tpl.php template files are changed to .html.twig. And these files are placed in the templates folder.

Let's browse through what each template file functions. - defines the theme themename.theme - programs the theme
html.html.twig - defines every page on the site
page.html.twig - defines every page on the site
node.html.twig - defines every node on the site
region.html.twig - defines every region on the site
block.html.twig - defines every block on the site
field.html.twig - defines every dynamic element on the site

If you want to change the way your default HTML, and pages look, you can create your own version of the files above.

The most important file that you want to alter now is the page.html.twig. Is is the so-called HTML skeleton of your page as it will render how your page HTML layout will look like.

Drupal will read this file and tell how your homepage displays, and even how all of your pages appear if you don't include other template files.

So the job now is to make your own a page.html.twig file.


Start with an empty page.html.twig file. Here all of the codes for the body section of your theme are stored. This file contains 3 main elements:

  1. Html markup of your theme.
  2. Region definitions.
  3. Variables for other content items (At the moment, we want it to be basic, so the page.html.twig is for creating regions only)

Note: you can also use the page.html.twig of your core in core\modules\system\templates\page.html.twig for reference, and change this file for your purpose.

We'll create basic html regions for the page, including headline, header, main, and footer regions. Notice that if you add these regions, you must define them in your info.yml file first.

<div id="page"> 
 <section id="headline"> 
 <section id="main">

Next, put all of the regions of your page into a Bootstrap container for ease of responsiveness. We'll add these codes between each section (headline, header, main, footer).

<div class="container">

For the content and the sidebar region, we'll use the column class of Bootstrap so that these two regions will be divided as follows:
Main content will constitute 75% of the site width, sidebar will account for 25%. That is for the desktop.
For mobile screens, main content and sidebar will be displayed full width (100%).

Your main section codes will look like this

<section id="main"> 
 <div class="container"> 
  <div class="row"> 
   <div id="content" class="col-md-9 col-sm-9 col-xs-12"> 
    {{ page.content }}    
   {% if page.sidebar %} 
    <aside id="sidebar" class="sidebar col-md-3 col-sm-3 col-xs-12"> 
     {{ page.sidebar}} 
   {% endif %} 

The last step of your page.html.twig file is to add these twig codes to the headline section to render them to the page. (If you don’t know twig syntax, return to our past post, or read twig syntax documentation).

{% if headline.sidebar %}
   {{ headline.sidebar }}
{% endif %}

The above codes create a conditional to check if the headline region has something in it. If there is, the headline region will be printed out. This is a good practice to ensure that empty markup will not be printed to the page.

Now add the similar and relevant codes to the header, content, sidebar, and footer.

The content section is an exception. It does not need a conditional statement because there will always be something in the content region.

After all done, the complete codes of your page.html.twig file will be be like this:

<div id="page"> 
 {% if page.headline %} 
  <section id="headline"> 
   <div class= "container"> 
    {{ page.headline }} 
 {% endif %} 
 <header id="header"> 
  <div class="container"> 
   {{ page.header }} 
 <section id="main"> 
  <div class="container"> 
   <div class="row"> 
    <div id="content" class="col-md-9 col-sm-9 col-xs-12"> 
     {{ page.content }} 
    {% if page.sidebar %} 
     <aside id="sidebar" class="sidebar col-md-3 col-sm-3 col-xs-12"> 
      {{ page.sidebar}} 
    {% endif %} 
 {% if page.footer %} 
  <footer id="footer"> 
   <div class="container"> 
    {{ page.footer }} 
 {% endif %} 


Now that you have given enough definitions for your theme, let’s start enabling the theme, and create content.


Your theme won’t work until you activate it.
Go to /admin/appearance, find your basis theme, and choose set as default.


Each section on Drupal will be called block. To make it appear in the right place, you need to place it in the right regions.

Since we have created regions, navigate to basis/admin/structure/block, and you will see many sections, encompassing headline, header, content, sidebar, footer.
For your basis theme, we would like it to have a website design layout as seen.

To do that, place these blocks on the relevant regions in the basis/admin/structure/block


 Main navigation (your menu) 
 Site Branding (Your logo, and slogan) 
Content (your front-page display) 


 Search Form 

 Powered by Drupal


By default, Drupal will look for the logo.svg in the theme\logo.svg for logo display. So you need to create one to enable it.
You will also have the options to choose what to display - site logo, site name, or site slogan in /admin/structure/block/manage/sitebranding


Your screenshot will show up next to your theme in the admin interface admin/appearance. To create one, place an image file named screenshot.png in your theme directory.


Now take your web design, Front-end skills, and your creativeness to create the appearance of the theme that you like. For our D8 themes, we use Bootstrap for responsiveness, and SASS for ease of styling. But it’s our working method. Just do what you want.

Related Post

Latest Post

Recent Posts Widget

Make sure to never miss a thing...

Get the latest news from the creative industry along with other creative goodies, conveniently delivered to social media.