diff options
Diffstat (limited to 'docs/creating-a-theme.txt')
| -rw-r--r-- | docs/creating-a-theme.txt | 1033 |
1 files changed, 739 insertions, 294 deletions
diff --git a/docs/creating-a-theme.txt b/docs/creating-a-theme.txt index 220a8e7..7113b1a 100644 --- a/docs/creating-a-theme.txt +++ b/docs/creating-a-theme.txt @@ -1,380 +1,825 @@ -.. 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™**, 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. -.. TEASER_END +Checking It Out +--------------- -Starting The Theme ------------------- +The first step in porting a theme is making the original theme work. Lanyon is awesome in that its +`GitHub project <https://github.com/poole/lanyon>`__ is a full site! -First we will create a testing site:: +So:: - $ 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. + # Get jekyll + sudo apt-get install jekyll - $ cd monospace-site/ + # Get Lanyon + git clone git@github.com:poole/lanyon.git -Our theme will inherit from the ``bootstrap`` theme, which is full-featured but boring. + # Build it + cd lanyon && jekyll build -:: + # Look at it + jekyll serve & google-chrome http://localhost:4000 +If you **do not want to install Jekyll**, 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 schemes +2. Reverse layout +3. Sidebar overlay instead of push +4. Open the sidebar by default, or on a per-page basis by using its 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 -The next step is to make the testing site use this new theme, by editing ``conf.py`` and -changing the ``THEME`` option:: +Edit ``conf.py`` and set ``THEME = 'lanyon'``. Also set ``USE_BUNDLES = False`` (just do it for now, we’ll get to bundles later). - # Name of the theme to use. Themes are located in themes/theme_name - THEME = 'monospace' +You can now build that site using ``nikola build`` and it will look like this: -Now we can already build and test the site:: +.. figure:: https://getnikola.com/images/lanyon-0.thumbnail.png + :target: https://getnikola.com/images/lanyon-0.png - $ nikola build && nikola serve + This is just the base theme. -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-1.png - :height: 400px +Basic CSS +--------- - This is the default "bootstrap" theme. +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: -Of course, the page layout is completely different from what we want. To fix that, we need to -get into templates. +.. code:: html -Templates: Page Layout ----------------------- + <!DOCTYPE html> + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us"> -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: + <head> + <link href="http://gmpg.org/xfn/11" rel="profile"> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> -.. code-block:: mako + <!-- Enable responsiveness on mobile devices--> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1"> + + <title> + Lanyon · 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 the paths a little so that they follow our conventions:: + + $ mkdir -p themes/lanyon/assets/css + $ cp ../lanyon/public/css/poole.css themes/lanyon/assets/css/ + $ cp ../lanyon/public/css/lanyon.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. + +Nikola **requires** ``assets/css/rst.css`` and ``assets/css/code.css`` to function properly. +We will also add themes for IPython Notebook (``assets/css/ipython.min.css`` +and ``assets/css/nikola_ipython.css``) into the template; note that they are +activated only if you configured your ``POSTS``/``PAGES`` with ipynb support. + +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 + % if needs_ipython_css: + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + % 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/poole.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/lanyon.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 + % if needs_ipython_css: + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + % endif + <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700|PT+Sans:400"> + </%def> + +.. figure:: https://getnikola.com/images/lanyon-1.thumbnail.png + :target: https://getnikola.com/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: + +.. code:: html + + <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> + +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? -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. +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. -Monospace is a two-column-with-footer layout, so let's copy the basics from its HTML and see what happens: +Let’s look at ``base.tmpl`` first. It’s short and nice, it looks like a webpage without +all the interesting stuff: -.. code-block:: mako +.. 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"))}: - ${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:: https://getnikola.com/images/lanyon-2.thumbnail.png + :target: https://getnikola.com/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:: https://getnikola.com/images/lanyon-3.thumbnail.png + :target: https://getnikola.com/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 toggle. Easy to do in ``base.tmpl`` +(only showing the 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:: https://getnikola.com/images/lanyon-4.thumbnail.png + :target: https://getnikola.com/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``, along with others used by other +pieces of the site: + +.. code:: css + + .sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + } + + .sr-only-focusable:active, + .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; + } + + .breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + } -.. figure:: http://ralsina.com.ar/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%; + .breadcrumb > li { + display: inline-block; + margin-right: 0; + margin-left: 0; } - ul.breadcrumb > li:before { - content: " / "; + + .breadcrumb > li:after { + content: ' / '; + color: #888; + } + + .breadcrumb > li:last-of-type:after { + content: ''; + margin-left: 0; + } + + .thumbnails > li { + display: inline-block; + margin-right: 10px; + } + + .thumbnails > li:last-of-type { + margin-right: 0; } -This will (after we rebuild it) make the site looks different of course, and getting closer to our goal: -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-3.png - :height: 400px +.. figure:: https://getnikola.com/images/lanyon-5.thumbnail.png + :target: https://getnikola.com/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 thing in Nikola, we have settings for +that. So, let’s use them. 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. + +And now we more or less have the correct page layout and styles. Except for a +rather large thing… + +Typography +---------- + +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! + +Let’s start with the titles. Here’s how they look in Lanyon: + +.. 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: - Monospaced allright. +.. code:: html+mako -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>`` + <%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> -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``: +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-block:: mako +.. 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> - ${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: - %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> +With these changes, it looks… similar? -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-4.png - :height: 400px +.. figure:: https://getnikola.com/images/lanyon-6.thumbnail.png + :target: https://getnikola.com/images/lanyon-6.png - Close enough! + It does! -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. +Similar changes (basically adding class names to elements) needed to be done in ``post_header.tmpl``: -.. code-block:: mako +.. code:: html+mako - ## -*- 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>] + <%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")}: - %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* also do that in the Nikola port. 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:: https://getnikola.com/images/lanyon-7.thumbnail.png + :target: https://getnikola.com/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 exercise 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 the Lanyon theme, it should be like this:: + assets/css/all.css=rst.css,code.css,poole.css,lanyon.css,custom.css -.. figure:: http://ralsina.com.ar/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 |
