The simplest way to use Atlas Themes, is to configure its Theme object to match an existing theme system. This ensures the Gutenberg editor, and the UI that it generates, fits the theme. You can just stop right there, if you want.
But, you can also elect to take advantage of additional features. You can even build your entire website on this theme system alone. Those special features include:
In this chapter, we describe the Atlas philosophy and tools concerning color, typography, and layout.
Graphic designers and web component designers have always needed to work with color tones. The idea is that there are some root colors -- often company brand colors -- with variants needed for things like lighter and darker areas, shading, gradients, or a "dark mode" that keeps the "spirit" of the brand color but tuned for a dark environment.
The naive approach to creating related tones is to adjust the color's "lightness" as defined by the HSL color space. However, if you create lighter and darker colors this way, you'll discover that it is a poor algorithm, especially at the extremes, and especially with certain hues, where the extremes end up just white or black:
Famously, the Google Material Design team created great color swatches for a handful of common colors, and an online tool for creating your own swatches. Compare theirs with the "lightness" algorithm above:
Sadly, a few issues remain. First, why is yellow turning orange when it gets darker? Second, it's great to generate swatches when the colors are known, but what about when the marketer selects an arbitrary color in Gutenberg? Or what about when a new color is automatically selected to support dark mode? Third, these are specific, discrete colors in a "level" range of 50
to 900
, but shouldn't you be able to use any level you want, e.g. 350
or even 286
?
The Atlas swatch system solves all of those issues. Using the same level-numbering system as Material Design, the "main" color is taken to be level 500
, but you can generate any level in the swatch. Here are those same colors using the Atlas swatch system, where you'll note the colors are not "blown out" at the extremes, and yellow remains yellow throughout:
Here are those Atlas swatches again, comparing with the specific levels from Material Design:
Try it for yourself! Pick any color and see what happens:
The Atlas theme and blocks system already uses this internally, but you can access it too. The simplest way is the getSwatchColor()
function which you can import from the root of the core module, or from the specific import as shown below. For example, to get the 650
level for dark blue:
import {getSwatchColor } from '@asmartbear/ gutenberg- bridge/ dist/ themes/ colors' function getDarkerBlue() {return getSwatchColor('#000080', 650)}
Other color utilities can be found in that same color module, such as isLight()
determining whether the color is "light," from an accessiblity standpoint (which is how the text color is selected for the "Custom Swatches" widget above.)
A common color requirement for accessibility, is for foreground (often text) colors to contrast sufficiently against its background color. You've seen the Atlas Theme object utilities for this already; those utilities also use these, but also apply the colors registered in the theme, which makes it even easier! If you want to compute colors by hand, however, you'll find the following useful.
In the simpler of the two utility functions, you provide a test color (i.e. the "background"), for which you want to select a sufficiently-contrasting color. You supply a prioritized list of options, and it returns the first color from that list which sufficiently contrasts. The list might come from a set of standard theme colors, for example, and ordered by which color you'd prefer, if it meets the guidelines.
import {getFirstReadableColor } from '@asmartbear/ gutenberg- bridge/ dist/ themes/ colors' function getMyReadableColor(color:string): string {return getFirstReadableColor(color, ['#303F9F', // indigo that you'd really prefer '#f0f0f0', // close- to- white option '#222', // close- to- black option ])}
How much contrast is "sufficient?" There are standards from WCAG, which depend on things like the size of the text and the desired target level of accessiblity. The default in Atlas is a contrast ratio of 3
as defined by WCAG. You can specify a different ratio by specifying that number as an additional, final argument to getFirstReadableColor()
.
The more complex case, is when there's not only a background color, but a "desired" foreground color, where you'd like to select that foreground color as-given, if the constrast is already sufficient; if it is insufficiently constrasting, you'd like to use a different tone in the same color family, i.e. something from the same Atlas Swatch. Make the color lighter or darker, until it constrasts enough. Finally, it is possible to construct a situation where no swatch color contrasts enough, therefore there needs to be a priority-ordered list of backup options as well. Atlas has a utility for this:
import {getReadableColor } from '@asmartbear/ gutenberg- bridge/ dist/ themes/ colors' function getMyBestColor(backgroundColor:string,desiredColor:string): string { return getReadableColor(desiredColor, / / color we'd prefer to use backgroundColor, / / background we're constrasting against ['#303F9F', / / ordered backup colors, as before '#f0f0f0', '#222', ],3 // optional contrast ratio threshold )}
Try it for yourself!
The Theme.
object holds the "palette" for your theme, which are pre-defined colors plus related colors. While it's always possible to use arbitrary colors in block properties, defining a standard palette makes it possible to show that palette in Gutenberg, and also tweak the values of those colors later, without having to edit all the existing blocks.
Your theme's palette is placed in Theme.
. Each object therein contains a color in a field named main
, then lighter and darker variations in additional fields. Finally, a text
field is the color of text that is overlayed on that color. To make it easier to supply all these colors, you can use StandardThemeGenerator.
to generate those fields automatically. For example:
const themeGen = new StandardThemeGenerator();themeGen.addBrandColor("tiffany", "#0ecad4"); // Named brand colors themeGen.addBrandColor("mirage", "#002838"); // for WP Engine themeGen.addBrandColor("seafoam", "#50e3c2");themeGen.addBrandColor("royal", "#7e5cef");themeGen.addBrandColor("sunset", "#ff6c29");const theme = themeGen.getTheme();
In addition to your brand colors, there are a few other standard fields on the palette
object:
lightText
darkText
darkModeShift
250
, with 0
meaning "no color change for dark mode." The easiest way to understand this value, is to just play with it, and see what it does to your site.The Atlas theme system can provide dark mode automatically. How does this work?
Atlas adopts the Google Material Design philosophy on dark mode principles. It's not necessary that you learn those principles, but they explain the "why" behind the choices we've made, particularly with regard to color.
To create a dark mode theme, pass true
for the second parameter of new StandardThemeGenerator()
. This sets you up with defaults for standard colors, for example using the Material Design recommendation of #121212
for the main background (which still leaves room for "true black" and for shadows).
This also automatically adjusts the brand palette colors that you register. The adjustment might be surprising at first, because sometimes the color is lightened (and also desaturated), while other times it is darkened. This is due to our dark mode philosophy, which includes observations such as: Dark hues against any dark color are not only difficult to see, but tend to "vibrate," and therefore it is better to use a low-saturation pastel version of the color.
The color function getSwatchColor()
accepts a second parameter which is a "dark mode shift." This is a number in units of Material Design levels that determines "how much" to shift colors (whether higher or lower) for dark mode (although note that the algorithm uses the level only as a guide, because some hues require more or less shifting, and there are additional adjustments for saturation). This is how the Atlas blocks automatically support dark made, and you can use it directly as well.
Example of dark mode in action:
Note how the heading text becomes near-white to contrast against near-black, but in the case of the box of text, the text remains near-white, because it still contrasts sufficiently. Also notice how the already-dark text box becomes lighter but desaturated, while retaining the character of the original color.
Images are also adjusted automatically. Images that were not created by Atlas (i.e. not from Gutenberg, but from some other URL) are adjusted with a standard algorithm, but images managed by Atlas in Gutenberg are adjusted using additional intelligence. In particular, the goal is to make images a specific target darkness, but for colors to still be visible. The brighter the image, the more we need to darken it to achieve a standard darkness level. But we also adjust contrast and saturation, so that colors don't get completely washed to gray. With images managed by Atlas, we pre-compute values like the average color hue and lightness, which then become inputs to the algorithm.
While the inputs to the algorithm are computed in Javascript, the image adjustments are performed in CSS. This means there aren't any CPU-intensive image calculations, nor delay while images are regeneraed, nor generated images that need to be stored or cached.
To see this in action, note how the first example is an image that is already dark, so it is barely changed at all, whereas the second image is bright and colorful is significantly adjusted, but colors are increased in contrast to prevent them from becoming muddy.
All images share the same average brightness in dark mode, which gives the interface a consistency, with nothing "jumping out" at the user who might be viewing the page in a darkened room.