writing HTML and CSS 'by hand'

This page documents my approach to writing HTML efficiently in a generic code editor. Previously I've been using WYSIWYG HTML editors (Netscape Composer, KompoZer, SeaMonky), but this XUL-based lineage of editors is fading away and none of the WYSIWYG alternatives appealed to me.

Writing HTML by hand is certainly more tedious but on the other hand it gives the advantage and pleasure of total control. This webpage is a test & reference page while describing strategies to achieve a practical workflow and maintainable design.

code editor

An editor for writing HTML must at least recognize HTML as a language, and also CSS. Most code editors do, natively or with help of a plugin. My favorite editor is Geany, which has served me well since long for software development (C/C++, Makefiles). It does support syntax coloring and symbol list for HTML and CSS, and user-defined code snippets. Some editors (Bluefish for example) provide buttons for HTML tags in the toolbar or menu, which Geany does not.

editor: syntax coloring

Syntax coloring makes it a bit easier to distinguish content from markup code at a glance, as illustrated by these screenshots taken from a simple text editor versus code editor:

editor: symbols list

Geany can show a list of symbols in a side pane, and in the case of HTML this applies to headings. This is particularly helpful because it enables you to quickly navigate to sections in the content via the heading titles:

editor: code snippets

A code editor is likely to support user-defined snippets, allowing to define simple names as aliases for more complex code snippets. In Geany these snippets can be defined language-specific in a configuration file like so:

# ~/.config/geany/snippets.conf: user defined code snippets per filetype


link=<a href="%cursor%"></a>

If you type 'link' in the HTML file and then hit the tab key, the word 'link' is instantaneously replaced with the HTML code as defined, with the cursor blinking at the position where the link URL shall be typed:

<a href="_"></a>

Code snippets are more tedious to use than GUI buttons because you need to memorize the aliases. On the other hand, user-defined snippets are more powerful than standard GUI because they can give quick access to special element classes if you have these defined in CSS. It would be great to have a drop-down menu with homebrew snippets, but in the absence of such a menu it helps to just have snippets.conf open in a tab while editing HTML.

content versus presentation

Ideally the HTML code should only define content (text, images etc.) while CSS takes care of layout, formatting and styling. This is not strictly possible of course, since the HTML code itself must contain markup tags. Tags and their attributes make HTML source code tedious to type, and cumbersome to read when compared to representation in a browser or WYSIWYG editor.

To keep the source tidy I focus on document structure in the first place, and use the minimum of markup code needed to clarify that structure. Headings of different level and paragraph tags do most of the work. Starting from this, I try to achieve my layout mainly by restyling standard HTML elements in CSS rules. Line-heights and top/bottom margins are redefined to force convenient vertical spacing. Background-colored padding for certain text elements gives a layout element 'for free', without the need for extra HTML code.

Only when standard HTML tags do not give enough control I define (sub)classes in CSS. For example: instead of using explicit line breaks to increase vertical space between images and other content, define an image class where such space is defined as margins. A special case that needs a lot of CSS is my single-button drop-down menu for navigation. This topic is detailed further down.

I've always written my own .css files (because Netscape and SeaMonkey didn't help with that), and found it convenient to split it up in one file for layout and another for colors and background image. Such separation simplifies 'skinning' of different HTML file groups while they can still share the same layout.

The above described simple approach will by itself result in a single-column layout. Though this leaves a lot of display real estate unused on large monitors it is practical for small laptops and handheld devices and I'm not going to do per-device-type layout. The question then arises where to put buttons or menu list for site navigation. As the current page illustrates, I opted for a fixed-position button with drop-down menu, much like the hamburger menu in smartphone apps. This menu is mainly used for quick access to sections of the page, which is useful for long pages with interrelated topics. Links to external sites do not belong in this menu; they may appear in-text or in a list at the page bottom.

For the drop-down effect I didn't want to use JavaScript since that isn't enabled or supported everywhere. The meny list does not literally drop down from the button. In reality, the list items are by default invisible because their direct parent (div #menulist) is positioned off-screen. The menulist is defined to align temporarily with the button under several conditions:

Response to focus is needed to make the menu accessible through tab key operation. As a side effect the menulist will stay on-screen after mouseclick on the button. This is helpful when the list is too long for the browser to display. Unfortunately the pseudo-class 'focus-within' is unsupported by some browsers. In that case the menulist will not remain visible while tabbing through it, however the links are still focusable and available to screen readers. HTML code for such a menu is simple and goes like this:

<nav class="menu">
    <a href="../linux/linux.html">my linux page</a>
    <span>on this page:</span>
    <a href="#topofpage">HTML by hand</a>
    <a href="#editor">code editor</a>
    <a href="#css">content vs presentation</a>
    <a href="#navigation">navigation</a>
    <a href="#images">images</a>
    <a href="#onesizefitsall">one size fits all</a>
    <a href="#links">links</a>

The CSS part is more complex. If your browser allows to inspect the HTML source, search and click '../layout.css' to see the annotated menulist rules. Otherwise use this link to open 'layout.css' in a new tab. Note that colors are defined in a different .css file.


Webspace and bandwidth limitations dictate the size of images on my web pages. Most of them are between 400 to 600 px wide depending on their function, and original size == presented size. Photo's are JPEG files with reduced quality to keep them around 50 KB.

images: screenshots

For screenshots it seems that GIF format can give best quality per KB. My default screenshooter (from Xfce4) can only do PNG. Screenshooter utility 'scrot' knows more formats but gives an error for GIF. Command 'convert' knows GIF but gives ugly result. At the moment I can only get proper GIF output from GIMP. Xfce4-screenshooter can open a screenshot in GIMP directly. This is currently my fastest route to GIF conversion. The two images below show no quality difference. Savings are not huge either so I'll only export screenshots to GIF when they need processing anyway.

PNG, 30 KiloByte

GIF, 18 KiloByte

images: positioning

Currently I've defined CSS rules for two image positioning scenarios:

A single image is easiest displayed as 'block' and using the 'auto' option on horizontal margins to center it. With maximum width and height set at 100% it will shrink to fit the browser window if needed. Order of definitions is important here (max-width before auto options). Here is my CSS rule for it:

/* simple case: img centered in its own block with much space around */
display: block;
max-width: 100%;
max-height: 100%;
margin-left: auto;
margin-right: auto;
margin-top: 5rem;
margin-bottom: 5rem;

Smaller images to be displayed side by side can be put together in a box (paragraph, div...). It gets more complicated when each of these images is to have its own caption underneath. These captions need a line break. Therefore each image must sit together with its caption in a box, and these boxes must flow horizontally without a line break. This is possible with display option 'inline-block'.

/* image container class for inlined [image + caption] */
display: inline-block;
margin: 3rem 1rem 1rem 1rem;
font-size: 0.9rem;
line-height: 1.5rem;

A side effect of inline-block is that such boxes will not forcibly stay next to each other when the window becomes too small. On a smartphone with vertical orientation they may align vertically instead of horizontally. That is fine with me, since the captions will stay with the image where they belong.

one size fits all

All methods and tricks described above will produce a simple layout that is essentially single-column, or at least it doesn't force fixed and permanent multi-column layout. The menu list produces a second column, possibly overlapping the content, but only temporary. Images sitting next to each other will align vertically when conditions require. Wide images will shrink with the window if needed. Paragraph text (I didn't mention it yet) has a maximum width but not a minimum, so it will reflow on smaller windows.

For a smartphone with its small high resolution display such flexibility is preemptive for readable presentation. But it is not complete yet. An essential line in the head of the HTML file must tell the browser that this page can be viewed at the native display width. The line is:

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

In the absence of this line, the smartphone browser will likely display the page at a much larger virtual viewport, with the effect that font size becomes minuscule beyond readability. Unless the user explicitly told the browser to not use a wide viewport. But that is not recommended because the browser would then try to squeeze multi-column layouts on the small display with sometimes not more than a single word per line. You could try that for fun in the browser settings.

my linux page