Thursday, August 5, 2010

Custom Header Image for Individual Pages on Blogger

One of the most common niceties of many sites around the web is a unique header or background image for different pages on the website. The unique image sets the page apart from others on the site. When done well, the images tie in nicely with each other and reinforce the overall theme of the site.

Unfortunately, this is difficult to accomplish on Blogger, and requires a good working knowledge of the way Blogger templates function to figure out for yourself. Having figured out how to do this recently in some on-the-side help for the bike shop my sister works for, Ascent Cycling, I decided I would do as many others have done before me and share the method I used. I will also explain some of the basics of Blogger's somewhat unique XML tags so that you can begin to see how to make these sorts of changes yourself. I'm going to assume zero familiarity with Blogger's Template HTML and very little familiarity with HTML in general; if you're experienced in these areas you should just be able to skip down through the code and see what I've done.

The first thing you need to do is go to the Design tab on your Blogger Dashboard and selected Edit HTML.Once you've done that, you will see a box of HTML, at the top right of which is a little box labeled "Expand Widget Templates." Check the box. There is a link near the top of this page, "Download Full Template;" you should click on it and save the file someplace where you can find it again. This way you'll have a backup in case anything goes wrong along the way.

Now, find the following snippet of code. The easiest way is usually by using your browser's search function (Ctrl-F on Windows, Cmd-F on Mac):

<b:widget id='Header1'...>

Once you've found this, you'll need to look and see how your header image is referenced. Usually you will have a series of tags something like this:

<b:if cond='data:useImage'>
  <b:if cond='data:imagePlacement == "BEHIND"'>
    <!--
    Show image as background to text. You can't really calculate the width
    reliably in JS because margins are not taken into account by any of
    clientWidth, offsetWidth or scrollWidth, so we don't force a minimum
    width if the user is using shrink to fit.
    This results in a margin-width's worth of pixels being cropped. If the
    user is not using shrink to fit then we expand the header.
    -->
    <div expr:style='"background-image: url("" + data:sourceUrl + ""); " + "background-position: " + data:backgroundPositionStyleStr + "; " + data:widthStyleStr + "min-height: " + data:height + "px;" + "_height: " + data:height + "px;" + "background-repeat: no-repeat; "' id='header-inner'>
      <div class='titlewrapper' style='background: transparent'>
        <h1 class='title' style='background: transparent; border-width: 0px'>
          <b:include name='title'/>
        </h1>
      </div>
      <b:include name='description'/>
    </div>
<b:else/>
  <!--Show the image only-->
    <div id='header-inner'>
      <a expr:href='data:blog.homepageUrl' style='display: block'>
        <img expr:alt='data:title' expr:height='data:height' expr:id='data:widget.instanceId + "_headerimg"' expr:src='data:sourceUrl' expr:width='data:width' style='display: block'/>
      </a>
    <!--Show the description-->
    <b:if cond='data:imagePlacement == "BEFORE_DESCRIPTION"'>
      <b:include name='description'/>
    </b:if>
  </div>
</b:if>

Some of the particulars may be different, but the overall flow should be similar. Now, we're really only concerned about one tag, the one highlighted in blue. This tag is a combination of a basic HTML tag, <img>, with some of Blogger's template XML. The expr: tag tells Blogger that what follows is an expression—one Blogger knows how to interpret. In this case, it tells Blogger that the alternate text for the image (for screen readers, people who disable images, etc.), the title (what you'll see if you hover over the image), the height, the width and the location of the image are all stored somewhere Blogger knows to grab them. Most important for our purposes are the height, width, and src parts of this.

Before we do anything else, you need to upload the image you're going to use for your secondary header somewhere. You can use a service like Picasa or Flickr, or you could even upload it to a Blogger page that you simply don't show to your readers. The important part is that you can get the address to the image itself easily (with Picasa, Flickr, or other sites, you'll need to find the permanent link to the image, rather than the page the image is normally displayed on). We'll be using it in just a minute. You also need to know the height and width of your original image, or at least the height and width you want to display. (If those are different, make sure you choose numbers that allow the image to scale properly, rather than ending up squished one direction or another.)

In order to make this work, we're going to need to add some Blogger conditional formatting. Blogger uses special XML codes, <b:if> to accomplish things under certain conditions and not others, usually by referencing other information about the page. The first thing we're going to do is add another image on any static page (a feature Blogger finally supports). I'll show you the code, then explain each part. Replace the line I highlighted in blue earlier with the following:

<b:if cond='data:blog.pageType != "static_page"'>
  <img expr:alt='data:title' expr:height='data:height' expr:id='data:widget.instanceId + "_headerimg"' expr:src='data:sourceUrl' expr:width='data:width' style='display: block'/>
<b:else/>
  <img expr:alt='data:title' height='your image's height' expr:id='data:widget.instanceId + "_static_page_headerimg"' src='url of your image' width='your image's width' style='display: block'/>
</b:if>

Changes are in yellow, things that are the same are in blue, and things that have been copied are in gray. Note that the second line (still highlighted in blue) is identical to the original line. What we've done with the first line is said that if the blog page someone is looking at is not a static page, display the header image just like normal. In the third line, we have a <b:else>, which tells Blogger that if the first condition isn't true—in other words, if the page is a static page—we want to do something different. Now, on the fourth line, note the replacements we've made. The original is in blue, while the new changes are in yellow. Italics indicate that you should substitute the correct information where the italic text is. For example, your height field might be height='600px' and your src field might be src='http://www.mypage.com/myimage.png'.

The height and width fields give your image the correct custom dimensions. If your special header image is the same size as the header image for the main page, you can leave these as they are in the original. You also don't actually have to change the id field, but I think it helps make clear that this is a unique element that should have its own behavior and styling. If you want to go back later and add some sort of custom effect to that image alone with CSS, you can, because it has its own id.

The most important change is in the src field: instead of Blogger's address for your default header image, you now have your own. All of your static pages will now display the new header image.

Let's go one step further: make it so that individual pages show different headers as well, with a default image for static pages that we don't need an individual header for but we still want to be different from the normal blog page. We'll only have to add a couple lines of code to pull this off.

<b:if cond='data:blog.pageType != "static_page"'>
  <img expr:alt='data:title' expr:height='data:height' expr:id='data:widget.instanceId + "_headerimg"' expr:src='data:sourceUrl' expr:width='data:width' style='display: block'/>
<b:else/>
  <b:if cond='data:blog.url == "custom page url"'>
    <img expr:alt='data:title' height='1st custom image height' expr:id='data:widget.instanceId + "_1st_static_page_headerimg"' src='1st custom image url' width='1st custom image width' style='display: block'/>
  </b:if>
  <b:if cond='data:blog.url == "2nd custom page url"'>
    <img expr:alt='data:title' height='2nd custom image height' expr:id='data:widget.instanceId + "_2nd_static_page_headerimg"' src='2nd custom image url' width='2nd custom image width' style='display: block'/>
  </b:if>
    ...
  <b:if cond='data:blog.url == "final custom page url"'>
    <img expr:alt='data:title' height='final custom image height' expr:id='data:widget.instanceId + "_final_static_page_headerimg"' src='final custom image url' width='final custom image width' style='display: block'/>
  <b:else/>
    <img expr:alt='data:title' height='default image height' expr:id='data:widget.instanceId + "_default_static_page_headerimg"' src='default custom image url' width='default custom image width' style='display: block'/>
  </b:if>
</b:if>

Note that I've again supplied a unique id for each image, again allowing you to style it. We've also added a <b:else> to the final check. It has to be after the final conditional, because otherwise it'll get overridden by others. But as it is you should be able to add new static pages and automatically have a default image that is different from normal blog pages show up, while retaining unique header images for all your other custom pages. If you later decide you want to change that image, you'll just need to add another <b:if> like the ones above. (I haven't had a chance to test this in any detail, but it should still work. Let me know if it doesn't.)

Once you've added the new lines, click "Save Template," and check out your blog to see the results. If something doesn't work, you can go back and continue editing, and if worst comes to worst and things just keep getting worse, you can always go back to the version of the template you saved off at the beginning.

17 comments:

  1. Hi Chris,

    I just wanted to let you know how helpful this tutorial has been for me in setting up my new blog the way I envisioned it! Your instructions are so clear and thorough. I look forward to reading more of your webdesign articles, if you decide to write any in the future.

    Thanks!

    ReplyDelete
  2. surefire—very glad to have been of help! I spent a not inconsiderable amount of time trying to see if anyone had done this before, and when I realized they hadn't, it just made sense to put up the method once I'd figured it out myself.

    Thanks for the comment; it inspired me to get back to posting some of these things I've figured out—the ones that no one else has put up are in some cases very useful (some of them are things I've seen people wanting for years; they're doable but you have to know where to look). On that note, I put up another one today, and I'll probably try to continue to do at least one a month in the future.

    I took a look at your site, and I like what you've done with it. Including the custom header images!

    ReplyDelete
  3. this is really well written and explained - thanks for sharing your knowledge!
    my only query is that on a second static page I'm struggling to work out how to put the code in for ANOTHER seperate image.. so far I've got my home page image and a second image in the header for my about section which is also in the events section but I'd like the events section to have a different image
    what am i missing?
    thanks!

    ReplyDelete
  4. hi ..finally got something that i needed to change but when i tried this - only the image that featured was 'default custom image'where did i go wrong ? also the image that featured was very very small.would really appreciate if you could help
    thanks in advance

    ReplyDelete
    Replies
    1. Hi, bose,

      Can you give me more details on what exactly you did, what you're trying to do, and what the results are? I may be able to help you figure it out, but definitely need more details to be able to help. Also, I'm super busy this weekend, so it'll probably be Monday or Tuesday before I can get back to you.

      Delete
  5. Chris, I'm having similar problem as the others that the very last image placed just after the final tag is appearing on all static pages as the default. How does this code need to be tweaked to switch out the header image on each static page? Thanks much!

    ReplyDelete
    Replies
    1. Up The Creek Winery (great name!),

      Basically, that <b:else/> tag is telling Blogger to make that image the default for all other pages. So you either need to specify an image you're okay putting on all static pages, or no header image at all.

      Note that every single page for which you want to specify a header image has to be referenced specifically. Unfortunately, I don't believe Blogger's XML namespace includes any sort of conditional (and that's not really a surprise, as having one would include a lot of extra overhead on their back end), so you're stuck doing it for each page manually.

      Delete
  6. um, I'm having a bit of trouble :/ I'm kinda new to HTML codes, and I can't find the <img expr anywhere, and it doesn't look anything like above when I find b:widget id='Header1'!! Could you help me out? My blog is www.littlspaceheroesfansite.blogspot.com and I'm trying to get a different header on the 'graphics' page

    ReplyDelete
  7. lol, cancel that last comment, I figured it out :D But um, is the static page meant to be the Homepage?

    ReplyDelete
  8. Hi! Does anyone know is this still working in 2013 Blogger? I tried out, but it doesn't seem to work O__o my url at http://kajasteartweb.blogspot.fi

    ReplyDelete
    Replies
    1. Alas, I have no idea; I switched to Wordpress over a year and a half ago and have done zero Blogger development since then. Sorry!

      Delete
  9. if i dont want using flickr@picasa, can i upload image at my pc?

    ReplyDelete
  10. I realise this was posted almost four years ago, but I was wondering if you had any idea how to do this for Pages that are label-based, and therefore not static?

    ReplyDelete
    Replies
    1. Alas, I have no idea; I haven't looked at Blogger's back end in about 3 years. Sorry!

      Delete
    2. No worries. I found a tolerable workaround. Thanks for replying.

      Delete
  11. Hello Chris,


    I realize you have not worked with Blogger in a while, but you explained the conditionals so simply and clearly in your post that I believe you could help me with their implementation in my Blogspot: http://shredair.blogspot.com/
    I am trying to get a different photo (map) on each page (Northwest, Colombia, Andes). Would you be willing to look at the code and help me?
    Thank you,
    Marcela

    ReplyDelete
    Replies
    1. Hi, Marcela,

      Sorry, I just don't have time to do that kind of thing at this point—especially for free! Best of luck getting it figured out, though.

      Delete

Got some thoughts? Fire away. Please be polite, thoughtful, and kind! Please provide your name and, if applicable, website. Anonymous comments, along with all forms of spam, trolling, and personal attacks, will be deleted.