Drupal Theme Design Tutorial 1 - Designing Comments & Comment FormsDrupal Theme Design Tutorial 1 - Designing Comments & Comment Forms

Categories:

This is the first of a series of Drupal design and theming tutorials. My goal is to inform you of the elements you need to design for and demonstrate how to make Drupal not look like Drupal.

As a designer that works almost exclusively in Drupal, it can often times be frustrating to get certain site elements to get that refined look to them. I don't consider myself to be a programmer, but often times learning some code snippets is the only way to get the page layout to behave the way you want. Thus, a careful balance of theming (HTML & CSS) and development (PHP) is often required to get that really unique look that sets your site apart. That's what this series of posts is all about. How do we take a Drupal installation and make it not look like Drupal? We'll be reviewing Drupal elements on a case by case basis. Today's Topic: Comments and Comment Forms.

First, just a quick note about these posts. There are many tutorials and documentation pages regarding Drupal theming, so these studies are not going to be ground-up discussions of theming basics. Drupal theming is not easy! Without a basic understanding of the Drupal Core system you are going to become hopelessly lost. These studies are meant for people that are familiar with Drupal already.  If you need more detailed descriptions of what theming is all about, please check out these resources:

- Drupal Theming Guide
- Drupal 6 Themes

 

Designing and Theming Drupal Comments and Comment Forms

Let's take a comparison shot of a default Drupal implementation of comments and see what we'll be working towards:

Before and After

As you can see there's a lot of work to be done. Drupal's default styling tends to be "everything in a big long list." We can save a lot of space and clarify the elements a bit by moving some elements inline and getting rid of unnecessary text.

Ok let's begin. Our strategy will be to first tackle any TPL files, followed by adding functions to template.php, and lastly polishing with CSS. Let's look a the specific features we will be adding. CAPTCHA is non-standard. You can use either the CAPTCHA module if you want ultimate control over styling, but reCAPTCHA is a good choice as well. We'll also want to add a special flag for posts created by the site admin. We'll be hiding some fields in the comment form and then restyling everything else.


1. TPL files:

If comment.tpl isn't already in your theme directory, copy it there. We're going to be augmenting some of the markup here to add special tags for admin comments. Comments are given special CSS classes by default in Drupal to mark messages that are "new" (for newly posted comments), "even", and "odd" (for striping or alternating styles every other comment). Using this same principle, we are going to add an "admin-comment" class. We will need to add a check to see if the author of the comment is the site admin:

 

<div class="comment<?php print ($comment->new) ? '  comment-new' : ''; print ' '. $status ?> clear-block<?php if  ($comment->uid >= 1){ print ' admin-comment';} ?>">

 

This is a quick and easy way of doing this for a single-user blog. For more complex scenarios you will need to use another method, perhaps checking by author role. At any rate, let's check our output really quick to make sure the class is added correctly:

 

Checking classes

 

Ok, looks good. The next thing we have is the date output. There are 2 ways of changing it. One is by navigating to your admin page under http://yoursite.com/admin/settings/date-time and altering date formatting from the drop downs. The way I prefer is to insert a quick function in the TPL file:

 

<?php print ($author . '<span style="color:#828282"> @ ' . (format_date($comment->timestamp, 'custom', 'j M Y')) . '</span>') ?>

 

What we have here is a function that prints the comment author with the date formatted using PHP date codes. In this case, "j M Y" is the day of the month, followed by the month name, followed by the year number. You can use this function in any TPL file to create a customized date output for different views or content types. The result in our case is the formatted author and date:

 

Date formatting

 

At this point we can make a decision as to whether we are using CSS3-based corners or image-based corners for our styling. I used image-based ones for this example, so I need to add some containing <div> to the layout (one for the top and one for the bottom slice). Lastly, we need to mark the author comments with a special image so that they are indicated visually in the page. We will do this with a similar technique to what we did for the comment class:

 

<?php if ($comment->uid >= 1): ?><img class="authortag" src="/sites/all/themes/yourtheme/images/comment-author.png" alt="Author" /><?php endif; ?>

 

Put it all together:

 

<div class="comment<?php print ($comment->new) ? '  comment-new' : ''; print ' '. $status ?> clear-block<?php if  ($comment->uid >= 1){ print ' admin-comment';} ?>">
    <div class="submitted">
        <?php print ($author . '<span style="color:#828282"> @ ' . (format_date($comment->timestamp, 'custom', 'j M Y')) . '</span>') ?>
    </div>
    <div class="content">
        <div class="comment-top">
            <div class="comment-bottom">
                <?php if ($comment->uid >= 1): ?><img class="authortag" src="/sites/all/themes/scriptotheme/images/comment-author.png" alt="Author" width="42px" height="42px" /><?php endif; ?>
                <?php print $content ?>
                <?php print $links ?>
            </div>
        </div>
    </div>
</div>
 
 

 

2. Working in template.php:

Instead of the default Drupal comment header which just says "Comments" I want to have a custom graphic separating the article from the comments which can be clicked to jump to the comment form. Let's open up template.php and add a preprocessing function to alter the default output:

// Add a comment header graphic
function yourthemename_preprocess_comment_wrapper(&$vars) {
  if ($vars['content']) {
    $vars['content'] = '<div id="comment-head"><div id="postnew"><a href="#commentform" name="commentlist" title="Post a comment"><img src="/sites/all/themes/scriptotheme/images/comment-postnew.png" width="144" height="21" alt="Post a comment"></a></div></div>'.  $vars['content'];
  }
}

What are doing here is adding some divs and links to the comment section header. Here is how the above code works with respect to the output.

 

Comment header

 

Next we have to clean up some elements we want to remove from comment forms. First, reply links. This is a small blog, no need for nesting comments.

 

// Remove reply link from comments
function  yourthemename_links($links, $attributes = array('class' => 'links')) {
  unset($links['comment_reply']);
  return theme_links($links, $attributes);
}

 

A telltale Drupal sign is the "not verified" text added to anonymous users. Let's get rid of that.

 

// Remove not verified text from comments
function yourthemename_username($object) {
  return str_replace(' ('. t('not verified') .')', '', theme_username($object));
}

 

We're also going to get rid of the homepage input box on the comment form as well as allowing previewing comments (There are few sites that should require previewing of comments anyways).

 

// Disable comment previews
function comment_form_comment_form_alter(&$form, $form_state) {
  unset($form['preview']);
  unset($form['homepage']);
}

 

Lastly, depending on your settings, your users may get some text at the bottom of the comment form that tells them what tags they can use (if any). These are known as Drupal tips:

 

Tips

 

Again, we are simplifying the form so let's get rid of them. There are modules that do this but let's just do it while we have template.php open:

 

// Disable tips display
function  yourthemename_filter_tips($tips, $long = FALSE, $extra = '') {
  return '';
}
function  yourthemename_filter_tips_more_info () {
  return '';
}




3. CSS Time:

Ok now for the tricky part. We have to take Drupal's output and style it the way we want. Luckily, one thing Drupal does very well is wrap its elements with tags, so it is possible to target virtually every element or div that you need to override with your own CSS. Let's start with the comment boxes. Nothing groundbreaking here, just simple CSS. NOTE: I used a CSS sprite for the comment background that looked something like this:

 

Comment sprites

 

Okay, and now the CSS:

 

.comment {
    margin-bottom:20px;
}
.comment .submitted {
    color:#db2453;
    text-align:center;
}
.comment .content {
    background-image:url(../
images/comment-bg.png);
    background-repeat:repeat-y;
}
.comment .comment-top {
    background-image:url(../images/comment-bg.png);
    background-position:-636px 0;
    background-repeat:no-repeat;
}
.comment .comment-bottom {
    background-image:url(../images/comment-bg.png);
    background-repeat:no-repeat;
    background-position:-1272px bottom;
    padding:24px 15px 0 15px;
}

 

Here is the output:

 

Background layering

 

Next we use negative margins to bring the admin flag in line:

 

.comment .authortag {
    float:right;
    margin:-13px -12px 0 0;
}

 

Here is the output:

 

Final comment rendering

 

Now for the comment form. Depending on the width of your content area, you might have to change these numbers. I was working with a 675px area width. The key to the styling is to float input labels left. Then you give them decent width, which will push the input box over and make everything line up nicely.

 

#comments .form-item label {
    padding-top:8px;
    float:left;
    width:190px;
}
.form-item {
    margin:15px 0;
}
input.form-text, input.form-file, select.form-select, textarea {
    font-family:"Lucida Sans Unicode", "Lucida Grande", "Lucida Sans", Arial, Helvetica, sans-serif;
    padding:8px;
    border:1px solid #ffffff;
}
textarea {
    font-size:1em;
    line-height:1.6em;
}

 

Form label floats

 

The rest are small adjustments that are needed to get the input boxes sized correctly in the remaining space as well as getting the comment resize "grippie" (the grey bar that you can drag to resize the text area) to size correctly and line up again.

 

#comments #edit-name-wrapper input.form-text, #comment-form #edit-mail-wrapper input.form-text{
    width:425px;
}
#comments #edit-comment-wrapper .resizable-textarea {
    width:auto;
}
#comments .description {
    display:none;
}
#comments #edit-comment-wrapper .resizable-textarea textarea {
    height:100px;
    width:425px;
}
#comments #edit-comment-wrapper .resizable-textarea .grippie {
    margin:0 0 0 190px;
    width:441px;
}

 

Lastly we have the CAPTCHA styling. This is the trickiest bit because getting it to appear not part of a fieldset (as the output will have it by default) requires some clever restyling.

 

#comments fieldset {
    border:none;
    background:none;
    padding:0;
}
#comments fieldset legend {
    padding:8px 0 0 0;
    float:left;
    width:190px;
    font-size:1em;
    font-weight:bold;
    color:#000000;
}
#comments .captcha #edit-captcha-response-wrapper label {
    padding-top:0;
    width:300px;
}
#comments .captcha .form-item {
    border:none;
}
.captcha img {
    float:left;
    padding-right:5px;
    border-right:1px dotted #a09d81;
}
.captcha #edit-captcha-response-
wrapper.form-item {
    width:200px;
    float:left;
    margin:0 0 0 5px;
}
.captcha #edit-captcha-response-wrapper input.form-text {
    width:196px;
}

 

And the output again:

CAPTCHA styling

 




4. Bonus form styling with CCS3, browser-specific styling, and CSS3Pie:

Now that our form is fully styled, we want to add a little flair to the form boxes. Subtle shadows and outlines make the elements really stand out from the default Drupal way. Unless you want to mess with CSS image backgrounds for forms (which can be a total nightmare), let's go with some CCS3:


input.form-text, input.form-file, select.form-select, textarea {
    -moz-border-radius:5px;
    -webkit-border-radius:5px;
    border-radius:5px;
    -moz-box-shadow:inset 0 0 3px #777777;
    -webkit-box-shadow:inset 0 0 3px #777777;
    box-shadow:inset 0 0 3px #777777;
}
.resizable-textarea textarea {
    border-bottom-right-radius: 0px;
    border-bottom-left-radius: 0px;
    -moz-border-radius-
bottomright: 0px;
    -moz-border-radius-bottomleft: 0px;
    -webkit-border-bottom-right-radius: 0px;
    -webkit-border-bottom-left-radius: 0px;
}

Cool, now its looking good. But what about IE? Fortunately some great people have put together a package you can install to allow IE 6-8 to pick up CSS3 declarations. It's called CSS3PIE and you can check it out here.


There you have it. Keep checking back for more "How to Make Drupal Not Look Like Drupal" styling case studies in the future.

Ashley Forrester's picture

This is one of those logical blogs that i have come across. yeah thanks for these tips. It would surely help new users of Drupal.

drupalme's picture

Bravo!!

DjebbZ's picture

Good initiative !
As a Drupal developer it's nice to see someone dedicating time to teach some tricks to beginners.
Just a correction : don't use format_date() in your tpl. 1) It's unadvised to use functions inside tpl files (security risks amongst others) and 2) format_date may give your visitor a wrong date because of timezones, better use the interface.
Good job, looking forward the next one.

Ben's picture

This article is great, one of the best I've read on theming

Anonymous's picture

Good information. One puzzle, why would you put place a css style inline in the .tpl, as opposed to a stylesheet?

Susanna's picture

Great tutorial. Have saved this for future reference.

Chris's picture

This is really great. Clear and concise! I'd love to see more posts like this.
WELL DONE!

Jim's picture

Thanks for detailed tutorial.
Could I ask the the next tutorial that you do would be on how to theme a Webform?
For me that would be like wining the jackpot :-)

bewhy's picture

This is the first Drupal theming tutorial that I've read that made sense. Focusing on one topic at a time is immensely helpful...people talk about the preprocess function but I had no idea how that fits into theming
.now only if you could teach me how to come up with cool designs...

Marcel's picture

Nice wrap-up, should've read it a week earlier... ;-)

Need a Custom Designed Theme?

If you need a custom designed theme for your business then our designers can work with you to create a unique concept that is consistent with your brand, clearly communicates your value proposition and helps you achieve your goals. >> Click here to contact us and let us know about your needs and we'll analyze and provide you with an estimate for designing and development your custom theme.