25 Mar 2024

Wrappers in expandfile

The web page files I write obtain content from a source file that gets headings, navigation, and page layout from a wrapper file. This division accomplishes several goals:

Wrappers

For building medium-sized web sites, a few hundred pages, I use my tool expandfile with wrappers designed for the site to

For example, this structure allowed me to make changes to every HTML page on a site, to add
<meta name="viewport" content="width=device-width, initial-scale=1">
to every page, by editing one wrapper file and recompiling.

Sample HTMX Page Using Wrappers

Consider this example .htmx file:

%[*set,&title,="example page"]%
%[*set,&description,="Page wrappers."]%
%[*include,=htmxlib.htmi]%
%[** Copyright (c) 2018, Tom Van Vleck **]%
%[** ============================================ **]%
%[*block,&body,^ENDBODY$]%

<p>
  This note describes how
  <span class="inred">expandfile</span>
  can be used to separate web page structure from content.
</p>

ENDBODY
%[*include,=example-page-wrapper.htmi]%

Notes

The example above sets three variables, title, description, and body. The lines in pink are regular HTML that will be in the generated page.

The text inside %[** **]% is commentary. There are two comment lines above.

The *include statements insert the contents of other .htmi files.

Sample Wrapper

The wrapper below outputs a whole HTML page, starting with an HTML5 DOCTYPE and a HEAD section with LANG specified, and then a BODY section. (I have capitalized keywords HTML, HEAD, and BODY for clarity: browsers accept either case.)

The HEAD section of the wrapper begins with statements used in every page. The wrapper uses the values of the "title" and "description" variables set in each input .htmx file to create HTML "meta" tags in the output .html file, and also outputs a "meta" tag that sets a viewport so the page looks better on mobile devices. The HEAD section also sets up the CSS definitions for the page, outputting a link to an external style sheet, and then providing some page-local definitions. If an "extrastyle" block was defined, it would be included in the HEAD.

The BODY section of the wrapper can include standard design elements for headings. Wrappers for multicians.org provide dropdown menus, standard breadcrumb navigation, and additional mobile-sensitive code to all pages on the site, as described in Multics Website Features. The DIVs with CLASS "outer", "main", and "tail" can be formatted and positioned by CSS declarations in the page's style sheet.

Here is example-page-wrapper.htmi:

%[** template for an example web page **]%
%[** parameters: **]%
%[**   title        - attribute in head **]%
%[**   description  - in head **]%
%[**   keywords     - in head **]%
%[**  minwidth, maxwidth, contentwidth - from config.txt**]%
%[**    **]%
%[** includes: **]%
%[**   stdfmt.htmi **]%
%[**   textnav.htmi **]%
%[**   addrtag.htmi **]%
%[**    **]%
%[** blocks: **]%
%[**   body       - standard body, can contain vars, macros, etc **]%
%[**   extrabodytag - extra attributes appended to BODY tag **]%
%[**   extrastyle - extra heading stuff, added to head **]%
%[**   extratail  - extra tail links **]%
%[** Copyright (c) 1994-2017, Tom Van Vleck **]%
%[** ================================================================ **]%
<!DOCTYPE html>
<HTML lang="en">
  <HEAD>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>%[title]%</title>
    <meta name="description" content="%[description]%">
    <meta name="keywords" content="%[keywords]%">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="mystyle.css">
%[*include,=stdfmt.htmi]%
    <style type="text/css">
    .outer {
      min-width: %[minwidth]%px; max-width: %[maxwidth]%px;
      width: auto !important; width: %[contentwidth]%px; margin: 0px auto;
    }
    </style>
%[*expand,extrastyle]%
  </HEAD>
  <BODY%[*callv,wrap,extrabodytag,=" ",=""]%> 
    <div class="outer">
      <div class="main">
%[*expand,body]%
        <div class="tail">
%[*expand,extratail]%
          <div class="tailnavbar">
            <div class="textnav">
%[*include,=textnav.htmi]%
            </div> <!-- textnav -->
          </div> <!-- tailnavbar -->
%[*include,=addrtag.htmi]%
        </div> <!-- tail -->
      </div> <!-- main -->
    </div> <!-- outer -->
  </BODY>
</HTML>

The %[*expand,body]% statement will be replaced by the expansion of the user-provided contents of the body block defined in the .htmx file. Variable references in the body block will be further expanded.

Notes

This wrapper is a simplified version of the one I use for multicians.org. It looks for some optional variables that not all .htmx files set, such as extrabody. (Unset variables are replaced by nothing.) The example page does not set these.

Most of the layout options for the generated HTML file come from the common CSS style sheet file mxstyle.css and three include files:

This wrapper looks for some other data items that an .htmx file can define to provide extra per-page features.

CSS Usage

One of the major benefits of the wrapper approach appears when a site's pages use CSS (Cascading Style Sheets) for formatting. (I still have much to learn about CSS -- the features of my pages are ones I've seen on other sites, or read about in how-to articles.)

CSS separates the structure of a page's information from the specs for formatting it. Formatting rules in STYLE sections of the HEAD of a page, and in .css style sheet files included by the page, specify how elements will be arranged and displayed. The rules declare which elements in the BODY they apply to by matching on the declared CLASS and ID of elements, and matching sequences of HTML tags.

The multicians.org wrappers obtain CSS declarations from the wrapper and from files that the wrapper includes; individual HTMX files can contain additional blocks like extrastyle that the wrapper includes if they are found, and these may contain more CSS STYLE tags as well as *include calls that cause more CSS to be included inline. The standard style sheet file mxstyle.css is included by every HTML file on the site, and then those rules are extended or overridden by CSS specs in individual files.

Wrappers encapsulate the CSS solutions for several design issues:

Fluid Design

Fluid design of a web page ensures that visitors' browsers display pages well on screens of various sizes. This goal implies that a page will be readable on a huge monitor as well as a smartphone screen. One part of this approach is to declare the widths of page elements as fractions of screen width, rather than specific counts of pixels. The "outer" and "main" classes in the example above are used in multicians.org's fluid layout.

(Laying out pages using TABLE elements was a fad in the 90s, now deprecated. Among other problems, using tables with a fixed width cuts off content on a screen smaller than the table width.)

Adaptive Design

Adaptive design of a page tells a web browser to switch between different CSS layouts depending on the screen size: a site may use a completely different layout for different screen sizes. For example, the wrappers for multicians.org switch between two different ways of displaying the navigation menus: drop-down menus are only used on large enough screens.

The result of a CSS media query is compared to a configured constant, and one menu presentation is hidden and the other un-hidden depending on the result.

For example, the statements

 .altmenubar {display: none;}
 @media (max-width: 600px) {
   .redmenubar {display: none;}
   .altmenubar {display: block; margin: 9px 5px 0 5px;}
   .main {margin-top: 0; padding: 5px 5px 5px 5px;}
 }

make the altmenubar DIV (normally invisible) visible, and hide the redmenubar DIV, if the screen display is less than 600 CSS pixels wide. The altmenubar DIV is a simple menu without dropdowns that works better on small screens. For narrow screens, the @media section also changes the margins on other DIVs.

Since smartphones don't support HOVER attributes, some adaptive sites change their navigation elements to provide additional methods to find pages for smartphone users. Some sites replace complex menu bars with a "hamburger menu" that opens simpler navigation, when the screen is small.

The "altmenubar" for multicians.org shows only the text "MENU" in a red bar: clicking that text toggles a hidden checkbox, which toggles the hiding/showing of a panel with 27 text links, compared to the 53 links in the JavaScript drop-down menus.

Responsive Design

Responsive design uses newer features of HTML to tell the visitor's browser to request different images depending on the number of pixels available, by using the SRCSET element in an IMG tag. Expandfile macros in htmxlib.htmi generate IMG tags with SRCSET if multiple media sizes are found at compile time.

Responsive Design can also use CSS Media Queries to determine the screen size and to calculate the widths of individual sections and elements.

(see High DPI Pictures.)