Support extend
in variants
config
#2651
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR makes it possible to
extend
your variants configuration to avoid having to write out the entire default variant list whenever you want to enable an extra variant.For example, this is what it looks like to add
focus-within
to thebackgroundColor
plugin traditionally:This is what it would look like after this PR is merged:
This is a non-breaking change and doesn't break or remove any existing functionality.
Motivation
Trying to extend variants has been the source of a lot of issues, Discord questions, forum posts, etc. over the years, as it's very common for people to do something like this and then be surprised that all of the default variants stopped working:
It's challenging to solve this problem though because the order of your variants matters, because it affects the order your CSS is generated in and CSS source order affects specificity.
For example, take a look at this HTML:
Given this configuration:
...when the button is both hovered and focused, the background is green, because the focus styles are defined after the hover styles.
With this configuration:
...when the button is both hovered and focused, the background is pink, because now the hover styles are taking precedence over the focus styles.
For this reason we punted on trying to solve this problem for a long time, because when someone needed to add a new variant, they also needed some way to say where in the list that variant should be added.
Eventually, I added this function-driven API that let you specify the position of a variant using helpers like
before
andafter
like so:This would add the
focus-within
variant before thehover
variant in the existing list.This totally works and is a very flexible API, but it is fairly cryptic looking, especially to people who aren't expert JavaScript programmers. It gets especially cryptic when you start trying to compose
before
andafter
together like this:Yeah it works but man that is some insane looking shit.
We need a better way! I regret adding this API and will likely stop documenting it after this PR is merged.
Detailed design
This PR uses a new approach based on the existing
extend
behavior people are used to from thetheme
section. You simply add the variants you want to enable under theextend
section, and they are merged with any other configured variants for that plugin.Handling sort order
To handle the sort order, we maintain a "recommended sort order" list in Tailwind that is stored in the default config under
variantOrder
:When you use
extend
, we merge your extended variants with any other configured variants, then sort them using this list as a reference.Overriding sort order
If you want to change the sort order, you can override the
variantOrder
key in your own config:Tailwind will use this as the new reference list when sorting things.
Overriding sort order per plugin
Tailwind will only sort your variants if you are actually using the extend feature for that plugin. If you'd like to have total control over the sort order per plugin, just set up your variant list the same way you alread do now:
Since in this example we aren't using the
extend
feature for thebackgroundColor
plugin, Tailwind will not attempt to sort it, and instead trust that you have put the variants in the order that you want them in.Working with third-party variant plugins
If you are using any plugins that add variants to Tailwind, those variants will always be added at the beginning of the variant list by default when using
extend
and triggering sorting:You can put the variant in a specific place by simply not using extend and providing the whole list yourself:
...or by adding the custom variant to your
variantOrder
configuration:We recommend just copying the default sort order from the default config and using it as a starting point when you need to do this, effectively just taking ownership of the list and managing it yourself.
Future improvements
We may eventually consider supporting a function syntax for
variantOrder
so you can more easily insert custom variants in specific positions in the list, but that is not included at the time of this PR.