Creating a Website with a Responsive Layout

My family blog has been Wordpress for a very long time. And I have experience with web development using JavaScript, Perl, PHP, and Java. But I was feeling nostalgic and missing the magical feeling of the first steps I took onto the internet. So I coded this site using very simple CSS and HTML. Well, CSS and HTML, generated from templates and my automation tool of choice: Python. It's always nice when tools can engender good feelings. :-)

But I was dismayed the first time I loaded it on a smart phone. Alas! The font was tiny and reading it required zooming and panning all over the place. That did make browsing the website a more interactive experience, but not really what I was going for.

Enter something called Responsive Web Design. The idea being to make my website respond to the device browsing it. I learned a lot from this helpful tutorial on the google developers site.

The first bit of magic is to add this line to my top level template in the <head> section.

<meta name="viewport" content="width=device-width, initial-scale=1">

Aside

My site is written in markdown and compiled with jinja2 into HTML. When I first wrote this article I found that the above line rendered as

&amp;lt;meta name...

It appears that the less than sign was being double escaped. At first I suspected that jinja2 was escaping input that I didn't want it to. But after figuring out how to turn off escaping in jinja2 I realized that wasn't the problem. Markdown was converting articles to HTML first so jinja2 was already properly handling HTML...

I dropped into a python interactive session and ran the article source through markdown alone. Sure enough it was double escaping. A search on the markdown github page turns up this bug report which is fixed in version 3.1 of the module. Now to upgrade...

Back to our regular programming

I've read that width=device-width makes "CSS pixels" and "device pixels" the same thing (except on browsers that don't comply). I don't understand that part, but it sounds important and it works. 'Nuff said. initial-scale=1 seems like the more important part to me. It means mobile browsers won't try to rescale or zoom my website. Good, good. I don't want that.

Next I need some queries in my CSS to change behavior depending on screen size.

First I handle the case of a biggish screen. In my case a screen larger than 900px wide. In this case I fix the width of my top level container at 900px and set it's margins to auto, so that it centers the content on the screen.

@media screen and (min-width: 900px) {
    #contain {
        width: 900px;
        margin-right: auto;
        margin-left: auto;
    }

My content is a two-column layout (in this mode) with the main content on the left and the sidebar (a menu) on the right. Notice that both are floated left. That's how it's done in CSS. You might be tempted to set the widths of the columns to equal 100%, but you'd be wrong (at least I was). I think padding isn't included in the width so I needed some slack in there. Experimentation showed 5% worked well. Clearly I don't know the box model as well as I could.

    #main {
        width: 70%;
        float: left;
    }
    #sidebar {
        width: 25%;
        float: left;
    }
}

Next I handle the small screen case. In this case the container should be 100% of the screen width. Main and sidebar are NOT floated but are shown one after the other. The sidebar is also modified from a vertical list to an inline list. That makes better use of the small screen width and reduces scrolling a bit.

@media screen and (max-width: 899px) {
    #contain {
        width: 100%;
    }
    #main {
        width: 95%;
    }
    #sidebar {
        width: 95%;
    }
    #sidebar li {
        display: inline;
    }
}

At first I had the menu show up before the content. From an organizational perspective this made sense to me. You'd want to know where are in the overall site structure before you read the content. But testing showed it was kind of annoying to click a link to read an article and then be confronted by the same list of links again and have to scroll to the article. I think the user flow is nicer if you read the content first, scrolling to the bottom and then see the menu. Aha!, the user thinks, there is more to read. I will open a bunch more of these links.

Other things I changed were removing any fixed widths from my CSS. I switched everything to percentages or just let the browser flow the content within the container. I also changed all my font-sizes from pixels to relative sizes, large, xx-large, etc.

It wasn't a ton of work. It probably took me two hours once I found the linked tutorial and a third of that time was refreshing my memory on making two column layouts with floats. I started out editing the local copy on my laptop without realizing it and when I ran my test rule from the main repo on my desktop I didn't see my changes. Wasted probably 20 minutes trying to figure that out.

A few nits are left to pick. I noticed that images aren't scaled to fit on the mobile screen, and some long lines of code flow outside the 900 pixel wide column I've define for content. Those are problems for another day.