Utilities
Style utilities are general-purpose helpers for your
components. Classes like
.align-right
or .large-shadow
are examples of such style utilities. From
Warhol's perspective the use of style utilities on already defined components
appears as unexpected CSS declaration error …
unless you configure style utilities in the utils
section in your
configuration! Warhol can then build a list of styles that components can
have in addition to their component styles without causing error messages.
By declaring style utilities to Warhol you quite literally create a whitelist of sets of styles that will not trigger unexpected CSS declaration errors. Style utilities can be combined and you can restrict style utilities to certain components. You do not need to care about style utilities if only use Warhol for theme checking.
Example configuration #
{
"patternLibUrl": "https://warhol.io/components",
"utils": {
"utilsUrl": "https://warhol.io/components/utils",
"sources": [
{ "type": "rule", "selector": ".align-left", "components": [ ".image", ".box" ] },
{ "type": "rule", "selector": ".align-right", "components": [ ".image", ".box" ] ] },
{ "type": "element", "selector": ".shadow", "name": "Shadow utility" }
]
}
}
Field utils.utilsUrl
(optional, string
, defaults to the pattern lib URL) #
If your utilities live on a specific URL in your pattern library, you can specify
this here. If you omit utils.utilsUrl
, the top top-level patternLibUrl
will
be used. If you set neither the utils.utilsUrl
nor the top top-level
patternLibUrl
, you will get an error.
Field utils.sources
(required, array of objects) #
Sources for utilities. Each utility is described by an object:
type
(either"rule"
or"element"
): whether to read the utility styles from an element or from a CSS ruleselector
(string
, required, non-empty): the selector for the style utilitycomponents
(list ofstring
, optional): target selectors for the components that can use this utility. By default all utilities can be used by all components. Use this field to restrict utilities to specific components.name
(string
, optional, non-empty, defaults tonull
): utility name defaults to null
How utilities work #
The distinction between type="element"
and type="rule"
is very important!
The former will read styles from an element in a web page (just like with
virtually everything else in Warhol) while the latter will take styles
directly from matching rules in your style sheets! This allows for very
precise style selection as only the styles from the matching CSS rules end up
defining the utility.
With type="element"
you have to make sure that only the styles for your
utility apply to the source element, which may be almost impossible! If any
style sheet in the pattern library uses the *
selector to set any styles,
these styles will also appear in your utilities. You probably do not want
this to happen!
The primary disadvantage of type="rule"
is that it ties Warhol directly to
implementation details of your pattern library. With type="rule"
, Warhol will
search all style sheets used in the pattern library for rules that uses one of
the exact selectors given in selector
. The CSS from the resulting rules
are then applied to a dummy element and the resulting styles are captured for
the utility. This is quite a delicate process! Be very sure to check the
snapshot error log in Warhol's web app to make sure that Warhol was able to find
a source rule for each utility in your configuration!
Another potential problem of type="rule"
is related to the way the resulting
utility is constructed. When the utility's styles are built from a dummy
element, only CSS variables that were defined on the root element (usually
<html>
) or on <body>
can have any effect on the resulting utility.
Note that the rules or classes used to define style utilities only need to exist in your pattern library. They are only used to build a whitelist of styles and Warhol does not need to know anything about their counterparts in your production web site.
If a selector matches more than one element or appears as the selector in more than one CSS rule, the styles from all matching sources will be combined into a single style utility. You can use this to compose utilities. Given the following CSS...
.align-left { text-align: left; padding-right: 1em }
.align-right { text-align: right; padding-left: 1em }
.red-text { color: red }
.green-background { background-color: green }
... and the following Warhol configuration...
{
"patternLibUrl": "https://warhol.io/components",
"utils": {
"sources": [
{ "type": "rule", "selector": ".align-left, .red-text", "components": [ ".box" ] },
{ "type": "rule", "selector": ".align-right, .red-text", "components": [ ".box" ] },
{ "type": "rule", "selector": ".green-background" }
]
}
}
... this configuration defines three utilities, each composed of the styles
defined in rules, not elements. The resulting utilities allow .box
components
to be aligned on the left or the right with the appropriate padding if their
text is also red. They, along with all other components can also have green
as a background color, because the third utility is not restricted to any
particular component. In short, the following uses of utilities on a .box
component are valid:
<div class="box"></div> <!-- no utility classes at all -->
<div class="box align-left red-text"></div>
<div class="box align-right red-text"></div>
<div class="box align-left red-text green-background"></div>
<div class="box align-right red-text green-background"></div>
.align-left
cannot be combined with .align-right
because the declarations of
the text-align
property contradict each other and both have the same
importance. All possible utility combinations are computed by Warhol in advance
and you will see a conflicting utilities debug message
in your snapshot log if there are any conflicts.
It goes without saying that you do not have to use the same classes or class names in production as in the pattern library. Warhol only uses the class names to construct whitelists for its tests.
Known limitations #
Warhol is able to read utilities (and everything else) from any iframes it encounters, but properly merging utilities from different source pages (e.g. two different iframes) is currently not supported.
Tips for debugging #
- Do not go crazy with utilities! They are tricky to get right and can have very far-reaching consequences. It is often better (and simpler and, for the human consumers of your pattern library, much more clear and intuitive) to define a few extra component variants.
- Check the snapshot error log in the web app to make sure that Warhol was able to find source rules and/or elements for each utility.
- Inspect your style utilities in the browser extension or the web app to make sure that the utilities do not contain to many or to few styles.