NOTE: There is a video version of this tutorial on the bottom of the article.
As part of refactoring/redesigning the website for a university department, I am building a design system that will help the editorial team manage the website content and layouts and better communicate how the website should work visually, semantically, and functionally. In addition to this, I have recently posted a poll in the GeneratePress Community FaceBook group as to what would be most interesting to make tutorials about. The Design System in GeneratePress and GenerateBlocks option won by a landslide. As any design system is too complex to describe in a single post, I will break this into chapters. This first chapter is about the Global Colors and Typographic Scale in GeneratePress.
I plan to do this as an iterative process where design and development feed off each other. I have built some components, set the typographic scales for desktop and touch, and made several page layouts in Figma. I now have enough design problems solved to begin development and build a minimum viable solution (MVP ha-ha). In future iterations, I will add more features and details. A big challenge for me in this process is the lack of solid design restrictions in the WordPress block editor, but I think there is enough to satisfy some basic needs.
The global colors
I have defined 5 colors in my color palette section within the Figma file. This translates nicely to the GeneratePress customizer color section. However, I want my names to be:
- primary-dark
- primary-light
- secondary-dark
- secondary-light
- accent
while GeneratePress names their colors:
- contrast
- contrast-2
- base
- base-2
- accent
- …
How to change this so that my color names make sense to me? 🙂 Luckily, Tom Usborne has us covered. The following function creates new CSS variables and assigns them desired values.
Setting the custom color palette with a custom naming.
The results of this function are visible in the customizer like so.
Setting the new defaults for the color picker UI
However, when applying the colors to various site elements, there is one tweak one would still want so that the thing works as it works with the default names.
When we choose a property of an element, for example, an “Entry meta” text color, click on the button with the label “Default”, the color that gets applied is a GeneratePress default “contrast-2” color. This is unfortunate, but the same as above, GeneratePress has us covered.
Here we can set the desired CSS variable for every element in the customizer to what you want it to be. With this, we have achieved the desired result, the colors in the color palette now have custom names and values, and they are set to be the defaults, so customizer functionality is not lost.
Typographic scale
Design decisions
For my typographic styles, I have made several decisions. We will be using only one font family, and we will use only the “normal” width or the 400, with its cursive companion 400i. We are using the Work Sans typeface provided by Google, and this typeface looks most expressive in this width. Adding more widths would hinder its style. Following this, a decision was made to use a strongly contrasted typographic scale to make up for the single-width system. I opted for the “perfect fourth” ratio of 1.333 for the desktop design and a “major third” with a more subtle ratio of 1.250. Small screens do not fare well with strong contrasts. I will be using the same type scale for both mobile and tablet designs because the tablet will simply use two of the columns present in mobile, essentially providing the same space for type columns.
WordPress setup
I am enqueuing the fonts from a local directory in the child theme for performance and privacy reasons, as a recent legal case has shown Google fonts are used by Google to track your users. To achieve this I made a dedicated stylesheet called “typography.css” which is enqueued both in the front side and in the block editor to achieve the same style in both views. I decided not to upload fonts via the media manager, because fonts are an essential part of the site design and should not be accessible to all editors of the site. Other than that I followed the guidelines provided by GeneratePress.
Once we have done this, we can choose the local version of the font in the customizer for the front end, and add .editor-styles-wrapper { font-family: “Work Sans”, sans-serif;} to the “typography.css” file to have the typeface render in the editor too.
Setting up the non-flexible type sizes
I like to start with the standard type sizes for two reasons. One, it is easier for me to work “around” these values when I set the fixed sizes first and two, it provides a fallback for older browsers that do not yet support the clamp() function, or the flexible type feature. To set up the static font sizes we will use the REM values based on 16px base size.
A web app, aptly called Type Scale provides a simple visual interface to set and see the type-scale one may want to use. I like to use this for my designs. The interface does all the calculations in a click and provides both the preview and the values for the font-size property for your site. From here on, we can simply apply the REM values from the web app to our Html elements like so.
Wrap the code into @media() for desktop, open another above it for mobile and paste the new values. If this was all we wanted, we might as well have done it the customizer right?
Adding “the flexible” in the flexible type scale.
Flexible type can be achieved in multiple ways, but the underlying logic is the same. We want to have the typography change its size according to the size, or width to be more exact, of the browser viewport. The larger the screen, the larger the type should be. In CSS we can achieve this using a unit that is a fraction of a browser viewport width. The viewport-with unit, or VW. The simplest flexible type system would then go something like this.
Combined with the @media() queries this could be a decent solution. However, what we miss there are some guardrails, as well as controls for the pace of size change. The web standard for this is a clamp() function. It takes three parameters, min, optimal, and max using the following syntax.
We now know H1 will never go smaller than 2.75rem and never larger than 3.35rem and it will try to be equal to 1vw while the resulting value is between the min and max values. Usually, though the clamp functions look something like this in practice.
Instead of a simple fraction of browser viewport for the $optimal value, there is a nested calc() function that calculates the max value, viewport width difference, etc. All in all, this one is a bit of a mind twist. 🙂
Responsive font calculator
But there is a web app that can help us construct these clamp functions without much effort.
We simply fill in the fields, choose units and a method and get the CSS code to achieve our responsive/fluid typesetting. Let’s look at a code example that works for me.
I use multiple selectors to enable the same styles for all h1 occurrences: for the front, for the block editor core/heading version, and GenerateBlocks headline version. Then I set the non-flexible size for older browsers that do not understand clamp(), then I use the flexible type definition and finally fix the Safari bug.
The procedure I follow is that the $max size of the h2 is a bit smaller than the $min size of the h1 and I do this for each type size in the type scale. This in turn makes all the type sizes change size proportionally to each other, thus retaining the type-scale ratio.
Finally, I apply vertical spacing to all the content elements. With the exception of <li> (list item) elements, I use the same value for the line height and the margin-bottom property. Worth noting is that the line-height property should always be expressed without the units of measurement, while the margin-bottom should use em units, NOT rem. If done this way both values inherit their flexible values in proportion with the font-size property and scale accordingly.
That’s it. 🚀 🔥 🎉
Thanks for reading.
Oh, and here is the youtube version of this tutorial.