Categories
Uncategorized

Javascript Godies: Intl.DisplayNames

There are times when our applications need to reference information such as languages, regions, scripts, and currencies. Some of these may be easier and some may be hard but either way, we shouldn’t hardcode them into the apps themselves, this makes them brittle and harder to localize.

Rather than download a fresh copy of the locale data every time there is a change, we can leverage the versions available in JavaScript runtimes. The Intl.DisplayNames API gives JavaScript developers direct access to those translations, allowing applications to more easily display localized names.

The following example creates four constants reflecting the languages, regions, scripts, and currency as used in Chile (es-cl as the first parameter to DisplayNames).

const LanguageNames = new Intl.DisplayNames(['es-cl'], { type: 'language' });
const RegionNames = new Intl.DisplayNames(['es-cl'], { type: 'region' });
const ScriptNames = new Intl.DisplayNames(['es-cl'], { type: 'script' });
const CurrencyNames = new Intl.DisplayNames(['es-cl'], {type: 'currency'});

We then use the constants to query the CLDR data based on our locale.

The values that we use for each type of query are different:

The first group of examples queries the names of the languages.

LanguageNames.of('fr');
"francés"

LanguageNames.of('es-es');
"español de España"

LanguageNames.of('JPN');
"japonés"

LanguageNames.of('zho');
"chino"

Same with the name of regions and countries. Some regions don’t appear in the listings for region names and where they appear they don’t work with the code.

RegionNames.of('UK');
"Reino Unido"

RegionNames.of('DE');
"Alemania"

RegionNames.of('EU');
"Unión Europea"

The currency values are, to me, the most confusing as they use only the first two letters of the country and then the name of the currency itself, which is not an intuitive name if you don’t look at the table.

CurrencyNames.of('JPY');
"yen"

CurrencyNames.of('clp');
"Peso Chileno"

CurrencyNames.of('GBP')
"libra esterlina"

CurrencyNames.of('USD');
"dólar estadounidense"

CurrencyNames.of('CNY');
"yuan"

The names for scripts and languages are a little more complicated. The names of the scripts/languages are not as intuitive as the names of languages or regions and not all regions have names available to us.

Entering an unknown script name will return either the string you entered or a syntax error when you use them.

ScriptNames.of('Latn');
"latino"

ScriptNames.of('Cyrl');
"cirílico"

ScriptNames.of('Arab');
"árabe"

ScriptNames.of('Kana');
"katakana"

This gives you a lot of flexibility when building multilingual applications. I need to fully learn how to use it but even as I stumble along, the possibilities for international e-commerce sites are awesome.

Links

Categories
Uncategorized

Rivendellweb Theme: Work So far

This is my first attempt in a while to create a fully customized WordPress theme without using Genesis or other theme frameworks. The idea is to use modern web technologies like CSS Grid, Variable Fonts and others to experiment with what it takes to add these technologies to a WordPress theme using Underscores as the starter theme.

It is also a playground for working with progressive enhancement, responsive design and how to accommodate multiple screen sizes in the same WordPress theme.

Some aspects that I think are important to highlight and also some areas where further work is needed.

Variable Fonts

The theme uses a single variable font, Recursive for everything from monospaced code examples to the casual font face used for the title header and everything in between, replacing 6 font files with a single 523KB WOFF2 one.

Yes, it’s over 500KB of fonts, but we’ve taken care of not interrupting the page loading experience by using several tools and techniques:

  • subsetting the font using [Glyphhanger](https://www.filamentgroup.com/lab/glyphhanger
  • Using Font Face Observer to add classes based on font loading results
  • Use font-display to swap the font in after it has finished loading.

To make everything work in WordPress we need to:

  • Enqueue the font or load it a local CSS stylesheet
  • Enqueue FontFace Observer
  • wrap the inline script that uses Fontface Observer in a PHP function and then use add_action to add the script to the footer of all documents.

The process is documented in Using Variable Fonts in a WordPress theme

The biggest disadvantage of variable fonts is that they require fairly recent browsers and operating systems to work so they must be treated as an enhancement and alternative fonts must be built into the stacks, preferably fonts that are close in size so that the text will not shift too much when the web font loads.

Another disadvantage is that, as I write this, Recursive is still in beta and there will be several more releases before it is deemed ready for production. I will continue to track the changes and will update the font when needed.

Adapting third-party libraries to use variable fonts

As documented in Modifying Prism.js to use a variable font I’ve tweaked the Prism.js CSS stylesheet to also use Recursive and its MONO axis

Yes, this ties me down to a specific version of Prism but, unless there are major changes in the Prism codebase or they add a new language that I must have, eliminating another potential font download is worth the effort.

Grid

One of the earliest decisions I made was to use CSS Grid for the layout and it works amazingly well.

Theme Structure

I have added the minimum necessary to make the theme work as designed. It usually involves adding styles, adding templates or modifying existing templates.

I’ve also used the WordPress Unit Test Data to validate that the content works as intended with as many types of content available on WordPress as possible.

To Gutenberg or not to Gutenberg

I’ve struggled with supporting Gutenberg on my theme or not until I realized that it doesn’t matter what I choose, it’s the people using the theme that get to choose whether to use it or not.

Header

The header uses the following items:

The custom logo and menu are conditional. If the corresponding setting on the appearance admin menu is not selected, then it will not appear in the front end.

Content

Content is pretty much untouched from the original Underscores sources.

There are a few edge cases that I need to address like full-bleed images in a grid when they are not direct children of the grid element but they don’t seem to impact the code appearance or the readability of the content itself.

Footer

The footer area uses two widget areas laid out using flexbox rows. Each area is also a flexbox laid using columns.

This may be more work than what’s needed but it gives me the flexibility to add multiple widgets in whatever order I choose.

Javascript build system

I’ve adopted a build system I originally crafted for SASS-based workflows. It works but SASS itself is starting to not support the workflows I’ve been using for a while.

There are other libraries that I’m evaluating as potential replacements for SASS and they would require minimal effort as far as the build system is concerned.

See PostCSS deep dive

Javascript still runs through Babel but some code still depends on jQuery to work. jQuery is useful but it takes away a lot of the newer functionality available to Javascript.

So one thing I may evaluate going forward is whether the tradeoff between browser support and language features is worth it.

Some things still outstanding

Some things I’m thinking about and considering as I move forward completing the theme. Some of these things are nice to have while others are things I’ve never attempted before when working on a theme.

Full-bleed figures

Full bleed images, with or without captions, are one of the few things that don’t work.

I’m researching what it would take to fix the issue.

jQuery or Javascript

Evaluate if the tradeoff between Javascript features and browser support is worth it, particularly in light that some features already require modern browsers and operating systems.

Plugging things to the customizer

Right now the theme and the customizer have little or no relationship. One of the next tasks is to figure out how to hook the theme into the customizer.

We do this to make sure that users don’t need to tweak the HTML/PHP and CSS directly.

AMP compatibility

What, if anything, we need to do to make sure the site is AMP-ready?

Credits

Categories
Uncategorized

WordPress conditional tags

One of the things I like the most about working with WordPress, although it can be frustrating at times, is the number of conditional tags available. This post will explore what they are, and some examples of how we use them.

What they are

Conditional tags are pre-packaged PHP functions that allow you to customize your WordPress theme based on whether the current item matches a condition or not Conditional Tags usually work with PHP if /else Conditional Statements.

The if/else code checks if a statement is true or false. The example uses the is_single() conditional tag.

If the statement is found to be true, the first set of code is executed and we echo This is a single post!.

If it’s false, we skip the first block of code, and execute the else block and echo This is not a single post! instead.

<?php
if ( is_single() ):
    echo 'This is a single post!';
else:
    echo 'This is not a single post!';
endif;
?>

How do they work?

Expanding on the example in the previous section we can use one or more conditional tags and one or more logical operators in either a template or in a function that hooks to a trigger or action for later execution.

We’ll walk through some examples as a means to explain what they do.

Are we on the home page?

WordPress makes a difference between the front page (the main page of the site) and the main page (the index page for the blog). They may be the same or they may not; in this particular case we only want to output something if the

<?php if ( ( is_front_page() && is_home() ) ) :
  echo "This is front and home page";
  echo "do something cool";
endif
?>

Likewise, WordPress makes conditional tags for different types of content like single posts or pages. The next example will branch out and check if the user is visiting a single post or a page and echo different outputs depending on what we visited.

<?php if ( is_single() ) :
  echo "Visiting Single Post";
elseif ( is_page() ) :
  echo "Visiting Page";
endif;
?>

The final example is to check whether a user is logged in and display different content to them than to anonymous visitors.

<?php if ( is_user_logged_in() ):
  echo "Show secret for logged in users";
else :
  echo "Shhh, user is not logged in!";
endif;
?>

We’ve used echo statements in the example; in real production code, we’d use more complex code, including WordPress specific functions.

The last example will work through actual WordPress code to, hopefully, fully illustrate how conditional tags work.

The code uses conditional tags in two places:

  1. The first one is to check if we’re in the site’s front page and the blog home page (they are the same)
    • IF the condition matches we use h1 for the title
    • If not then we use p elements for the title since we want to style it differently
  2. Check if we have a description of the blog (another name for the tag line) or we’re looking at the customizer view of the page
    • If neither condition are met we don’t show the description
<div class="site-branding">
  <?php the_custom_logo(); ?>
  <?php if ( is_front_page() && is_home() ) : ?> <!-- 1 -->
    <div class="site-branding__text">
      <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>
      <?php
    else :
      ?>
      <p class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></p>
      <?php
    endif;
    $rivendellweb_description = get_bloginfo( 'description', 'display' );
    if ( $rivendellweb_description || is_customize_preview() ) :
      ?> <!-- 2 -->
      <p class="site-description"><?php echo $rivendellweb_description; /* WPCS: xss ok. */ ?></p>
    <?php endif; ?>
  </div> <!-- .site-branding__text -->
</div><!-- .site-branding -->

There is a huge number of conditional tags available. If you want to see the full list, check the List of Conditional Tags at wordpress.org.

Links and Resources

Categories
Uncategorized

Animating variable fonts

One of the things I find the most interesting about variable fonts is that you can animate them between different values.

This post will explore how to create animations using Variable font axes, both default axes like weight and custom axes like casual available in Recursive

I will be using the following HTML:

<h1 class="weight">Hello World</h1>

<h1 class="casual">Hello World</h1>

The CSS is broken in multiple blocks for readability and ease of explanations.

The first block performs the following tasks

  1. Load the variable font using a modified @font-face syntax
    • The format for the font changes to reflect that it’s a variable font
    • We repeat the URL to accommodate two values for the format attribute
    • font-weight takes two values representing the boundary values for the attribute
  2. Define the default values for the variable fonts in the :root attribute. We use :root rather than html because :root has a higher specificity
  3. Add a set of default attributes to the universal selector. This will match all elements on the page so we don’t have to add them individually to all elements
  4. We add padding to the HTML and enlarge h1 elements
@font-face {
  font-family: "Recursive VF"; <!-- 1 -->
  src:  url("fonts/recursive.woff2") format("woff2 supports variations"),
        url("fonts/recursive.woff2") format("woff2-variations");
  font-weight: 300 1000;
  font-display: swap;
}
:root { <!-- 2 -->
  --recursive-mono: 0;
  --recursive-casual: 0;
  --recursive-weight: 400;
  --recursive-slant: 0;
  --recursive-italic: 0.5;
}

* {
  font-family: "Recursive VF", Verdana, sans-serif; <!-- 3 -->
  font-weight: var(--recursive-weight);
  font-variation-settings:
    "MONO" var(--recursive-mono),
    "CASL" var(--recursive-casual),
    "slnt" var(--recursive-slant),
    "ital" var(--recursive-italic);
}

body { <!-- 4 -->
  padding: 2em;
}

h1 { <!-- 4 -->
  font-size: 3em;
}

Then for each animation, we need to do two things:

  1. Define the animation using the animation using either the shorthand or individual attributes
    • Both examples use the shorthand syntax
  2. Create the keyframes sets using the @keyframes at-rule
    • The name must match the animation property defined in the previous step
.weight {
  opacity: 0;
  animation: weightAnim linear 2s forwards; /* 1 */
}

@keyframes weightAnim { /* 2 */
  from {
    opacity: 0;
  }
  to {
    font-weight: 1000;
    opacity: 1;
  }
}
.casual {
  animation: casualAnim linear 4s forwards; /* 1 */
}

@keyframes casualAnim { /* 2 */
  from {
    font-variation-settings: "CASL" 0;
  }
  to {
    font-size: 8em;
    font-variation-settings: "CASL" 1;
  }
}

Tools like Splitting.js, Lettering.js or its jQuery-less counterpart (in this Gist) allow for more complex effects targetting portions of a sentence or even individual characters.

See Mandy Michael’s Interactivity and Animation with Variable Fonts for more in-depth coverage of how to animate variable fonts and examples of what this looks like.

Categories
Uncategorized

Using Variable Fonts in a WordPress theme

Variable Fonts give you a lot of flexibility while losing support for older browsers and operating systems. They reduce the number of font files required to render content and they give you options that are difficult or not possible with traditional web fonts.

Quoting Jason Pamental’s The evolution of typography with variable fonts: an introduction:

As described by John Hudson, a variable font is a single font that acts as many: all the variations of width and weight, slant, and even italics can be contained in a single, highly efficient and compressible font file. What’s more: the format (which is technically part of the OpenType 1.8 specification) is completely extensible. The type designer has complete control over what axes are used, their ranges, and even the definition of new axes. There are currently 5 ’registered‘ axes (width, weight, slant, italics, and optical sizing), but the designer can vary any axis they choose. Some examples include the height of ascenders and descenders, text grade, even serif shape. The possibilities are nearly limitless.

Why use them

Variable fonts improve performance in several ways. They reduce the number of HTTP connections we have to make for Font assets, it makes the fonts smaller overall (the one file you download may be larger but it’s one as opposed to 4 for each traditional font you work with).

They also allow for things that were very difficult or impossible to do before. We can animate the axes if we set them up properly giving us additional flexibility.

We’ll explore Variable fonts using Recursive as the single font for a WordPress-based site. Along the way, we’ll talk about responsive typography, based on the Work of Jason Pamental, and how to work with older browsers.

Loading variable fonts

WordPress strongly suggests that you enqueue third-party scripts and stylesheets for use with a WordPress theme. However, when creating a theme from scratch we don’t need to enqueue the main stylesheet and that’s where we’ll make all our variable fonts additions.

We’ll cover both methods below.

Modifying an existing theme

Assuming that we’ve created a stylesheet to load the font using @font-face syntax and all the style that override the default font size then all it takes is to enqueue the stylesheet.

We’ve discussed how to enqueue local stylesheets so I won’t go into details about how the code below works, I’ll just show the end product.

function rivendellweb_enqueue_local_fonts() {
    wp_enqueue_style( 'local_styles',
            get_stylesheet_directory_uri() . '/css/recursive-styles.css' );
}
add_action( 'wp_enqueue_scripts', 'rivendellweb_enqueue_local_fonts' );

From Scratch

When building a theme from scratch the rules change slightly. We’re not adding new resources to the theme but we’re changing the existing CSS to match our design.

There is no enqueueing necessary as we’re working with the default styles for the theme. We’ll look at how to do it in the next section.

Example: Recursive Font from scratch

The following code will build a responsive-typography stylesheet using Recursive.

We first load the font using the @font-face rule with some changes to accommodate the variable fonts.

We use two different formats to support different syntaxes for the format for the attribute.

Attributes like font-weight, font-style and font-stretch take two values indicating the lower and upper boundaries for the particular axis.

Finally, we use font-display: swap to tell the browser to swap the font once it’s loaded.

@font-face {
  font-family: "Recursive VF";
  src:
    url('./fonts/recursive.woff2') format('woff2 supports variations'),
    url('./fonts/recursive.woff2') format('woff2-variations');
    font-weight: 300 1000;
    font-display: swap;
}

The next block defines variables with the default values for each of the axes that the font makes available. We’ll make extensive use of these variables elsewhere in the document.

:root {
  --recursive-mono: 0;
  --recursive-casual: 0;
  --recursive-weight: 400;
  --recursive-slant: 0;
  --recursive-italic: 0.5;
}

This default selector adds the default font family and default values using the variables defined in the previous block.

font-variation-settings allows you to add the custom axes with variables.

The uppercase axes, MONO and CASL, are custom axes that will only work with Recursive.

The lowercase axes, slnt and ital are predefined axes. The reason why we don’t use the equivalent CSS property is that they both match the same property so we’d have to use either one but we can’t use them together.

* {
  font-family:  "Recursive VF",
                Verdana,
                sans-serif;
  font-weight: var(--recursive-weight);
  font-variation-settings:
    "MONO" var(--recursive-mono),
    "CASL" var(--recursive-casual),
    "slnt" var(--recursive-slant),
    "ital" var(--recursive-italic);
}

The rest of the code in this post is taken and adapted from FF Meta Variable Font Demo, a pen from Jason Pamental.

We first add another :root block with CSS Custom Properties / Variables too define the values that we want to work with.

This is a simplified version that considers only p and h1 elements. The full version has additional entries for h2 through h4.

This code only deals with font size, line height, and their relationship when the screen size changes using media queries. It also takes advantage of Fontface Observer to add styles for when the font fails to load.

:root {
  /* Breakpoint variables */
  --bp-small: 24.15;
  --bp-medium: 43.75;
  --bp-large: 60.25;
  --bp-xlarge: 75;
  /* Paragraph variables */
  --p-line-height-min: 1.25;
  --p-line-height-max: 1.4;
  --p-font-size-min: 1.0;
  --p-font-size-max: 1.25;
  /* H1 variables */
  --h1-line-height-min: 1.1;
  --h1-line-height-max: 1.1;
  --h1-font-size-min: 2.5;
  --h1-font-size-max: 4;
  --h1-vf-wght-multiplier-s: 0.75;
  --h1-vf-wght-multiplier-m: 0.75;
  --h1-vf-wght-multiplier-l: 0.75;
}

The default rule for paragraphs sets the size to 16px, the font size to 400 and the line-height to 1.

All the media queries play with what values to use and how to combine them.

p, li {
  font-size: calc( var(--p-font-size-min) * 1rem );
  font-weight: var(--recursive-weight);
  line-height: var(--p-line-height-min);
}
@media screen and (min-width: 24.15em) {
  p, li {
    line-height: calc(( var(--p-line-height-min) * 1em ) + ( var(--p-line-height-max) - var(--p-line-height-min) ) * ((100vw - ( var(--bp-small) * 1em )) / ( var(--bp-large) - var(--bp-small) )));
  }
}
@media (min-width: 60.25em) {
  p, li {
    font-size: calc(( var(--p-font-size-min) * 1em ) + ( var(--p-font-size-max) - var(--p-font-size-min) ) * ((100vw - ( var(--bp-large) * 1em )) / ( var(--bp-xlarge) - var(--bp-large) )));
    line-height: var(--p-line-height-max);
  }
}
@media (min-width: 75em) {
  p, li {
    font-size: calc( var(--p-font-size-max) * 1em );
  }
}

We do something similar with h1 with the corresponding h1 variables and one additional change.

We leverage the .fonts-failed class generated by FontFace Observer and style elements when our variable font is not available.

h1 {
  font-weight: calc( var(--recursive-weight) * var(--h1-vf-wght-multiplier-s) );
  font-size: calc( var(--h1-font-size-min) * 1em );
  font-style: normal;
  line-height: var(--h1-line-height-min);
}
.fonts-failed h1 {
  font-family:  Georgia,
                "New Times Roman",
                serif;
  margin: 2em 0;
  letter-spacing: -.5px;
}
@media screen and (min-width: 24.15em) {
  h1 {
    line-height: calc(( var(--h1-line-height-min) * 1em ) +
      ( var(--h1-line-height-max) - var(--h1-line-height-min) ) * ((100vw - ( var(--bp-small) * 1em )) / ( var(--bp-xlarge) - var(--bp-small) )));
    font-size: calc(( var(--h1-font-size-min) * 1em ) + ( var(--h1-font-size-max) - var(--h1-font-size-min) ) * ((100vw - ( var(--bp-small) * 1em )) / ( var(--bp-xlarge) - var(--bp-small) )));
  }
}
@media screen and (min-width: 43.75em) {
  h1 {
    font-weight: calc( var(--recursive-weight) * var(--h1-vf-wght-multiplier-m) );
  }
  .fonts-failed h1 {
    letter-spacing: normal;
  }
}
@media (min-width: 75em) {
  h1 {
    font-size: calc( var(--h1-font-size-max) * 1em );
    font-weight: calc( var(--recursive-weight) * var(--h1-vf-wght-multiplier-l) );
    line-height: var(--h1-line-height-max);
  }
  .fonts-failed h1 {
    letter-spacing: -1px;
  }
}

Yes, this is a lot of code but it will keep text readable and easy to change. Whenever we need to change something, we change the corresponding variables at the top.

One of the Recursive font’s custom axes is Casual. I use it to create distinctive headers in combination with both Slant and Italic axes.

The code looks something like this:

h1.casual {
  --recursive-casual: 1;
  --recursive-slant: -15;
  --recursive-italic: 1;
}

We’ve done the same thing with styles. This is the modified styles for Prism.js used on my project.

We change the font to monospaced and add slashed 0 to fully distinguish them from lowercase and uppercase o.

code[class*="language-"],
pre[class*="language-"] {
    --recursive-mono: 1;
    --recursive-zero: "zero" on;
    color: #657b83;
    font-family:  "Recursive VF",
                Consolas, Monaco,
                'Andale Mono',
                'Ubuntu Mono',
                monospace;
    font-size: 1.1em;
    text-align: left;
    white-space: pre;
    word-spacing: normal;
    word-break: normal;
    word-wrap: normal;
    line-height: 1.5;
    tab-size: 4;
    hyphens: none;
}