KohaCon 2009: Customizing Your OPAC

This post was my way to “talk out” the issues I wanted to cover for my presentation at KohaCon 2009. Some of it consists of condensed versions of other posts already on the site, so please take a look around at the other stuff I’ve posted. — Owen

When we at the Nelsonville Public Library first began planning our transition to Koha, we were very excited about having the opportunity to have complete control over the look and feel of our ILS. We had a goal of no less than complete customization, and we ended up creating a whole new set of template for both the OPAC and the staff client.

The structure of Koha pages comes from the templates. Templates contain all the HTML markup which gets sent to the browser. When Koha executes a Perl script for, say, the detail page of a particular book, the script grabs all the data it needs from the database and outputs the data according to the way the template is set up.

Customizing the templates isn’t difficult. They’re pretty much just HTML files with some template processing markup mixed in. But taking the template-customization path presents some serious difficulties down the road when it comes time to upgrade. Any changes that have been made to the standard set of templates has to also be made to your custom set. You have the choice of either constantly tracking updates as they are made to the official set of templates, or doing a massive re-write every time it’s time to do an upgrade. It can be done, but you need to have a lot of time to invest in the process.

The current set of templates has been designed with a lot of options built-in for customizing the appearance of the OPAC without needing to modify templates. There’s no way to have complete control over the design, but there are a lot of ways to tweak things to give it your own unique style.

Avenues of Customization

There are two main ways in which you can change the appearance of your OPAC: via a custom stylesheet, and through changes to Koha’s system preferences. Koha has several system preferences which each control the content of specific regions on the page. Here’s a diagram which shows the areas of the OPAC which are affected by these preferences.


The regions are opacheader, opacsmallimage, OpacNav, OpacMainUserBlock, and opaccredits. These areas are blank slates for whatever kind of content you want to add: HTML, images, even Flash. You simply paste the markup into the relevant system pref.

The other powerful tool we have for changing the OPAC’s appearance is through CSS, Cascading Style Sheets. If you’re interested in taking full control of your OPAC, a good understanding of CSS is indispensable. Every aspect of the OPAC’s default appearance is controlled through CSS. When you add a custom stylesheet (through the opaccolorstylesheet system preference) you can add to or override any of the styles defined in the default stylesheets.

Starting with some basic changes: opacheader

To get started, let’s look at some of the simple ways we can add customization to the OPAC. Starting at the top of the page we’ve got the opacheader region. This area is good for library logos and sitewide menus. For the Athens County Public Libraries’ OPAC I created a custom graphic with our library logo to put in the opacheader region. Below that I added our site-wide navigation menus which our patrons will recognize from our library’s web site.

Adding a logo is probably the simplest thing you can do to customize your OPAC. Go into the Koha staff client and navigate to OPAC system preferences. Click the opacheader system preference to edit it, and paste in the HTML to display your logo. If you manage your own Koha installation this might be somewhere on the same server, or you can have it point to an image somewhere else. Here’s what we would add to display the ACPL catalog logo:

<a href="/cgi-bin/koha/opac-main.pl"><img alt="Athens County Public Libraries" src="http://acpl.kohalibrary.com/opac-tmpl/prog/images/myacpl-logo-text.gif" /></a>

That’s all there is to it. The page renders as if the HTML you entered was part of the original template. Your logo can be simple and relatively small, or it can be relatively large and striking. You can even do without while still leveraging the opacheader region to give your site distinction.

Changing the default Koha logo

In those examples we saw a couple of different options for dealing with the default Koha logo which usually sits at the head of that blue search bar. This logo is defined by the opacsmallimage system preference. Some libraries keep the default Koha logo, some libraries replace it with their own, and some libraries hide it altogether.

The opacsmallimage system pref is a little tricky to deal with because you really have to tweak some CSS at the same time. The default CSS defines a region just large enough to display the Koha logo, and if your logo doesn’t match the Koha logo’s dimensions (120 pixels wide by 38 pixels high), it won’t display correctly.

The ACPL OPAC hides the default Koha logo altogether, because shrinking our logo down small enough to fit in that space would make it too small to be legible. We hide it by making two simple changes in our custom stylesheet:

h1#libraryname { display:none; }
#fluid { margin-left : 0; }

The first line hides the logo, which uses an image-replacement technique to overlay an image on top of a standard HTML header tag. The second line changes the margin on the #fluid container, eliminating the space that was given to the logo.

If you want to add your own logo in this space, you’ll need to do similar changes to the CSS with care match your changes to the size of your logo. Please see my post on
Customizing Koha 3’s OPAC logo for a step-by step walk-through of that process.


Originally the main page of the Koha OPAC was a search form. First it was just a simple keyword search box. Then a recent acquisitions search was added. It began to look too cluttered, and not user-friendly. What should the focus of the OPAC home page be? What searches should be available to the user? What features would “make” the home page?

Finally–out of indecision as much as anything else–it was decided to leave the OPAC home page essentially blank. There would be a login form and of course OpacNav would display if it was configured. Otherwise the OPAC main page would be a blank canvas on which libraries would paint their own page. That canvas is the OpacMainUserBlock system preference.

Paste any HTML content into OpacMainUserBlock and it will appear on your OPAC’s home page. Some libraries use this area for introductory text or instructions to their patrons. Others use it as an area for promotion of services or content in their catalog.

One disadvantage to the practice of pulling HTML content from system preferences is that the content is static. You can’t embed any server-side processing like PHP or Perl in your content.  However, that doesn’t mean you can’t use the power of static HTML to pull in dynamic content from elsewhere.

The ACPL OPAC uses an iframe to pull in content that is pulled dynamically from a database running on another server. The whole process is described in detail in my post ‘ACPL’s “New and Upcoming” OPAC List.‘ In brief, I embed an iframe in the OpacMainUserBlock pref. The iframe pulls content from a page on our library’s web site, where I can use PHP to pull content from a database. The page on the library’s web site grabs new book information from a list we store in our database, and that content gets passed back through the iframe to display on the OPAC.

The other method for getting dynamic content onto the OPAC home page is to use AJAX. With AJAX you can use JavaScript to pull data from an external page in the same way an iframe does, but you can have much tighter integration of the OPAC page and the content your getting from the outside. The disadvantage of this method is that if your user doesn’ t have JavaScript enabled (or is using a device which lacks JavaScript support), he won’t see the content. In the Bern Dibner library example, turning off JavaScript means 3 out of 4 panes are empty: only the “About PolyCat” pane shows any content.

This is not to say it isn’t a viable solution. Each library should evaluate the needs of their particular users and decide based on their own research what technologies will offer the best experience to the greatest number of their users.

Fine control with your custom stylesheet

Digging into the OPAC’s stylesheets is the best way to get a good handle on changing the way things look. There are a couple of ways you can add your own custom CSS. The first option is to add a custom stylesheet to the filesystem of your Koha server. This allows you to specify a stylesheet using the opaccolorstylesheet system preference. The preference looks for stylesheets in the template directory for your OPAC language, for instance: /koha-tmpl/opac-tmpl/prog/en/css. If you upload a custom file, opac-mystyles.css to this directory, you can specify it by entering opac-mystyles.css in your opaccolorstylesheet system preference. This adds your custom stylesheet as a linked stylesheet alongside the OPAC’s default CSS files. This method is preferable because linked stylesheets are cached by the user’s browser, meaning upon repeat visits to your site the user’s browser will not have to re-download the stylesheet, instead using the copy in the browser’s cache.

The other option for customizing CSS is to use the OPACUserCSS

As you’ve seen with the OpacHeader and opacsmallimage examples, it’s simple to make changes via system preferences, but without some style additions or tweaks you’ll find things don’t display the way you expect. opac-table-exampleWhen you add HTML markup via a system pref you might find that the OPAC’s default stylesheet is adding style you don’t want. For instance, if you try to add content to OpacMainUserBlock which uses a table for layout purposes you’ll find that it displays with a thin gray border. That’s because it’s defined as a default for all tables in the default stylesheet.

When you find something that doesn’t look like you think it should, use FireBug to inspect the element in question.

  1. Click the FireBug icon in the lower-right of Firefox’s status bar.
  2. Click the Inspect link in the upper left-hand corner of the FireBug pane.

opac-table-inspectionWhen you use FireBug’s Inspect feature, you can hover your mouse over any part of the page and Firefox will show you details about where that element is in the HTML source and what styles are being applied to it. Let’s inspect the table in example above to see where the table is picking up the border. The FireBug pane shows us that line 241 of opac.css defines a left- and top-border of 1px solid #DDDDDD. Line 249 of opac.css defines the same for the right- and bottom-borders. Now we know that if we want to override that border style our stylesheet needs to override those specific declarations.

We have to be careful, because if we’re only concerned with changing the style of our table on the OPAC home page, we don’t want to change the style of every table in the Koha OPAC. We should probably leave the border intact for pages like search results and lists. How do we target our CSS change to the page we’re concerned with?

opac-inspect-opacmainuserblockFurther digging using FireBug should give is ideas for “hooks” on which to hang our CSS. If we’re trying to eliminate the border on our OPAC home page table, we should inspect the markup that surrounds it to find out if we can isolate that table in our CSS. Inspecting the HTML structure around that table, we can see <div id=”opacmainuserblock>, a container div that is unique to that area of the page (we know it’s unique on this page because it has an id attribute).

Now we can target our custom CSS to tables in that region:

#opacmainuserblock table, #opacmainuserblock td {
border: 0;

A CSS declaration for “table { }” affects all tables. A CSS declaration for “#opacmainuserblock table { }” only affects tables which are “inside” an element which has the ID attribute “opacmainuserblock.”

Hiding content with CSS

CSS can also be leveraged in a similar way to hide content. I’ve found that some libraries want to hide the login form on the OPAC home page because their users assume that they are required to log in.  A simple addition to the OPAC’s custom CSS solves this:

#login { display: none; }

Changing content with JavaScript

So far we’ve talked about adding content to specific areas of the OPAC and changing the appearance of the OPAC. We’ve already talked about why those methods are our top choice for customizing the OPAC: the template system works in such a way that modifying templates directly carries a long-term burden that most libraries would not be willing to bear.

Where does that leave us if we want to change text that is “hard-coded” into a Koha template? Our last-ditch tool is JavaScript: specifically, JavaScript via a JavaScript library called jQuery. The jQuery library is included by default in the OPAC. It’s the tool that enables many of the JavaScript-based functions and effects in the OPAC. jQuery’s power, flexibility, and simplicity makes it ideal for those who want to flex their JavaScript muscles to alter the appearance of the OPAC.

Of course, all the caveats about JavaScript we discussed earlier apply here as well:

  • Some users might have JavaScript disabled (at the browser level, or through a Firefox addon like NoScript.
  • Some users might be using a device which isn’t JavaScript-enabled. Cell phone? Screen reader? Lynx?

With this in mind we can think about using jQuery to manipulate the output of the OPAC, understanding that there may be a small percentage of users who will not see the effects of our efforts.

Labeling the Login Form

Let’s use the login form on the OPAC home page as an example. The labels read “Login” and “Password.” But say my library requires that patrons use their library card number as their login, and because of the ILS we used 10 years ago we’re still calling it a “PIN” instead of a password. That text is written into the template. How can we change it?

jQuery provides us with a very powerful toolset when it comes to manipulating the structure of our HTML.  We’re going to add our custom JavaScript via another OPAC system preference, opacuserjs. Any JavaScript code we paste into the opacuserjs preference will get wrapped in a <script> tag and added to each page of the OPAC. It’s not as efficient as including it in a linked external file, but it’s the most flexible option we have.

Every time you use jQuery for a job like this, you’ll start with this basic construction:

// your script goes here

What this does is set the stage for jQuery to execute your custom JavaScript when the HTML of the OPAC page (“document”) has loaded (is “ready”). It doesn’t need to wait until all the images are loaded, just the HTML structure. After all, we can’t use jQuery to alter HTML on the page if that HTML hasn’t loaded yet.

jQuery lets us use CSS-like syntax to target elements for change. In CSS we can used an advanced selector to target tags with specific attributes. Here’s how we define the text alignment for any <th> with the attribute “scope=’row'”:

th[scope=row] { text-align: right; }

We’re going to use a similar syntax to target our login form’s “Login” label:

// your script goes here
$("label[for='userid']").html("Card Number:");

This code follows a basic formula for simple jQuery statements: $(” element “).function(). “Element” is the part of the HTML we’re targeting: in this case, a <label> tag with a “for” attribute value “userid.” How do we know that? FireBug told us:


$(“label[for=’userid’]) specifically targets any <label for=”userid”>. If there were more than one on the page, jQuery would perform the same function on each of them.

The second part of our jQuery line is the function: .html(“Card Number:”). html() is the function we use to make the change. Coupled with some text (“Card Number:”), the html() function tells jQuery we want to replace the contents of the <label> tag we targeted. Anything between <label> and </label> will get replaced by the text (“Card Number:”) we specify. Now lets add the change to the passsword field label:

// your script goes here
$("label[for='userid']").html("Card Number:");

Now when we reload the OPAC home page we’ll see the changed labels.


The same method can be used to change even larger segments of text. Let’s take a look not at the login form on the home page but on the form you see if you click the “log in to your account” link at the top of the page. This HTML is written into the template:

<h5>Don't have a password yet?</h5>
<p> If you don't have a password yet, stop by the circulation desk the next time you're in the library. We'll happily set one up for you.</p>
<h5>Don't have a library card?</h5>
<p> If you don't have a library card, stop by your local library to sign up.  </p>

This text might work for some portion of public libraries, but it might be completely inappropriate for others, particularly other kinds of libraries. Pending better methods of customizing text on a per-library basis, let’s take a crack at it with jQuery.

When I inspect HTML for a way to manipulate it with jQuery, the first thing I look for is an ID to “anchor” my context. In this case the text in question falls within a <form> tag with an id, “auth.” That’s where we’ll start with our jQuery selector:

// your script goes here

But we don’t want to replace the entire contents of the <form>, we just want to replace the headings and paragraphs. Luckily those are wrapped in a single <div> which contains only the parts we want to change:

// your script goes here
$("#auth div")...

Now our code will affect any <div> which falls inside <form id=”auth”>. We’re going to use the same html() function again:

// your script goes here
$("#auth div").html(...);

We’re going to replace everything inside that <div>, and it’s as simple as writing out the html in our JavaScript:

// your script goes here
$("#auth div").html("<h5>Don't have a password yet?</h5><p>You should be receiving your login and password via telegram. Please allow 6-8 weeks for delivery.</p>");

Note that where we included an apostrophe in our HTML it was necessary to “escape” it with a backslash: . The same should be done with double-quotes:

// your script goes here
$("#auth div").html("<h5>Don't have a password yet?</h5><p>You should be receiving your login and password via telegram. <span>Please allow 6-8 weeks for delivery.</span></p>");

7 thoughts on “KohaCon 2009: Customizing Your OPAC

  1. Rachel

    Of course the other way to get it so that your customisations “flow through” is to donate your templates to the project (sans logo), and hope they become the new default 🙂

    Nice one Owen


  2. Lynn Henry


    I’m not a programmer and not really adept at html or css. I’d like to customize some of my colors like background in the lefthand menu space and the overall background. Is there an easy way to do this?

    Also, the opacmainuserblock doesn’t show up in the OPAC system preferences. Is this normal? I can’t find documentation which helps me with this.



  3. Jacek


    If I would like to modify templates ANYWAY, how could I do this?
    I have been trying altering .tt files but it takes no effect (should they be somehow recompiled or sth?).

    I would like to hide most of things on a staff-side. When I say most of things I mean about 80% of it. The easiest way to do it which I can think of is to comment out parts of template files.


  4. oleonard Post author

    Jacek, modifying the .tt (and.inc) files is what you do if you want to change the templates. If it doesn’t seem to be working could it be you’re modifying the wrong set of templates? If you work with non-English templates there will be more than one set.

    I highly recommend you use git to keep track of your template modifications so that you can more easily merge changes when it’s time to upgrade.

  5. Purab Gujar

    Hi Owen,

    In the case of modifying templates (Intranet and opac) – Can you provide the exact git and package upgrade workflow one should follow so as to manage upgrades effectively? Is there post that describes the workflow?



Leave a Reply

Your email address will not be published. Required fields are marked *