Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
Theme four-point-nine
The default theme for 4.9 needed updating to reflect the new image generation system, so I thought I’d give it a go.
My approach is one-size-fits-all, and provides a range of sizes for the browser to choose from (it uses sizes="auto").
A bunch of template suggestions followed:
Pages and Forms
The default and archive pages are somewhat daunting or complex for newbies, so I simplified them by creating 2 new forms (misc/head.txp and misc/pagination.txp). This reduced the pages considerably, but there is still more that can be done eg. the <body> tag variants are a candidate for another form. Is <txp:if_author> et.al used enough to warrant so many lines throughout the default templates? I’d like to see a peppering of some of the more recent/useful tags and attributes e.g. <txp:yield />. Maybe we could treat default.txp as only-the-basics, with archive.txp as the page with bells and whistles?
I added an image capability to article_listing.txp, and made minor formatting changes throughout – typically using wraptag="foo" to replace surrounding tags where possible to reduce the line count, and moving html comments so that they are within a <txp:if_etc> tag so they display if required.
Style
The css in the four-point-nine install is compressed, making it difficult to edit. I’m recommending new styling which still presents the site as a wireframe, but allows the user to control aspects via css variables at the top of the file, or dig deeper to make changes to components etc. lower down.

Offline
Re: Theme four-point-nine
Happy New Year Gary! You’re making a good start already! Just a brief answer for now as I’m short on time. I’ve only taken a quick look at your commits for now but I like your general approach. Things like excerpting css variables I think are a great idea. Users can then add own stylesheets in the presentations tab and set their own css variables or add extra css, potentially transforming the basic framework (4.9 adds some other ways of bringing in css from Textpattern’s styles panel as inline content). I see various other simplifications in your commits, and some more segmentation into forms, which I agree aids readability. Ditto wraptag to avoid if_conditionals.
A more general aspect: as informative as schema.org structured data can be, I find it clouds the readability of the demo theme, even to the point of causing roundabout constructions that would not be necessary if one didn’t have to cater for the extra attributes. I absolutely see its purpose for complex sites and markup patterns that html does not already cater for, or for types of site with particular content patterns (and then arguably the json-ld method could end up being more concise), but the demo theme is not that complex in terms of content and my personal feeling is that search machines aren’t going to have difficulties processing the demo site. In short, the principle is great, but how much extra search-machine clarity does it actually bring in this demo case? Maybe this is just a gripe of mine?
For example:
<p itemprop="image" itemscope itemtype="https://schema.org/ImageObject">
<txp:variable name="img-tag" />
</p>
denotes that it is an image?! … which the img tag already does on its own. Also, is it still important to differentiate between images with and without a caption? MDN suggests not, expressly calling figure a figure with optional caption element and shows a Just an image example. The validator doesn’t seem to complain, either, if a figcaption is not included.
Might there also be a less nested way of handling the multiple if_… situations? I suppose it does demonstrate the conditional tags, but even with experience, I have to read it carefully to follow. Oleg showedan alternative pattern. If I have site that needs this more than once, I do the nesting dance once and define a page_context variable that can I use in the rest of the templates.
Overall nice ideas in there. I imagine the toned-down styling will be polarising, but I like it. Maybe some style variants would illustrate the potential of the css custom properties?
When I have more time, I’ll give it a proper tryout.
TXP Builders – finely-crafted code, design and txp
Offline
Re: Theme four-point-nine
Fab start! The default theme defintely needs some consolidation, and I love the idea of using CSS variables to show off the customisation opportunities. And yeah, auto thumbs…
Currently, sadly, the thumbnail tags need height="0" to prevent them automatically creating weirdly tall images (without CSS to tame them) but I’m hoping this can be addressed in a few weeks in a maintenance release 4.9.1 to also catch a few stray edge case bugs. Hopefully I can get my head round a way to retain the thumbnail tag’s broadly backwards-compatible nature (which it is now) but also less wordy (which it certainly isn’t now).
So if we can iterate this idea for the default theme, I’m all for including it in 4.9.1.
The microformats do seem over the top. Not just in our theme, but in general. schema.org is way way waaaay too prescriptive and, as Jools says, a lot of it is completely unnecessary if using descriptive HTML5 tags. I’d love to hack some of it out. Yes, keep the “BlogPosting” stuff perhaps because div and section tags need a little hinting. But definitely slim it down.
I would actually like to take this opportunity to showcase the tag processing order – although I’m not sure how intuitive it is in a default theme – to actually ditch the wordy inline microformats and use JSON-LD. There’s a whole discussion on it and the consensus seems to be that the JSON-LD structure can be built by peppering <txp:variable name="json-ld" add> containers (see Jools’ comment and my reply) throughout the template and then using <txp:variable[-1] name="json-ld" /> to output the entire structure in the <head> tag, utilising secondpass to add it after the variable has been constructed (even though it is output before them all in the source code). It’s clever and shows off how powerful the tag processor is, and also simplifies the template.
Thoughts on this welcome. But yes, definitely a fantastic step up. Thank you, Gary (and Happy New Year).
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Hire Txp Builders – finely-crafted code, design and Txp
Offline
Re: Theme four-point-nine
(HNY :)
Thanks!
I need to first grok/experiment-with the logic of the alternative and Jool’s comment approaches — I’ve never understood (and have consequently shied away from) the ‘shift’ attribute. In the past my method of determining whether it’s the homepage has been <txp:if_section name=", default">. Tag-processing-order is also new to me ;-)
I too dislike the clutter and redundancy of much microdata. I’ll attempt a cleanup, lowest hanging fruit first… Maybe we should change it from “BlogPosting” to “Article”.
Offline
Re: Theme four-point-nine
I still use <txp:if_section name=""> to check for front-page, so you’re not alone.
And sure, if Article makes more sense as a microformat type, then that’s cool with me.
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Hire Txp Builders – finely-crafted code, design and Txp
Offline
Re: Theme four-point-nine
Updated images.txp
<figure>
<img srcset="<txp:image_url thumbnail width="320" /> 320w,
<txp:image_url thumbnail width="640" /> 640w,
<txp:image_url thumbnail width="1280" /> 1280w,
<txp:image_url thumbnail width="2560" /> 2560w"
sizes="auto"
width="<txp:image_info type="w" />"
height="<txp:image_info type="h" />"
loading="lazy"
alt="<txp:image_info type='alt' default='<txp:image_info type='name' />' />"
/>
<txp:if_individual_article>
<txp:evaluate>
<figcaption itemprop="caption">
<!-- image_info without a type attribute outputs the caption -->
<txp:image_info escape="textile"/>
</figcaption>
</txp:evaluate>
</txp:if_individual_article>
</figure>
I removed the microdata (including the <meta height/width lines – redundant as we’re specifying the width and height in the <img> tag itself – recommended to prevent CLS). The fallback for the alt description is now the image name.
I’m unsure about the ::if_individual_article tag, but I’ve regularly found the need to omit captions on landing pages.
As images are such an integral part of a modern website, would it be worth while abstracting it all into a <txp::images /> (or <txp::figure />) shortcode so some yield functionality can be exposed? Scope-creep? Maybe just use an evaluate block on the caption?
JSON_LD scripts can be placed in the head or body, so they could be included here directly or as a shortcode within a <txp:hide> block. Showcasing another tag :)
Last edited by giz (2026-01-03 19:39:09)
Offline
Re: Theme four-point-nine
Update
To get green ticks from evaluation tools like WAVE I needed to enforce the order of the heading tags appearing on any page, hence heading sizes became difficult to control cohesively. I resolved this by specifying heading sizes as:
h1,
.h1-style {
font-size: var(--h1);
}
h2,
.h2-style {
font-size: var(--h2);
}
// etc
While this allows easy sizing control of elements (not just headings) by the user, it does require the classes to be added to the markup which is a pity. If anyone has suggestions of a cleaner/simpler way of doing this without writing reams of css, I’m all ears.
Schema
I removed some duplication from the head by creating a JSON schema-shortcode that currently only handles the basics, but could be extended to generate any schema.
<txp::schema type="WebPage" url='<txp:section url escape="json" />' headline='<txp:section title escape="json" />' /> used as required in the head’s if-this-then-that dance.
- Maintain a minimal schema in the head as above, and maintain all the current schema-related snippets throughout the templates, but take the hit with (human!) code legibility
- Move all schema info to the head (or end of the body tag), leaving the templates much cleaner, albeit with the odd schema shortcode added in relevant places. Dumb, as we’re effectively duplicating the content on each page… and all that extra processing.
- Maintain a minimal schema in the head only, and be hard-assed by omitting most schema snippets (with the exception of the actually useful schemas like
itemprop="description"anditemprop="articleBody") so the reliance is on semantic html instead.
Is the web progressively opting out of semantic html in favour of unnecessary schema glut?
if-this-then-that
I can’t see any way past the need to have many <txp:if_blah><txp:else /></txp:if_blah> statements scattered in various places in the code. Any approach which attempts to centralise this logic would be complex (and not as easy to read). Multiple nested logic statements may be long-winded, but they are easy to understand. I’ve always felt that one of Textpattern’s strengths is the way you don’t need to comment much in the code; it reads like English :)
The if-this-then-that in the head for canonical/robots/etc metas should act as an example for users to use everywhere, so we have an opportunity to make it as performant and easy to understand as possible. I’ll try changing the current
<txp:if_search>
// not used often
<txp:else />
<txp:if_author>
// not used often
<txp:else />
// most commonly used
// most code lives here
</txp:if_author>
</txp:if_search>
with <txp:if_article_list type="author, c, month, pg, q"> variants. I’m a little concerned that it won’t read as clearly…
style
jakob wrote #342071:
Maybe some style variants would illustrate the potential of the css custom properties?
I’m busy on a couple of variants. ‘Soon’.
(As a diversion from doing actual work :) I built a css-variable configurator html page which allows you to adjust the variables and see your changes reflected adjacent in an iframe. It helps immensely in illustrating whats going on, so I’ll publish it so you can have a play.
Offline
Re: Theme four-point-nine
Wow, that’s amazing stuff. Thank you.
Regarding schema, if we can swap any divs and non-semantic tags for semantic counterparts like nav and section and article, it should help remove the need for overly prescriptive schema markup. But I guess in some places it’s unavoidable; at least in places where computers need a helping hand to grasp the context. For all other places, I’m fine with the hard ass approach.
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Hire Txp Builders – finely-crafted code, design and Txp
Offline
Re: Theme four-point-nine
Nice!
Headings
Yes! I usually just have .h2, .h3, etc. or specific role headings like .page-title, .section-title (meaning in a <section /> tag) or .sidebar-title …
Schema
I’d also be for v2 or v3 with props only included if the semantic tags don’t provide sufficient indication and where it’s not explicit (like a div in an article) then where its role could be misconstrued. It’d be good to have a modicum of json-ld in the head to illustrate the principle.
if-this-then-that
I get what you mean. Maybe you’re right. What l’ll do if a site looks like it will need multiple such if-cascades is to set some “page environment variables” at the top of the page (usually in a head_vars form loaded at the top of the head block):
<txp:hide process>
++++ variable: page_context = current page view ++++
<txp:if_search>
<txp:variable name="page_context">search</txp:variable>
<txp:else />
<txp:if_author>
<txp:variable name="page_context">author</txp:variable>
<txp:else />
<txp:if_category>
<txp:variable name="page_context">category</txp:variable>
<txp:else />
<txp:if_section name="default">
<txp:variable name="page_context">home</txp:variable>
<txp:else />
<txp:if_article_list>
<txp:variable name="page_context">listing</txp:variable>
<txp:else />
<txp:variable name="page_context">article</txp:variable>
</txp:if_article_list>
</txp:if_section>
</txp:if_category>
</txp:if_author>
</txp:if_search>
++++ variable: page = current paginated page ++++
<txp:variable name="page"><txp:page_url type="pg" /></txp:variable>
++++ variable: page_context_paged = landing-page / sub-page ++++
<txp:variable name="page_context_paged"></txp:variable>
<txp:if_variable name="page">
<txp:if_variable name="page" value="1">
<txp:variable name="page_context_paged">landing</txp:variable>
<txp:else />
<txp:variable name="page_context_paged">sub</txp:variable>
</txp:if_variable>
</txp:if_variable>
</txp:hide>
The principle can be pruned or extended as needed. With <txp:hide process> … </txp:hide> you get the variables without any page output, so you can write comments freely without having comments appearing on the page.
You can then use the resulting variable in your forms to do:
<txp:if_variable name="page_context" value="home">
<!-- the home page -->
</txp:variable>
<txp:if_variable name="page_context" match="any" value="search, author, category, listing">
<!-- a page with a list of articles -->
</txp:variable>
<txp:if_variable name="page_context_paged" value="landing">
<!-- only show this on the first page of a section with multiple sub-pages -->
</txp:variable>
and so on…
Sure, it duplicates some of the core tags in individual use cases, but as a variable you can test for multiple page contexts using match="any". It also means you can define other content or variables that are dependent on context in-place rather than having to track down where you set them earlier in a huge if-cascade.
TXP Builders – finely-crafted code, design and txp
Offline
#10 Today 11:40:56
Re: Theme four-point-nine
jakob wrote #342200:
as a variable you can test for multiple page contexts using
match="any".
That’s clever, and helpful in many cases. Nicely extensible too, as you say. I do that sometimes.
But in other cases, there’s no getting away from the fact it’s nice to separate out the pathways because <txp:if_search> and <txp:if_category> etc trigger very specific behaviours like populating search_results tags that you’d explicitly need to check or wrap in <txp:evaluate> to determine if the context applied.
I don’t mind a bit of nesting if I confine all such processing to the default page template. As giz says, it reads as English: if search, do this, otherwise if category, otherwise if author, …
Then for regular list/landing/individual article handling, a second page template can be much simpler without all the extra context checks.
Bear in mind also that they don’t technically need nesting. It’s a tiny bit less efficient but:
<txp:if_search>
<h2>Search results for <txp:search_term /></h2>
</txp:if_search>
<txp:if_category>
<h2>Articles in category <txp:category title /></h2>
</txp:if_category>
<txp:if_author>
<h2>Articles by author <txp:author title /></h2>
</txp:if_author>
<txp:article listform="context_listing" />
will work equally well and only trigger one of the conditionals at a time. And if you want to display different results such as <txp:search_results> then you can put that in the search block and move the article tag into each of the other two blocks.
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Hire Txp Builders – finely-crafted code, design and Txp
Offline