-
-
Notifications
You must be signed in to change notification settings - Fork 72
PostCSS Preset Env 8
We're very mindful of the impact that major releases have, which is why we're trying to keep the changes well documented, well thought out and establish a good way to move forward.
As a quick summary, we're trying to achieve the following:
A polyfill should be indistinguishable from the native behavior
This has been our motto for a while! We've seen that specs rarely change, but they do! And also, over time, some plugins got some features that were not spec-compliant. We've closely reviewed plugins and made corrections where needed.
Back when all of the plugins were moved to the monorepo (see announcement) we've been enforcing a consistent style among the plugins, both in terms of code style but also in file organization. This meant that links from unpkg
hinted within plugins that require browser polyfills would have stopped working. To avoid creating more breaking changes, we had some scripts to copy to the old placement.
This script has now been removed so you will need to use the new locations if you rely on the old ones.
As hinted back in January, we're no longer enabling plugins that require a browser polyfill by default. We've seen that the PostCSS plugins are "expected" to just work and that it wasn't obvious that a separate browser polyfill was also needed. In reality those polyfills were almost never bundled and the feature almost never worked.
The end result of changing this default is that a minimal config of postcss-preset-env
is more correct and will work better for more users.
We want you to be able to remove/disable any plugin from postcss-preset-env
if the feature is sufficiently supported in browsers.
Some plugins however had sub features which were not a polyfill.
The most notable are importFrom
and exportTo
. We discussed this in detail here: replacement for importFrom
and exportTo
.
We do value those sub features but we think they are worthy of dedicated plugins and should be kept separate from postcss-preset-env
.
We created three plugins that we think have more potential in the long run:
- PostCSS Design Tokens to "import" bits of CSS.
- PostCSS Extract to "export" bits of CSS.
- PostCSS Global Data to "inject" CSS into the PostCSS execution context, allowing plugins to access it but then removing it from the output.
See an example of postcss-extract
to replace exportTo
There were some plugins that had CLI packages distributed and some that didn't, we remediated that by creating a global CLI. While we don't recommend using the CLI as part of any pipeline, it's definitely useful when trying to quickly debug or demonstrate something.
We've removed those outliers that still kept an independent CLI so if you were relying on that, you should now migrate to use @csstools/csstools-cli.
The following plugins have been impacted:
- PostCSS Preset Env
- PostCSS Blank Pseudo
- PostCSS Custom Media
- PostCSS Custom Properties
- PostCSS Custom Selectors
- PostCSS Focus Visible
- PostCSS Focus Within
- PostCSS Has Pseudo
- PostCSS Logical
- PostCSS Nesting
- Prefers Color Scheme
This disables by default the following plugins:
- PostCSS Blank Pseudo
- PostCSS Focus Visible
- PostCSS Focus Within
- PostCSS Has Pseudo
- Prefers Color Scheme Query
These plugins require browser polyfills and transform your CSS in ways that make you dependent on the browser polyfill. As these plugins are rarely used and can appear to break your CSS, we prefer to have these disabled by default.
If you did rely on plugins that need a client-side polyfill, you must now pass the option enableClientSidePolyfills
as true
as opposed to not needing to pass it:
postcssPresetEnv({
+ enableClientSidePolyfills: true
});
This affects the following plugins:
If you used the importFrom
or exportTo
plugin options you will need to refactor your code so that you no longer rely on those sub-features.
We also recommend the usage of PostCSS Global Data where importFrom
was used. This plugin allows you to inject data from any source so the plugins have the data they need to generate media queries, custom properties, or custom selectors. It needs to run before PostCSS Preset Env for it to work.
PostCSS Env Function was removed from postcss-preset-env
This plugin didn't actually polyfill a native feature.
If you used the env()
function in CSS with custom properties you will need to refactor your code so that you no longer rely on this feature. Alternatively, you can still use the plugin by installing it separately and adding it to your list of plugins manually so it always runs. However, do note that the plugin is not maintained anymore and is officially deprecated.
The internal CLI exposed by the package has been removed in favor of the global CLI.
The old CDN URLs have been removed.
The browser polyfill has updated the initialization which means you need to update how it's called.
Generated CSS is now also different since it prepends js-blank-pseudo
to the document on initialization so CSS doesn't start applying till then.
- Re-build your CSS with the new version of the library.
- If you use a CDN URL, please update it.
- <script src="https://unpkg.com/css-blank-pseudo/browser"></script>
- <script src="https://unpkg.com/css-blank-pseudo/browser.min"></script>
+ <script src="https://unpkg.com/css-blank-pseudo/dist/browser-global.js"></script>
- cssBlankPseudo(document)
+ cssBlankPseudoInit()
- cssBlankPseudo({
- attr: false,
- className: 'blank'
- })
+ cssBlankPseudoInit({
+ replaceWith: '.blank'
+ })
-
importFrom
andexportTo
plugin options were removed - implement logical evaluation of complex media queries
If you used the importFrom
or exportTo
plugin options you will need to refactor your code so that you no longer rely on those sub-features.
We also recommend the usage of PostCSS Global Data where importFrom
was used. This plugin allows you to inject data from any source so the plugins have the data they need to generate media queries, custom properties, or custom selectors. It needs to run before PostCSS Preset Env for it to work.
If you use relatively complex media queries together with @custom-media
you should verify that the outcome is still the same.
If you used custom media references without parenthesis you must add these :
@custom-media --foo (min-width: 320px);
- @media --foo {}
+ @media (--foo) {}
-
importFrom
andexportTo
plugin options were removed
If you used the importFrom
or exportTo
plugin options you will need to refactor your code so that you no longer rely on those sub features.
We also recommend the usage of PostCSS Global Data where importFrom
was used. This plugin allows you to inject data from any source so the plugins have the data they need to generate media queries, custom properties, or custom selectors. It needs to run before PostCSS Preset Env for it to work.
-
importFrom
andexportTo
plugin options were removed - always use :is() in transformed selectors
The usage of :is()
is important to align Custom Selectors with its draft specification and with CSS Nesting.
If you used the importFrom
or exportTo
plugin options you will need to refactor your code so that you no longer rely on those sub-features.
We also recommend the usage of PostCSS Global Data where importFrom
was used. This plugin allows you to inject data from any source so the plugins have the data they need to generate media queries, custom properties, or custom selectors. It needs to run before PostCSS Preset Env for it to work.
If you use pseudo-elements in custom selectors (e.g. ::before
) you will need to rewrite your custom selectors to remove these.
- @custom-selector :--pseudos ::before, ::after;
-
- :--pseudos {
+ ::before, ::after {
content: "";
}
If you use complex selectors (e.g. .foo + .bar
) you will need to verify your project.
The matched elements can be different.
We've changed generated classes so it prepends .js-focus-visible
to them. That way CSS is applied when the polyfill is known to be running. This class is added automatically by WICG's polyfill.
Even though there's no migration needed for this change, you might have been relying on the previous behavior which is why we've flagged this release as major.
We've changed generated classes so it prepends .js-focus-within
to them. That way CSS is applied when the polyfill is known to be running. This class is added automatically by our browser polyfill which is now bundled within postcss-focus-visible
as opposed to using the one from JSXTools.
- Import the polyfill from the PostCSS Plugin:
import focusWithinInit from 'postcss-focus-within/browser';
focusWithinInit();
We have deprecated the experimental version of the plugin. All issues have been resolved in the main plugin and the experimental plugin is no longer maintained.
- Re-build your CSS with the new version of the library.
- If you were relying on
@csstools/css-has-pseudo-experimental
, please use css-has-pseudo. - If you use a CDN URL, please update it.
- <script src="https://unpkg.com/css-has-pseudo/browser"></script>
+ <script src="https://unpkg.com/css-has-pseudo/dist/browser-global.js"></script>
- <script src="https://unpkg.com/css-has-pseudo/browser.min"></script>
+ <script src="https://unpkg.com/css-has-pseudo/dist/browser-global.js"></script>
We have removed support for the logical
keyword for margin
, padding
, border-width
, border-style
, border-color
properties. The main reason is that the rest of the spec has been implemented by all main browsers but none of them support the logical
keyword. There's also a warning around it on the spec. See 4.7. Four-Directional Shorthand Properties and also [css-logical] Flow-relative syntax for margin-like shorthands #1282.
We have also removed support for transforming resize
, float
, and clear
. The reason for this is that support on browsers differs greatly from the majority of the properties. This was a concern for us on PostCSS Preset Env given that we only run plugins that are needed depending on your browserconfig. As an example, this would mean that logical
would be running and transforming padding-block
when you wouldn't really need it.
We have removed support for the preserve
attribute. Logical properties can map to different physical properties which could lead to unexpected results.
We have also changed how the plugin works in general. It no longer uses :dir
to apply logical properties. This was done for several reasons:
- It increases the specificity of the generated CSS which is not ideal.
- It does not fully cover all use cases (e.g. for vertical languages).
- If you were relying on the usage of
:dir
you need to refactor your code. - The
dir
option has been removed. If you were using it, you can now change theinlineDirection
option:
postcssLogical({
- dir: 'rtl',
+ inlineDirection: 'right-to-left',
});
- If you were relying on transforming
resize
,float
, andclear
you should now also include postcss-logical-float-and-clear and postcss-logical-resize in your build.
We have removed support for Deno. We never released updates for Deno and we feel we are not helping users by documenting this as supported. If we were to bring this back, it would be in a maintainable way that would support all of the plugins and not only Nested.
Deno is actively working on better support for JavaScript hosted on NPM so if you were relying on this feature, it might get possible to use this in Deno natively. See: https://deno.land/manual@v1.29.4/node/npm_specifiers
The old CDN URLs have been removed.
color-depth
fallback has been removed.
The no-preference
support has been dropped as this has been removed from the spec.
The old global object has been removed.
- Re-build your CSS with the new version of the library.
- If you use a CDN URL, please update it.
- <script src="https://unpkg.com/css-prefers-color-scheme/browser"></script>
+ <script src="https://unpkg.com/css-prefers-color-scheme/dist/browser-global.js"></script>
- <script src="https://unpkg.com/css-prefers-color-scheme/browser.min"></script>
+ <script src="https://unpkg.com/css-prefers-color-scheme/dist/browser-global.js"></script>
- Use
prefersColorSchemeInit
to initialize the polyfill in the browser.
- initPrefersColorScheme()
+ prefersColorSchemeInit()
- Remove
@media (prefer-color-scheme: no-preference)
from your CSS.
@media (prefers-color-scheme: no-preference)
was removed from the specification and should be equivalent to not having any media query.
- @media (prefers-color-scheme: no-preference) {
- .some-selector {
- /* your styles ... */
- }
- }
+ .some-selector {
+ /* your styles ... */
+ }
The exportTo
option used to specify destinations where custom selectors can be exported to, which might have been CSS, JS, and JSON files, functions, and directly passed objects.
This feature has been removed as it was outside the scope of the plugin.
postcssCustomSelectors({
exportTo: 'path/to/file.css' // @custom-selector :--heading h1, h2, h3;
});
The replacement for this feature is PostCSS Extract.
To match the format from the removed exportTo
option you can use this snippet :
const postcss = require('postcss');
const postcssCustomSelectors = require('postcss-custom-selectors');
const postcssExtract = require('@csstools/postcss-extract');
postcss([
postcssExtract({
queries: {
customSelectors: 'atrule[name="custom-selector"]'
},
results: (results) => {
const formatted = {}
results.customSelectors.forEach((atRule) => {
const splitIndex = atRule.params.indexOf(' '); // split after the custom selector name
formatted[atRule.params.slice(0, splitIndex)] = atRule.params.slice(splitIndex+1).trim();
});
console.log({
customSelectors: formatted
});
}
}),
postcssCustomSelectors(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);