Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Tuesday, November 9, 2010

Hiding Post Page Content on Home Page [Blogger Hacks]

One of the features I implemented for Pillar on the Rock a few months ago is a means of showing different content on the main page than on the post pages. Oftentimes, we have introductory or editorial content that's simply extraneous in the context of our magazine-like landing page. People are not interested in reading an introduction to each post; they want to see whether the article itself grabs their attention or not. (Similarly, what's the point in having a great first sentence if it's buried below a bunch of other content?) At the time, we were shifting from showing entire articles on the front page to showing snippets. I took the opportunity to implement a small, easy fix that allows us to hide any content in a post from the front page while still displaying it normally on the post page.

Before you implement any of the following, make sure you backup a copy of your full Blogger template (Design→Edit HTML→Expand Widget Templates, then after the reload, choose Download Full Template). Now, you're going to need a couple pieces of CSS, and then some HTML implementation in Blogger's post-generating XML code. We'll start with the CSS. You can update this one of two ways. If you're using a new Blogger template, the CSS can be customized in Design→Template Designer→Advanced→Add CSS. If you're using a classic template, the CSS is available in the <head> section. Either way, you'll want to add some code like the following (the particular name of the class is not important; that you can remember it and it's descriptive of what you're wanting to do with it is important).

We're going to add a CSS "class" that we can apply to our content. (If you're unfamiliar with CSS, W3C Schools' tutorial is a great place to start. It'll explain concepts like ids, classes, and how CSS works in general.) Here's the class:

.hidden-content {
    // any styling you want applied to this content on your post pages

You could actually ignore that entirely, but if you want to do anything special with the content on your post pages, you should add the styling to that class here.

Next, on the Edit HTML tab, run a search for "Blog1" (the name of the blog widget element). Scroll down (or just run another search) until you find the following code:

<div class='post-body entry-content'>
    <div style='clear: both;'/> <!-- clear for photos floats -->
Here, we are going to insert some code to tell Blogger what to do in the particular case that we are not on the post page, which Blogger identifies by setting the pageType to item—that's the section highlighted in yellow below.

<div class='post-body entry-content'>
<b:if cond='data:blog.pageType != "item"'> <style type='text/css'> .hidden-content { display: none; } </style> </b:if>
<div style='clear: both;'/> <!-- clear for photos floats --> </div>

Aside: Those of you familiar with Blogger's templates may wonder why I didn't use pageType == index rather than pageType != item. The answer is that if you do that, archive pages (those accessed by searching by label or date) will all still display the content. Obviously you'll need to decide whether that makes sense in your case. For me, I only wanted the content to appear on the post pages.

Now, save your template, and you're done with the template changes. Now, any time you want to hide text on the front page but show in on the post-page, you simply need to wrap it in an element that has the class article-hiddne-content. For example, if you want to hide a whole section of text, you might do the following in your post (of course you'll have to be using the Edit HTML tab of the post creator):

<div class='hidden-content'>
Donec fringilla lobortis metus eu sollicitudin.
Nam eros quam, venenatis ut ultrices sit amet,
tincidunt ac nisl. Phasellus varius ante ut nibh
mattis dapibus rutrum purus pellentesque. Morbi
congue risus et metus pellentesque vel pulvinar
leo sagittis. Duis sapien diam, volutpat sed
pharetra sit amet, consectetur vel sapien.

Donec dictum sapien at ipsum suscipit id
condimentum turpis tristique. Nam bibendum
molestie libero, sed imperdiet quam pharetra non.
Maecenas bibendum nunc ut libero congue volutpat.
Vivamus eu ante lorem, eu sodales risus. Mauris
ultricies gravida interdum. Praesent eu tortor
nibh, vitae facilisis orci. Duis et justo eu
libero tempus viverra. Nulla.
Alternately, you could hide anything else just as easily:
  • Images: <img src='image_url' class='hidden-content'/>
  • Links: <a href='target_url' class='hidden-content'/>[link content]</a>
  • Paragraphs: <p class='hidden-content'>[paragraph text]</p>
  • Spans: <span class='hidden-content'>[span text]</span>

It's that simple! Of course, you can apply the same technique to accomplish substantially more sophisticated behavior as well. In my case, I not only wanted to hide some content on the front page, I wanted to change certain styles when on the front page (e.g. I didn't want my drop-cap first-paragraph effect to appear anywhere except the post-page, so I reset the styling for it to match ordinary text). All that requires is adding other styling elements inside the <style type='text/css'>...</style> block we created—those styles will only be applied when you're on a post-page, because Blogger won't even create that code for other kinds of pages.

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'/>
      <b:include name='description'/>
  <!--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'/>
    <!--Show the description-->
    <b:if cond='data:imagePlacement == "BEFORE_DESCRIPTION"'>
      <b:include name='description'/>

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'/>
  <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'/>

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=''.

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: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 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 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'/>
    <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'/>

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.

Monday, August 2, 2010

Web design

I'm beginning to think I missed my calling. Perhaps I should have been a professional web designer. I get a huge kick out of it.

I finally understand why: it mixes technical problem solving (really a certain kind of programming), which I enjoy, with the demands of artistry. On the one hand, the successful web designer must be fluent in the sometimes complex technical languages that make web design happen: HTML, CSS, XML, Javascript, and so on. I'm fairly proficient in the first two, and just dangling my toes in the water of the latter two. (Frankly, I find Javascript pretty grimy.)

At the same time, a good web designer has to have an eye for layout, understand relationships between elements, have some degree of skill in manipulating images, and be able to put typography to good use. As my wife (and, for that matter, friends from high school) can attest, I love fonts. I sometimes pick them off of signs driving down the road. I am certainly weaker in this area than in the "coding" aspect of web design, but I enjoy it as much or more. Recently, I have found myself studying web sites, admiring the good ones and critiquing the less good ones.

Even more amusingly, I find myself looking at designs and pondering how I could improve them, what I would do to make them compelling and useable.

Over the last three days, I have done a good deal more tweaking to Pillar's back end, yielding a fairly significant change in the front end appearance (go take a look). Along the way, I've puzzled out how to accomplish a number of tasks with Blogger's backend that, in my search across the web in the past have generally been considered difficult or impossible. I have also helped my sister with the site for the bike she works at, Ascent Cycling—I made different header images appear in different pages.

(Never let anyone tell you that Wordpress is more powerful or more customizable than Blogger. It's just easier to customize under certain conditions. I have used both quite a bit, and they both have their pluses and minuses.)

Because I spent a fair amount of mental energy on these puzzles, and because the answers to them, near as I can tell, do not appear anywhere else on the internet, I will be posting a few of them in the next week so that I can help others (just as plenty of other bloggers have helped me along the way). These will be more like reference pages than my normal content, so apologies to my normal readers, but I know the pages will be helpful to others in the future. (Those of you who enjoy messing with blogger may find it interesting!)

[If you're wondering about that essay I mentioned last Saturday, it's about a third done. The content is substantial and it's requiring significantly more time than I expected. That combined with the aforementioned web design efforts has led to a short delay in its publication. Worry not: it is still coming.]