
I had a bit of a gap between projects, so one of the things I decided to do was to tackle the redesign and development of my own website: wheelercreek.com. It's been about 6 years, so it was definitely due. The old website has functioned well, and was built in Drupal 7. But it was not responsive - and I just never had much time to address it.
As it happens, Drupal 8 has just reached Release Candidate 2 so I thought, let's give it a shot. This is a great opportunity to explore Drupal 8 and learn how to work with the new system. I've been working in version 7 for several years and I enjoy it.. but as we know - nothing ever stays the same on the web. Drupal 7 does have certain limitations and frustrations.. and I found D8 easier in several ways.
Still, I was hoping I would be able to continue using the Foundation framework from Zurb. I've come to rely on that framework as it's so easy to use.. and I never really got into some of the Drupal responsive theme flavors (like Adoptive theme, or Zen). And as it turns out, it's much easier to work with Foundation 5 in Drupal 8 than it was in Drupal 7 (which actually wasn't all that easy).
I also like to use SCSS and Compass, which there's no problem with in Drupal 8. So, I'm going to write up what I learned here so I can remember what I did, and maybe it will help others as well.
The old version of wheelercreek.com
I won't go through everything, there is already a lot of good information in the Drupal 8 Theme Guide. But I'll hit the highlights of how I used Foundation, and how I structured my own theme. First, here is a copy of my wcreek theme (wcreek.zip).
In the D8 folder structure, my theme is sitting at /themes/custom/wcreek/. It's no longer recommended to put custom themes into /sites/all/themes/ as we used to do in D7. Also in D8, any custom modules or contributed third-party mods would go into /modules/custom or /modules/contrib/ - as needed.
You'll see if you look at my files that I put the Foundation framework here. Since I've got everything set up for running Compass, to grab the latest Foundation files it's a simple matter of running "foundation new wcreek" (see the foundation with Sass instructions here). You don't have to do it that way, you can always just download and drag the files where they need to be.
In the Foundation files (which is now going to be my Drupal theme), I remove the files that would normally sit at the root of a site: humans.txt, index.html, and robots.txt.
Next I added Drupal's theme files:
- wcreek.info.yml,
- wcreek.libraries.yml,
- wcreek.breakpoints.yml,
- logo.svg,
- screenshot.png
- favicon.ico
I also created additional folders: images/ and templates/. So my file structure is:
One note here, because I'm going to be using Git to track my Drupal site, I went ahead and removed the Foundation Git folder and the .gitignore file. Forgetting to do that can cause headaches later when you try to commit your site.
My wcreek.info.yml file looks like this:
You can see I used one global-styling library. The Drupal theme libraries are where you add in the theme's CSS and JS files as explained here.
There are also several regions created here. I find I like to create plenty of regions for each main area of content I'm going to use. As I looked at my design, especially for the homepage, there were several content areas where I thought it would be nice to be able to drop blocks into place and not have to worry too much about positioning them going forward. I'll style these regions - placing foundation row & column classes around them in the templates, and I'll be good to go.
You could also remove certain core system stylesheets here, but I left them in. The reason I left them in is -- I found a great contributed module called "Admin Toolbar", which extends the new D8 responsive toolbar by adding drop-menus (very helpful). When I tried removing the system stylesheets, the admin toolbar went wonky. Since I don't want to take the time to try to figure out which stylesheets it's using, I just left them in.
Here is the wcreek.libraries.yml file:
In my global-styling library, I bring in my fonts stylesheet and the foundation-icons.css. If you don't know about the foundation icon fonts, check them out here. It makes using icons on the site very quick. There is also a reference here to the app.css (the main foundation CSS file) and print css file.. which I need to remember to create.
Drupal 8 doesn't come with jquery installed by default, so I also added that as a dependency. Incidentally, I tried to attach the jquery.min.js file from core, but couldn't get that to work. In the end, specifying it as a dependency was the only way I could get it working.
This is also where we can attach the required Foundation javascript files. Drupal will place all these files into the bottom of the HTML page, just prior to the </body> tag. Placing the css and js files here in the libraries script allows for Drupal to use it's caching and aggregating tools. Drupal 8 seems to be caching everything, even when I followed all the instructions to turn off caching for local development, I still have to frequently clear the cache.
I will say this though, the site feels a lot faster than D7 sites... I'm sure that a lot of that speed is due to the various caching mechanisms, and the compiled twig templates.
You'll notice also that I have a homepage library listed in the wcreek.libraries.yml file above. I'm not loading this in globally through the info.yml file (above), because I only need to use these files on the homepage. So I'm going to bring them into the twig template file page--front.html.twig. I should mention here that my process has been to just copy the core theme template files, I don't usually start with any other theme. So to create my page.html.twig file I would copy the file from /core/modules/system/templates/page.html.twig and save it into my own theme's template directory. In this case, as I want a more customized front page, I'm opting to name it page--front.html.twig. If you need to learn more about how Drupal's template naming suggestions work check this page in the theme guide.
Okay, Twig.
I admit I wasn't super excited about learning twig, but it really didn't take that long to get it figured out. I understand the desire to push to a more MVC model and separate the view from controller code.. and I was able to get things worked out fine on this site. But I'm still worried that in the future I'm going to run into a situation where I just really need to make a custom function call from a theme template file - and I haven't yet figured out a way to do that.
If you are new to Twig read this guide page here.. and also this comparison page is very helpful. You can do very basic things like create variables, and simple conditional statements. Also, the Twig debug feature is invaluable to tell you what template files to use.
Here is a section from my page--front.html.twig file:
You can see here at the top, I'm attaching my homepage library. This allows for the Javascript files I need on this page to be available here. Also, you can see where I'm bringing in various Drupal regions that were listed above in the info.yml file, and how I'm wrapping them into the Foundation rows and columns as I need them. Foundation's grid system is wonderful - and makes responsiveness very easy to achieve.
Working in Drupal 8 with the Twig debug feature turned on (in the /sites/default/services.yml file) you can see very easily where to locate the core and module Twig template files - which you should then copy into your own theme's template folder.
Working with these template files is one powerful way to take control of theming different pages. You can create various template files for the pages if they need a different layout. If you download my theme file (linked above), and look into the templates folder you'll see these files:
- page.html.twig (this is the default template)
- page--front.html.twig (this is for the homepage)
- page--drupal-web-development.
html.twig (this is my portfolio page)
When you have twig debugging turned on, it will give these template naming suggestions to you - so you can copy the default template and name it something new (as suggested) and that page should now run through that template. You might need to clear the Drupal cache to get it to work.
I started my theme templates by grabbing the core default page.html.twig file from core/modules/system/templates. I often work from the default page.html.twig, and html.html.twig. Then I found the default node template (node.html.twig) from core/modules/node/templates. And you can probably guess where the default block template is (core/modules/block/templates), if you need that one.
Again, you're not editing these files - but rather, copy them into your theme/templates directory. When your theme is activated, Drupal will use them if it finds them where they should be.
In Chrome, I use Inspect Element to view the HTML output, and I can see Twig debug comments like the following:
This tells me that if I want to modify the HTML markup in some way for this block or region, where to find the template and also what name suggestions to use when I copy it. The name suggestions go from general up to specific - so if you copy the block.html.twig file and modify that, it will cause all the markup for all blocks to be modified. But if I copied that same file and gave it the name "block-customthemingandsmartdrupalbuilds.html.twig" (I guess it grabbed that name from the long block title) - it would be specific to that one block.
So this works the same as Drupal 7, except its now much easier to figure out what template file use, and what to name it!
One last template file I'll show - involves the use of Drupal's main menu and the Foundation Top Bar tool. I usually go with Top Bar as a responsive menu system for the sites that I build. In Drupal 7 I had to create a crazy function with nested loops to build the menu system to integrate the top bar HTML markup. Not any more.. This was actually pretty easy with Twig and the menu--main.html.twig file to set it up properly:
Most of this logic was already in the template file. I just needed to figure out where to add certain markup and class names. The Twig function attributes.addClass() is my new best friend. There's no need to add classes inside preprocess functions anymore (although you can probably do that). But it's so easy here in a template this is usually what I jumped to once I figure it out.
Another thing I found helpful is to modify the default field.html.twig file to add the field names, labels and values as class names. Otherwise it makes it very difficult to target specific fields with CSS:
In fact, if you look inside my wcreek.theme file, you'll see that I've added several preprocess functions, but didn't use them. The only one that has any content is wcreek_preprocess_html(). I found that Drupal 8 doesn't add the helpful classes to the <body> tag anymore (um, why?) but I found that it's not too difficult to at least add the node type as a class.
I have a feeling I'll be adding this bit to every Drupal 8 project I work on:
function wcreek_preprocess_html(&$vars) { if (!empty($vars['node_type'])) { $vars['attributes']['class'][] = 'node-'.$vars['node_type']; } }
There is one other bit of annoyance that really threw me for a loop when I first got started theming in Twig. I was editing a twig template file, and then I went and spent some time changing some CSS.. when I looked at the site it just completely crashed with no helpful PHP error code. All I got was the enigmatic "A problem has been detected, please try again later" message, and nothing else to go on.
I hadn't gotten very far.. but had no idea what to do to troubleshoot. I didn't remember that I had made an edit to a template file, I was messing around with CSS and suddenly everything went Kaput. I ended up doing a complete re-install, and as soon as I activated my theme again, same message. Inspecting my Twig template files, I found an unclosed string. That was it.
So - the lesson here is, guess what: Twig files get compiled. That means they can't generate nice helpful code error messages (I guess). They aren't processed in a way that errors can be dumped to the screen. If you encounter that particular error message, try looking into your Twig files for any unclosed strings, or missing curly-braces, etc.. Any code error in a Twig file will generate this message.
Well, that's it for now. Hopefully this helps someone! I'm still getting to know Drupal 8, as it's brand new - so I'm sure there's a few things I did wrong here & will do better next time. But overall I like the changes the Drupal community has made.