Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: getnikola/nikola
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e7ea5381e18d
Choose a base ref
...
head repository: getnikola/nikola
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 650b41e1db2b
Choose a head ref
  • 1 commit
  • 1 file changed
  • 1 contributor

Commits on May 28, 2015

  1. use the new theme tutorial

    ralsina committed May 28, 2015

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    650b41e View commit details
Showing with 679 additions and 296 deletions.
  1. +679 −296 docs/creating-a-theme.txt
975 changes: 679 additions & 296 deletions docs/creating-a-theme.txt
Original file line number Diff line number Diff line change
@@ -1,384 +1,767 @@
.. title: Creating a Theme
.. title: Creating A Theme
.. slug: creating-a-theme
.. date: 2012-03-13 12:00:00 UTC-03:00
.. date: 2015-05-28 18:46:48 UTC
.. tags:
.. category:
.. link:
.. description:
.. type: text

Creating A Theme From Scratch (Almost)
======================================
Nikola is a static site and blog generator. So is Jekyll. While I like what we have done with Nikola,
I do admit that Jekyll (and others!) have many more, and nicer themes than Nikola does.

.. class:: lead
This document is an attempt at making it easier for 3rd parties (that means you people! ;-) to
create themes. Since I **suck** at designing websites, I asked for opinions on themes to port,
and got some feedback. Since this is **Not So Hard (TM)** I will try to make time to port a few
and see what happens.

There is some documentation about creating themes for Nikola, but maybe a tutorial is also a useful way
to explain it. So, here it is. I'll explain how to create a theme (almost) from scratch. All themes
in Nikola must inherit from the ``base`` theme. In this case, we will inherit from ``bootstrap``
so we get good support for slides and galleries.
Today's theme is `Lanyon <https://github.com/poole/lanyon>`__ which is written by `@mdo <https://twitter.com/mdo>`__
and released under a MIT license, which is liberal enough.

I will try to create a theme that looks like `Vinicius Massuchetto's Monospace Theme <http://wordpress.org/themes/monospace>`_.
So, let's get started.

.. danger::
Checking It Out
---------------

This document is outdated! Recommendations in this post may not work!
The first step in porting a theme is making the original theme work. Lanyon is awesome in that its
`github prohject <https://github.com/poole/lanyon>`__ is a full site!

.. TEASER_END
So::

Starting The Theme
------------------
# Get jekyll
sudo apt-get install jekyll

First we will create a testing site::
# Get Lanyon
git clone git@github.com:poole/lanyon.git

$ nikola init --demo monospace-site
A new site with some sample data has been created at monospace-site.
See README.txt in that folder for more information.
# Build it
cd lanyon && jekyll build

$ cd monospace-site/
# Look at it
jekyll serve & google-chrome http://localhost:4000

Our theme will inherit from the ``bootstrap`` theme, which is full-featured but boring.
If you want, you can also see it in action at http://lanyon.getpoole.com/

::
Some things jump to my mind:

1) This is one fine looking theme
2) Very clear and readable
3) Nice hidden navigation-thingy

Also, from looking at `the project's README <https://github.com/poole/lanyon/blob/master/README.md>`__
it supports some nice configuration options:

1) color scheme themes
2) reverse layout
3) sidebar overlay instead of push
4) show the sidebar open by default, or based on a page's metadata

Let's try to make all those nice things survive the porting.

Starting From Somewhere
-----------------------

Nikola has a nice, clean, base theme from which you can start when writing your own theme.
Why start from that instead of from a clean slate? Because theme inheritance is going to save you a ton of work,
that's why. If you start from scratch you won't be able to build **anything** until you have a bunch of
templates written. Starting from base, you just need to hack on the things you **need** to change.

First, we create a site with some content in it. We’ll use the ``nikola init`` wizard (with the ``--demo`` option) for that::

$ nikola init --demo lanyon-port
Creating Nikola Site
====================

This is Nikola v7.4.1. We will now ask you a few easy questions about your new site.
If you do not want to answer and want to go with the defaults instead, simply restart with the `-q` parameter.
--- Questions about the site ---
Site title [My Nikola Site]:
Site author [Nikola Tesla]:
Site author's e-mail [n.tesla@example.com]:
Site description [This is a demo site for Nikola.]:
Site URL [https://example.com/]:
--- Questions about languages and locales ---
We will now ask you to provide the list of languages you want to use.
Please list all the desired languages, comma-separated, using ISO 639-1 codes. The first language will be used as the default.
Type '?' (a question mark, sans quotes) to list available languages.
Language(s) to use [en]:

Please choose the correct time zone for your blog. Nikola uses the tz database.
You can find your time zone here:
http://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Time zone [UTC]:
Current time in UTC: 16:02:07
Use this time zone? [Y/n]
--- Questions about comments ---
You can configure comments now. Type '?' (a question mark, sans quotes) to list available comment systems. If you do not want any comments, just leave the field blank.
Comment system:

That's it, Nikola is now configured. Make sure to edit conf.py to your liking.
If you are looking for themes and addons, check out https://themes.getnikola.com/ and https://plugins.getnikola.com/.
Have fun!
[2015-05-28T16:02:08Z] INFO: init: A new site with example data has been created at lanyon-port.
[2015-05-28T16:02:08Z] INFO: init: See README.txt in that folder for more information.

Then, we create an empty theme inheriting from base. This theme will use Mako templates. If you prefer Jinja2,
then you should use base-jinja instead::

$ cd lanyon-port/
$ mkdir themes
$ mkdir themes/monospace
$ echo bootstrap > themes/monospace/parent
$ mkdir themes/lanyon
$ echo base > themes/lanyon/parent

Edit conf.py and set ``THEME = 'lanyon'``. Also set ``USE_BUNDLES = False`` (just do it for now, we'll get to bundles later).

The next step is to make the testing site use this new theme, by editing ``conf.py`` and
changing the ``THEME`` option::
You can now build that site using ``nikola build`` and it will look like this:

# Name of the theme to use. Themes are located in themes/theme_name
THEME = 'monospace'
.. figure:: /images/lanyon-0.thumbnail.png
:target: /images/lanyon-0.png

Now we can already build and test the site::
This is just the base theme.

$ nikola build && nikola serve
Basic CSS
---------

.. figure:: http://ralsina.me/galleries/monospace-tut/monospace-1.png
:height: 400px
The next step is to know exactly how Lanyon's pages work. To do this, we read its HTML.
First let's look at the head element:

This is the default "bootstrap" theme.
.. code:: html

Of course, the page layout is completely different from what we want. To fix that, we need to
get into templates.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">

Templates: Page Layout
----------------------
<head>
<link href="http://gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">

The general page layout for the theme is done by the ``base.tmpl`` template, which is done using
`Mako <http://www.makotemplates.org/>`_. This is bootstrap's ``base.tmpl``, it's not very big:
<!-- Enable responsiveness on mobile devices-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">

.. code-block:: mako
<title>
Lanyon &middot; A Jekyll theme
</title>

<!-- CSS -->
<link rel="stylesheet" href="/public/css/poole.css">
<link rel="stylesheet" href="/public/css/syntax.css">
<link rel="stylesheet" href="/public/css/lanyon.css">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700|PT+Sans:400">

<!-- Icons -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/public/apple-touch-icon-144-precomposed.thumbnail.png">
<link rel="shortcut icon" href="/public/favicon.ico">

<!-- RSS -->
<link rel="alternate" type="application/rss+xml" title="RSS" href="/atom.xml">

<!-- Google Analytics -->
[...]
</head>

The interesting part there is that it loads a few CSS files. If you check the source of your Nikola site, you will
see something fairly similar:

.. code:: html

## -*- coding: utf-8 -*-
<%namespace name="base" file="base_helper.tmpl" import="*" />
<%namespace name="bootstrap" file="bootstrap_helper.tmpl" import="*" />
${set_locale(lang)}
<!DOCTYPE html>
<html% if comment_system == 'facebook': xmlns:fb="http://ogp.me/ns/fb#" %endif lang="${lang}">
<html prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article# " vocab="http://ogp.me/ns" lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
${bootstrap.html_head()}
<%block name="extra_head">
</%block>
${extra_head_data}
<meta charset="utf-8">
<meta name="description" content="This is a demo site for Nikola.">
<meta name="viewport" content="width=device-width">
<title>My Nikola Site | My Nikola Site</title>

<link href="assets/css/rst.css" rel="stylesheet" type="text/css">
<link href="assets/css/code.css" rel="stylesheet" type="text/css">
<link href="assets/css/theme.css" rel="stylesheet" type="text/css">

<link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml">
<link rel="canonical" href="https://example.com/index.html">
<!--[if lt IE 9]><script src="assets/js/html5.js"></script><![endif]--><link rel="prefetch" href="posts/welcome-to-nikola.html" type="text/html">
</head>
<body>
<!-- Menubar -->
<div class="navbar navbar-fixed-top" id="navbar">
<div class="navbar-inner">
<div class="container">

<!-- .btn-navbar is used as the toggle for collapsed navbar content -->
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>

<a class="brand" href="${abs_link('/')}">
${blog_title}
</a>
<!-- Everything you want hidden at 940px or less, place within here -->
<div class="nav-collapse collapse">
<ul class="nav">
${bootstrap.html_navigation_links()}
</ul>
%if search_form:
${search_form}
%endif
<ul class="nav pull-right">
<%block name="belowtitle">
%if len(translations) > 1:
<li>${base.html_translations()}</li>
%endif
</%block>
% if show_sourcelink:
<li><%block name="sourcelink"></%block></li>
%endif
</ul>
</div>
</div>
</div>
</div>
<!-- End of Menubar -->
<div class="container-fluid" id="container-fluid">
<!--Body content-->
<div class="row-fluid">
<div class="span2"></div>
<div class="span8">
<%block name="content"></%block>
</div>


Luckily, since this is all under a very liberal license, we can just copy these CSS files into
Nikola, adapting a little the paths so that they follow
our conventions::

$ mkdir -p themes/lanyon/assets/css
$ cp ../lanyon/public/css/lanyon.css themes/lanyon/assets/css/
$ cp ../lanyon/public/css/poole.css themes/lanyon/assets/css/

Notice I am *not* copying ``syntax.css``? That's because Nikola handles that styles for syntax highlighting
in a particular way, using a setting called ``CODE_COLOR_SCHEME`` where you can configure
what color scheme the syntax highlighter uses. You can use your own ``assets/css/code.css`` if you
don't like the provided ones.

But how do I tell **our** lanyon theme to use those CSS files instead of whatever it's using now?
By giving our theme its own base_helper.tmpl

That file is a **template** used to generate parts of the pages. It's large and complicated but we don't need to change a lot of it. First, get it from `Nikola's source code <https://github.com/getnikola/nikola/blob/master/nikola/data/themes/base/templates/base_helper.tmpl>`__ and put a copy in ``themes/lanyon/templates/base_helper.tmpl``::

$ mkdir themes/lanyon/templates
$ curl https://raw.githubusercontent.com/getnikola/nikola/master/nikola/data/themes/base/templates/base_helper.tmpl > themes/lanyon/templates/base_helper.tmpl

The part we want to change is this:

.. code:: html+mako

<%def name="html_stylesheets()">
%if use_bundles:
%if use_cdn:
<link href="/assets/css/all.css" rel="stylesheet" type="text/css">
%else:
<link href="/assets/css/all-nocdn.css" rel="stylesheet" type="text/css">
%endif
%else:
<link href="/assets/css/rst.css" rel="stylesheet" type="text/css">
<link href="/assets/css/code.css" rel="stylesheet" type="text/css">
<link href="/assets/css/theme.css" rel="stylesheet" type="text/css">
%if has_custom_css:
<link href="/assets/css/custom.css" rel="stylesheet" type="text/css">
%endif
%endif
</%def>

And we will change it so it uses the lanyon styles instead of theme.css (again, ignore the bundles for now!):

.. code:: html+mako

<%def name="html_stylesheets()">
%if use_bundles:
<link href="/assets/css/all.css" rel="stylesheet" type="text/css">
%else:
<link href="/assets/css/rst.css" rel="stylesheet" type="text/css">
<link href="/assets/css/lanyon.css" rel="stylesheet" type="text/css">
<link href="/assets/css/poole.css" rel="stylesheet" type="text/css">
<link href="/assets/css/code.css" rel="stylesheet" type="text/css">
%if has_custom_css:
<link href="/assets/css/custom.css" rel="stylesheet" type="text/css">
%endif
%endif
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700|PT+Sans:400">
</%def>

.. figure:: /images/lanyon-1.thumbnail.png
:target: /images/lanyon-1.png

You may say this looks like crap. Don't worry, we are just starting :-)

Page Layout
-----------

This is trickier but should be no problem for people with a basic understanding of HTML and a desire to make a theme!

Lanyon's content is split in two parts: a sidebar and the rest. The sidebar looks like this (shortened for comprehension):

.. code:: html

<body>
<!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular
styles, `#sidebar-checkbox` for behavior. -->
<input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox">

<!-- Toggleable sidebar -->
<div class="sidebar" id="sidebar">
<div class="sidebar-item">
<p>A reserved <a href="http://jekyllrb.com" target="_blank">Jekyll</a> theme that places the utmost gravity on content with a hidden drawer. Made by <a href="https://twitter.com/mdo" target="_blank">@mdo</a>.</p>
</div>
<!--End of body content-->
</div>
<div class="footerbox">
${content_footer}

<nav class="sidebar-nav">
<a class="sidebar-nav-item active" href="/">Home</a>
<a class="sidebar-nav-item" href="/about/">About</a>
[...]
</nav>
</div>
${bootstrap.late_load_js()}
${base.html_social()}
<script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});
$(window).on('hashchange', function(){
if (location.hash && $(location.hash)[0]) {
$('body').animate({scrollTop: $(location.hash).offset().top - $('#navbar').outerHeight(true)*1.2 }, 1);
}
});
$(document).ready(function(){$(window).trigger('hashchange')});
</script>
<%block name="extra_js"></%block>
${body_end}
</body>

So, a plain body, with an input element that controls the sidebar, a div which is the sidebar itself.
Inside that, div.sidebar-item for items, and a nav with "navigational links". This is followed by the "masthead" and
the content itself, which we will look at in a bit.

If we look for the equivalent code in Nikola's side, we see this:

It's basically a HTML document with some placeholders to be replaced with actual content, configuration options, and some helper functions.
For example, the ``html_head`` helper can be used to add CSS or JS files in all document's ``head`` tags.
.. code:: html

Monospace is a two-column-with-footer layout, so let's copy the basics from its HTML and see what happens:
<body>
<a href="#content" class="sr-only sr-only-focusable">Skip to main content</a>
<div id="container">
<header id="header" role="banner">
<h1 id="brand"><a href="https://example.com/" title="My Nikola Site" rel="home"> <span id="blog-title">My Nikola Site</span> </a></h1>
<nav id="menu" role="navigation"><ul>
<li><a href="../archive.html">Archive</a></li>
<li><a href="../categories/index.html">Tags</a></li>
<li><a href="../rss.xml">RSS feed</a></li>

.. code-block:: mako
So Nikola has the "masthead" above the nav element, and uses list elements in nav instead of bare links.
Not all that different is it?

Let's make it lanyon-like! We will need 2 more templates: `base.tmpl <https://github.com/getnikola/nikola/blob/master/nikola/data/themes/base/templates/base.tmpl>`__ and `base_header.tmpl <https://github.com/getnikola/nikola/blob/master/nikola/data/themes/base/templates/base_header.tmpl>`__. Get them and put them in your ``themes/lanyon/templates`` folder.

Let's look at ``base.tmpl`` first. It's short and nice, it looks like a webpage without
all the interesting stuff:

.. code:: html+mako

## -*- coding: utf-8 -*-
<%namespace name="base" file="base_helper.tmpl" import="*"/>
<%namespace name="bootstrap" file="bootstrap_helper.tmpl" import="*" />
<%namespace name="header" file="base_header.tmpl" import="*"/>
<%namespace name="footer" file="base_footer.tmpl" import="*"/>
<%namespace name="annotations" file="annotation_helper.tmpl"/>
${set_locale(lang)}
<!DOCTYPE html>
<html lang="${lang}">
<head>
${bootstrap.html_head()}
<%block name="extra_head">
</%block>
${extra_head_data}
${base.html_headstart()}
<%block name="extra_head">
### Leave this block alone.
</%block>
${template_hooks['extra_head']()}
</head>
<body class="home blog">
<div id="wrap" style="width:850px">
<div id="container" style="width:560px">
<body>
<a href="#content" class="sr-only sr-only-focusable">${messages("Skip to main content")}</a>
<div id="container">
${header.html_header()}
<main id="content" role="main">
<%block name="content"></%block>
</main>
${footer.html_footer()}
</div>
${body_end}
${template_hooks['body_end']()}
${base.late_load_js()}
</body>
</html>

That link which says "Skip to main content" is very important for accessibility, so we will leave it in
place. But below, you can see how it creates the "container" div we see in the Nikola page, and the content is
created by ``html_header()`` which is defined in ``base_header.tmpl`` The actual ``nav`` element is done
by the ``html_navigation_links`` function out of the ``NAVIGATION_LINKS`` option.

So, first, lets change that base template to be more lanyon-like:

.. code:: html+mako

## -*- coding: utf-8 -*-
<%namespace name="base" file="base_helper.tmpl" import="*"/>
<%namespace name="header" file="base_header.tmpl" import="*"/>
<%namespace name="footer" file="base_footer.tmpl" import="*"/>
<%namespace name="annotations" file="annotation_helper.tmpl"/>
${set_locale(lang)}
${base.html_headstart()}
<%block name="extra_head">
### Leave this block alone.
</%block>
${template_hooks['extra_head']()}
</head>
<body>
<a href="#content" class="sr-only sr-only-focusable">${messages("Skip to main content")}</a>
<!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular
styles, `#sidebar-checkbox` for behavior. -->
<input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox">

<!-- Toggleable sidebar -->
<div class="sidebar" id="sidebar">
<div class="sidebar-item">
<p>A reserved <a href="http://getnikola.com" target="_blank">Nikola</a> theme that places the utmost gravity on content with a hidden drawer. Made by <a href="https://twitter.com/mdo" target="_blank">@mdo</a> for Jekyll,
ported to Nikola by <a href="https://twitter.com/ralsina" target="_blank">@ralsina</a>.</p>
</div>
<div id="sidebar">
<!--Sidebar content-->
<h1 id="blog-title">
<a href="${abs_link('/')}" title="${blog_title}">${blog_title}</a>
</h1>
<%block name="belowtitle">
%if len(translations) > 1:
<small>
${(messages("Also available in"))}:&nbsp;
${base.html_translations()}
</small>
%endif
</%block>
<ul class="unstyled">
<li>${license}
${base.html_social()}
${bootstrap.html_navigation_links()}
<li>${search_form}
</ul>
</div>
<div id="footer">
${content_footer}
${header.html_navigation_links()}
</div>

<main id="content" role="main">
<%block name="content"></%block>
</main>
${footer.html_footer()}
${body_end}
${template_hooks['body_end']()}
${base.late_load_js()}
</body>
</html>

.. figure:: /images/lanyon-2.thumbnail.png
:target: /images/lanyon-2.png

And that's after I exposed the sidebar by clicking on an invisible widget!

One problem, which causes that yellow color in the sidebar is a CSS conflict. We are loading rst.css which specifies
the background color of ``div.sidebar`` which is more specific than lanyon.css, which specifies for ``.sidebar`` alone.

There are many ways to fix this, I chose to change lanyon.css to also use div.sidebar:

.. code:: css

div.sidebar,.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: -14rem;
width: 14rem;
[...]

This is annoying but it will happen when you just grab CSS from different places. The "Inspect Element"
feature of your web browser is your best friend for these situations.

Another problem is that the contents of the nav element are wrong. They are not bare links. We will fix that in
``base_header.html``, like this:

.. code:: html+mako

<%def name="html_navigation_links()">
<nav id="menu" role="navigation" class="sidebar-nav">
%for url, text in navigation_links[lang]:
<a class="sidebar-nav-item" href="${url}">${text}</a>
%endfor
${template_hooks['menu']()}
${template_hooks['menu_alt']()}
</nav>
</%def>

**Note: this means this theme will not support submenus in navigation. If you want that, I'll happily take a patch.**

.. figure:: /images/lanyon-3.thumbnail.png
:target: /images/lanyon-3.png

Starting to see a resemblance?

Now let's look at the content. In Lanyon, this is how the "main" content looks:

.. code:: html

<!-- Wrap is the content to shift when toggling the sidebar. We wrap the
content to avoid any CSS collisions with our real content. -->
<div class="wrap">
<div class="masthead">
<div class="container">
<h3 class="masthead-title">
<a href="/" title="Home">Lanyon</a>
<small>A Jekyll theme</small>
</h3>
</div>
</div>

<div class="container content">
<div class="post">
<h1 class="post-title">Introducing Lanyon</h1>
<span class="post-date">02 Jan 2014</span>
<p>Lanyon is an unassuming <a href="http://jekyllrb.com">Jekyll</a> theme [...]
</div>
</div>
</div>
<label for="sidebar-checkbox" class="sidebar-toggle"></label>
</body>
</html>

Everything inside the "container content" div is ... the content. The rest is a masthead with the site title
and at the bottom a label for the sidebar's toggle. Easy to do in ``base.tmpl`` (only showing relevant part):

.. code:: html+mako

<!-- Wrap is the content to shift when toggling the sidebar. We wrap the
content to avoid any CSS collisions with our real content. -->
<div class="wrap">
<div class="masthead">
<div class="container">
<h3 class="masthead-title">
<a href="/" title="Home">Lanyon</a>
<small>A Jekyll theme</small>
</h3>
</div>
</div>
${bootstrap.late_load_js()}
<script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script>
<%block name="extra_js"></%block>

<div class="container content" id="content">
<%block name="content"></%block>
</div>
</div>
<label for="sidebar-checkbox" class="sidebar-toggle"></label>
${footer.html_footer()}
${body_end}
${template_hooks['body_end']()}
${base.late_load_js()}
</body>
</html>

.. figure:: /images/lanyon-4.thumbnail.png
:target: /images/lanyon-4.png

Getting there!

The sidebar looks bad because of yet more CSS conflicts with rst.css. By adding some extra styling in lanyon.css, it will look better.

.. code:: css

/* Style and "hide" the sidebar */
div.sidebar,.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: -14rem;
width: 14rem;
visibility: hidden;
overflow-y: auto;
padding: 0;
margin: 0;
border: none;
font-family: "PT Sans", Helvetica, Arial, sans-serif;
font-size: .875rem; /* 15px */
color: rgba(255,255,255,.6);
background-color: #202020;
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}

Also, the accessibility link on top is visible when it should not. That's because we removed "theme.css" from the base theme, and with it, we lost a couple of classes. We can add them in lanyon.css:

.. figure:: http://ralsina.me/galleries/monospace-tut/monospace-2.png

Yikes!

This will get better quickly once we add some CSS


Base CSS
--------

The orphan theme includes just a little styling, specifically ``rest.css`` so
the reStructuredText output looks reasonable, and ``code.css`` for code snippets.

It also includes an empty ``assets/css/theme.css`` where you can add your own CSS.
For example, this is taken from the original monospace theme, except for the last
few selectors:

.. code-block:: css

body { margin:0px; padding:20px 0px; text-align:center; font-family:Monospace; color:#585858; }
.post { margin:0px 0px 30px 0px; padding:0px 0px 30px 0px; border-bottom:1px dotted #C8C8C8; }
.meta { margin:10px; padding:15px; background:#EAEAEA; clear:both; }
#footer { text-align:center; clear:both; margin:30px 0px 0px 0px; padding:30px 0px 0px 0px; border-top:1px dotted #C8C8C8; }
#wrap { margin:0px auto; text-align:left; font-size: 13px; line-height: 1.4; }
#container { float:right; }
#sidebar { overflow:hidden; clear:left; text-align:right; width:250px; height:auto; padding:0px 15px 0px 0px; border-right:1px dotted #C8C8C8; }
#sidebar li { list-style-type:none; }
#sidebar > li { margin:20px 0px; }
#sidebar h1 { border-bottom:1px dotted #C8C8C8; }
#sidebar .description { display:block; width:100%; height:auto; margin:0px 0px 10px 0px; }
h1, h2, h3, h4, h5, h6, h7 { margin:0px; text-transform:uppercase; }
h4, h5, h6 { font-size:14px; }
#blog-title { margin-top: 0; line-height:48px;}
.literal-block {padding: .5em;}
div.sidebar, div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning {
/* Issue 277 */
border: 1px solid #aaa;
border-radius: 5px;
width: 100%;
.. code:: css

.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
ul.breadcrumb > li:before {
content: " / ";

.sr-only-focusable:active,
.sr-only-focusable:focus {
position: static;
width: auto;
height: auto;
margin: 0;
overflow: visible;
clip: auto;
}

This will (after we rebuild it) make the site looks different of course, and getting closer to our goal:
.. figure:: /images/lanyon-5.thumbnail.png
:target: /images/lanyon-5.png

Little by little, things look better.

One clear problem is that the title "Lanyon A Jekyll theme" is set in the theme itself. We don't do that sort of things
in Nikola, we have settings for that. So, let's use it. There is a ``html_site_title`` function in ``base_helper.tmpl`` which is just the thing. So we change base.tmpl to use it:

.. code:: html+mako

<div class="wrap">
<div class="masthead">
<div class="container">
${header.html_site_title()}
</div>
</div>

That's a H1 instead of a H3 like Lanyon does, but hey, it's the right thing to do. If you want to go with an H3, just
change ``html_site_title`` itself.

.. figure:: http://ralsina.me/galleries/monospace-tut/monospace-3.png
:height: 400px
And now we more or less have the correct page layout and styles. Except for a rather large thing...

Monospaced allright.
Typography
----------

If you compare it to `the original <http://wp-themes.com/monospace/>`_, however, you will see that the layout of
the posts themselves is different, and that was not described in ``base.tmpl`` at all. But if you look, you'll see that
there is a placeholder called content: ``<%block name="content"></%block>``
You can see in the previous screenshot that text still looks quite different in our port: Serif versus Sans-Serif
content, and the titles have different colors!

That's because ``base.tmpl`` defines the *base* layout. The layout of more specific pages, like "the page that shows
a list of posts" is defined in the other templates. Specifically, this is defined in ``index.tmpl``.
It turns out ``bootstrap`` doesn' have one of those! That's because it inherits that template from ``base``:
Let's start with the titles. Here's how they look in Lanyon:

.. code-block:: mako
.. code:: html

<h3 class="masthead-title">
<a href="/" title="Home">Lanyon</a>
<small>A Jekyll theme</small>
</h3>

Versus our port:

.. code:: html

<h1 id="brand"><a href="https://example.com/" title="My Nikola Site" rel="home">

So, it looks like we will have to fix ``html_site_title`` after all:

.. code:: html+mako

<%def name="html_site_title()">
<h3 id="brand" class="masthead-title">
<a href="${abs_link(_link("root", None, lang))}" title="${blog_title}" rel="home">${blog_title}</a>
</h3>
</%def>

As for the actual content, that's not in any of the templates we have seen so far. The page you see is an
"index.tmpl" page, which means it's a list of blog posts shown one below the other. Obviously it's not doing
things in the way the Lanyon CSS expects it to. Here's the original, which you can find in Nikola's source
code:

.. code:: html+mako

## -*- coding: utf-8 -*-
<%namespace name="helper" file="index_helper.tmpl"/>
<%namespace name="comments" file="comments_helper.tmpl"/>
<%inherit file="base.tmpl"/>

<%block name="extra_head">
${parent.extra_head()}
% if posts and (permalink == '/' or permalink == '/' + index_file):
<link rel="prefetch" href="${posts[0].permalink()}" type="text/html">
% endif
</%block>

<%block name="content">
% for post in posts:
<div class="postbox post-${post.meta('type')}">
<h1><a href="${post.permalink()}">${post.title()}</a>
<small>&nbsp;&nbsp;
${messages("Posted")}: <time class="published" datetime="${post.date.isoformat()}">${post.formatted_date(date_format)}</time>
</small></h1>
<hr>
${post.text(teaser_only=index_teasers)}
% if not post.meta('nocomments'):
${comments.comment_link(post.permalink(), post.base_path)}
% endif
<%block name="content_header"></%block>
<div class="postindex">
% for post in posts:
<article class="h-entry post-${post.meta('type')}">
<header>
<h1 class="p-name entry-title"><a href="${post.permalink()}" class="u-url">${post.title()|h}</a></h1>
<div class="metadata">
<p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p>
<p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="published dt-published" datetime="${post.date.isoformat()}" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p>
% if not post.meta('nocomments') and site_has_comments:
<p class="commentline">${comments.comment_link(post.permalink(), post._base_path)}
% endif
</div>
% endfor
${helper.html_pager()}
${comments.comment_link_script()}
${helper.mathjax_script(posts)}
</header>
%if index_teasers:
<div class="p-summary entry-summary">
${post.text(teaser_only=True)}
%else:
<div class="e-content entry-content">
${post.text(teaser_only=False)}
%endif
</div>
</article>
% endfor
</div>
${helper.html_pager()}
${comments.comment_link_script()}
${helper.mathjax_script(posts)}
</%block>

So, let's tweak that to be closer to the original. We put the post's metadata in a
box, add links for the posts tags, move the date there, etc.

.. code-block:: mako
And this is how it looks after I played with it for a while, making it generate code that looks closer to
the Lanyon original:

.. code:: html+mako

## -*- coding: utf-8 -*-
<%namespace name="helper" file="index_helper.tmpl"/>
<%namespace name="disqus" file="disqus_helper.tmpl"/>
<%inherit file="base.tmpl"/>
<%block name="content">
% for post in posts:
<div class="postbox post-${post.meta('type')}">
<h1><a href="${post.permalink()}">${post.title()}</a></h1>
<div class="meta" style="background-color: rgb(234, 234, 234); ">
<span class="authordate">
${messages("Posted")}: ${post.formatted_date(date_format)}
</span>
<br>
<span class="tags">Tags:&nbsp;
%if post.tags:
%for tag in post.tags:
<a class="tag" href="${_link('tag', tag)}"><span>${tag}</span></a>
%endfor
%endif
</span>
</div>
${post.text(teaser_only=index_teasers)}
% if not post.meta('nocomments'):
${disqus.html_disqus_link(post.permalink()+"#disqus_thread", post.base_path)}
% endif
<%block name="content_header"></%block>
<div class="posts">
% for post in posts:
<article class="post h-entry post-${post.meta('type')}">
<header>
<h1 class="post-title p-name"><a href="${post.permalink()}" class="u-url">${post.title()|h}</a></h1>
<div class="metadata">
<p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p>
<p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="post-date published dt-published" datetime="${post.date.isoformat()}" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p>
% if not post.meta('nocomments') and site_has_comments:
<p class="commentline">${comments.comment_link(post.permalink(), post._base_path)}
% endif
</div>
% endfor
${helper.html_pager()}
${disqus.html_disqus_script()}
</header>
%if index_teasers:
<div class="p-summary entry-summary">
${post.text(teaser_only=True)}
%else:
<div class="e-content entry-content">
${post.text(teaser_only=False)}
%endif
</div>
</article>
% endfor
</div>
${helper.html_pager()}
${comments.comment_link_script()}
${helper.mathjax_script(posts)}
</%block>

Some of the typography problems were caused by loading ``lanyon.css`` and ``poole.css`` in the wrong order all the way back at the beginning of this tutorial.

.. figure:: http://ralsina.me/galleries/monospace-tut/monospace-4.png
:height: 400px
With these changes, it looks ... similar?

Close enough!
.. figure:: /images/lanyon-6.thumbnail.png
:target: /images/lanyon-6.png

Then if we click on the post title, we will see some broken details in the metadata that can be fixed in ``post.tmpl``, and so on.
It does!

.. code-block:: mako
Similar changes (basically adding classnames to elements) needed to be done in ``post_header.tmpl``:

## -*- coding: utf-8 -*-
<%namespace name="helper" file="post_helper.tmpl"/>
<%namespace name="disqus" file="disqus_helper.tmpl"/>
<%inherit file="base.tmpl"/>
<%block name="extra_head">
${helper.twitter_card_information(post)}
% if post.meta('keywords'):
<meta name="keywords" content="${post.meta('keywords')|h}"/>
% endif
</%block>
<%block name="content">
<div class="post">
${helper.html_title()}
<div class="meta" style="background-color: rgb(234, 234, 234); ">
<span class="authordate">
${messages("Posted")}: ${post.formatted_date(date_format)}
% if not post.meta('password'):
[<a href="${post.source_link()}" id="sourcelink">${messages("Source")}</a>]
.. code:: html+mako

<%def name="html_post_header()">
<header>
${html_title()}
<div class="metadata">
<p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p>
<p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="post-date published dt-published" datetime="${post.date.isoformat()}" itemprop="datePublished" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p>
% if not post.meta('nocomments') and site_has_comments:
<p class="commentline">${comments.comment_link(post.permalink(), post._base_path)}
% endif
</span>
<br>
%if post.tags:
<span class="tags">${messages("Tags")}:&nbsp;
%for tag in post.tags:
<a class="tag" href="${_link('tag', tag)}"><span>${tag}</span></a>
%endfor
</span>
<br>
%if post.description():
<meta name="description" itemprop="description" content="${post.description()}">
%endif
<span class="authordate">
${helper.html_translations(post)}
</span>
</div>
${post.text()}
${helper.html_pager(post)}
% if not post.meta('nocomments'):
${disqus.html_disqus(post.permalink(absolute=True), post.title(), post.base_path)}
% endif
</div>
</%block>
${html_translations(post)}
</header>
</%def>

Customization
-------------

The original Lanyon theme supports some personalization options. It suggests you do them by tweaking the templates, and
you *can* do that in Nikola's port also. But we prefer to use options for that, so that you can get a later, better
version of the theme and it will still "just work".

Let's see the color schemes first. They apply easily, just tweak your ``body`` element like this:

.. code:: html

<body class="theme-base-08">
...
</body>

We can tweak ``base.tmpl`` to do just that:

.. code:: html+mako

% if lanyon_subtheme:
<body class="${lanyon_subtheme}">
%else:
<body>
%endif

And then we can put the options in conf.py's ``GLOBAL_CONTEXT``:

.. code:: python

GLOBAL_CONTEXT = {
"lanyon_subtheme": "theme-base-08"
}

.. figure:: /images/lanyon-7.thumbnail.png
:target: /images/lanyon-7.png

Look at it, all themed up.

Doing the same for layout-reverse, sidebar-overlay and the rest is left as an excercise for the reader.

Bundles
-------

If you have ``WebAssets`` installed and the ``USE_BUNDLES`` option set to True, Nikola can put several CSS or JS files together in a larger file,
which makes sites load faster. To do that, your theme needs a ``bundles`` file where the syntax is::

outputfile1.js: thing1.js, thing2.js, ...
outputfile2.css: thing1.css, thing2.css, ...

For this theme, it should be like this::

assets/css/all.css=rst.css,code.css,lanyon.css,poole.css

.. figure:: http://ralsina.me/galleries/monospace-tut/monospace-5.png
:height: 400px
**Note:** Some themes also support the ``USE_CDN`` option meaning that in some cases it will load one bundle with all CSS and in other will load some CSS files
from a CDN and others from a bundle. This is complicated and probably not worth the effort.

Details, details.
The End
-------

The demo site exercises most of the features in Nikola, so if you make it look good, your site probably will look good too.
This monospace theme is included with nikola, if you want to use it or play with it.
And that's it, that's a whole theme. Eventually, once people start using it, they will notice small broken details, which will need handling one at a time.

This theme should be available in http://themes.getnikola.com#lanyon and you can see it in action at https://themes.getnikola.com/v7/lanyon/index.html