For theme authors
How a theme works with Formulize UI: giving the tokens its values, loading the stylesheet, keeping its own rules from getting in the way of the classes, and framing the page that everything is on.
- Giving the tokens values
- Loading the stylesheet
- Keeping theme rules out of the way
- Framing the page
- Marking the content area
- Printing
Giving the tokens values
Formulize UI sets a neutral default for every token. A theme gives them its own values in a :root rule, and the colours and font set on the Appearance page then override the theme's.
- Set the tokens, rather than restyling the classes: every class is built on them, so the theme's look reaches all of them at once, and the Appearance page keeps working.
- The sizes are in rem, so the browser's font size scales them. Keep a theme's own sizes in rem too.
In the theme's stylesheet
:root {
--fz-color-accent: #0f5e9c;
--fz-color-accent-hover: #0b4a7a;
--fz-color-accent-soft: #e7f0f8;
--fz-font-sans: "Source Sans 3", system-ui, sans-serif;
--fz-radius-lg: 0.25rem;
}Loading the stylesheet
Formulize adds formulize-ui.css to its own pages, with its small script, formulize-ui.js. A theme adds them to every other page by calling formulize_uiStylesheetLink() in its theme.html, before the theme's own stylesheet.
- The function leaves out whatever the page already has, so nothing is loaded twice.
- The script is for browsers that can't yet do everything popovers, menus and dialogs need on their own: in them, it opens dialogs from buttons with
commandfor, and places popovers beside their buttons. In browsers that can, it does nothing. - The order matters:
formulize-ui.cssfirst, then Formulize's own stylesheet, then the theme's. Where a theme rule and a class have the same weight, the theme wins.
In theme.html, in the head
<{php}>
require_once XOOPS_ROOT_PATH . '/modules/formulize/include/functions.php';
echo formulize_uiStylesheetLink();
<{/php}>
<link rel="stylesheet" type="text/css" media="all" href="<{$icms_imageurl}>css/style.css" />Keeping theme rules out of the way
Every public class is a single class selector, with no !important, so a utility or a modifier can always adjust it. A theme keeps that working by not outweighing the classes.
- Give the theme's own classes the theme's prefix, such as
lyris-, neverfz-. - When styling Formulize's own markup, wrap the selector in
:where(), which gives it no weight, so a class added to that markup still wins. - A rule that styles every element of a kind, such as every
buttonor every checkbox, would also restyle the Formulize UI components. Add:where(:not([class*="fz-"]))to it: it skips any element with a Formulize UI class, and adds no weight, so the rule otherwise works as before.
In the theme's stylesheet
/* Formulize's own markup: no weight, so classes added to it still win */
:where(#formulize-list-of-entries) td {
padding: 0.5rem 0.75rem;
}
/* Every button, except the Formulize UI ones */
button:where(:not([class*="fz-"])),
input[type="submit"]:where(:not([class*="fz-"])) {
min-width: 8rem;
border-radius: 0;
}Framing the page
The space at the edges of a page, and how wide a page can get, are the theme's to supply, in one place, for every page. No type of screen brings its own, and what people write for a screen starts at the edge of what the theme gives it.
- Put one wrapper around all of a page's content in
theme.html, and give itpadding: var(--fz-page-padding), the Appearance page's Page padding. Every type of screen then has the same space, including the types added later, and a screen inside another is not inset twice. - To offer the Page width setting, keep the same wrapper to
--formulize-content-max-width. A screen set to the full width has that property at100%on its own page. - Make the wrapper its own element, inside the part of the page that scrolls, and leave the scrolling part without padding.
- Don't put the page's space on the parts of a screen, in screen templates: a screen drawn with other templates would have none.
- On a phone the space can be smaller, and a screen made of bars and cards can run to the edges of the screen, as long as nothing in it touches them.
- The whole of this, with what Lyris does, is in What Formulize expects from a theme, in the documentation.
In theme.html
<main class="mytheme-content">
<div class="mytheme-page">
<{$icms_contents}>
</div>
</main>In the theme's stylesheet
.mytheme-page {
box-sizing: border-box;
max-width: var(--formulize-content-max-width);
margin-inline: auto;
padding: var(--fz-page-padding);
}Marking the content area
A theme puts fz-content on the element around a page's contents, inside its own header, menus and footer. Text there then follows the look's written-content tokens, which the Appearance page's advanced editor sets on its Text page: its running text, and its headings, links, lists, block quotes and separator lines.
| Class | What it does |
|---|---|
fz-content | On the element around a page's contents, such as the one around <{$icms_contents}>. |
- Running text takes its size, line height, font and colour from it, as anything inside does that has none of its own.
- The headings, links, lists, block quotes and separator lines it styles are those with no class of their own. One with a class is part of a component, which has its own styles, so the components are left alone.
- The rules have the weight of an element selector, so a theme's own rule with a class still wins.
- Text in
fz-prosefollows the same tokens, with or withoutfz-contentaround it. - Without it, a theme's text looks as the theme styles it, and the Text page's settings don't reach it.
In theme.html
<main class="my-theme-main">
<div class="my-theme-page fz-content">
<{$icms_contents}>
</div>
</main>Printing
A page can be made for printing with the Print classes, which decide what of the page's own content is on paper. The theme does the rest: on paper it leaves out its own header and menus, and lets the content run on over as many sheets as it needs.
- In an
@media printrule, hide the parts of the theme that are for getting around the site: the header, the menus, the footer. - Anything the theme makes scroll on screen stops at its own bottom edge on paper. Give it
height: autoandoverflow: visiblethere, so it is as tall as what is in it. - Take the space at the edges of the page off as well: the sheet's own margin does that on paper.
- These rules have to win over the theme's own layout whatever it is, so
!importantis at home in them.
In the theme's stylesheet
@media print {
.mytheme-header,
.mytheme-menu,
.mytheme-footer {
display: none !important;
}
.mytheme-content {
height: auto !important;
overflow: visible !important;
padding: 0 !important;
}
}