cssnano is reordering overridden properties - css

I am using less, postcss and cssnano (version 3.7.3). In less, I am using classes which inherit from a shared base and overriding some of the properties when needed. I am finding that cssnano is reordering the inherited\overridden properties causing unexpected differences in the style.
A trimmed down example .less looks like this:
.cell-label {
font-size: 11px;
}
.heading-label-cell {
.cell-label;
color: #heading-colour;
font-size: 13px;
}
.question-label-cell {
.cell-label;
color: #question-colour;
}
Which is then expanded to css looking like:
.heading-label-cell {
font-size: 11px;
font-size: 13px;
color:#616161;
}
.question-label-cell {
font-size: 11px;
color: #0073d6;
}
But cssnano then does the following which has reordered the font-size property:
.heading-label-cell {
color:#616161;
font-size:13px
}
.heading-label-cell,.question-label-cell {
font-size:11px;
}
.question-label-cell {
color:#0073d6
}
Is there a different way I am expected to do inheritance/overrides that doesn't suffer this problem or is the fault in cssnano?

Reordering CSS properties is not always a safe operation, but it is enabled in the default preset. If you encounter problems, with it, disable it. This optimisation is called cssDeclarationSorter.
For example, the options to call cssnano with:
{
preset: [
'default',
{ cssDeclarationSorter: false }
]
}
Or if you use cssnano as a plugin for postcss, this is postcss.config.js:
module.exports = {
plugins: {
cssnano: {
preset: [
'default',
{ cssDeclarationSorter: false }
]
}
}
}

Related

How to remove unnecessary css when it compiled to output in TailwindCSS?

I'm combining tailwindcss with another ui framework (Ant Design), but having some conflicts with the css in tailwind.
I want to compile the necessary classnames if it is used to minimize conflicts
My expect example:
<div className="text-center font-bold" />
After compiled in output.css file:
.text-center {
text-align: center;
}
.font-bold {
font-weight: bold;
}
which this output results should not included css default like:
html{-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji}
.text-center {
text-align: center;
}
.font-bold {
font-weight: bold;
}
Just disable Preflight
// tailwind.config.js
module.exports = {
....
corePlugins: {
preflight: false,
}
}

Add attribute to all CSS rules except some

I need to add an attribute [dir=ltr] to all the rules of a big CSS file except for some ones.
Source CSS:
.rule-1 {
color:black
}
.rule-2 {
color: yellow
}
.rule-3 { /* exclude */
color: blue
}
.rule-4 {
color: red
}
Target CSS:
[dir=ltr] .rule-1 {
color:black
}
[dir=ltr] .rule-2 {
color: yellow
}
.rule-3 {
color: blue
}
[dir=ltr] .rule-4 {
color: red
}
Maybe a CSS postprocessor is needed here.
Try using the css :not() attribute, example below:
[dir=ltr]:not(.rule-3) {
//..
}
You can learn more about this attribute and what it does here
The issue was solved using the PostCSS plugin postcss-prefix-selector.
postcss.config.js
module.exports = {
plugins: {
"postcss-prefix-selector": {
prefix: '[dir=ltr]', exclude: [/.rule-3(?![\w])/]
}
}
}

Styling `::slotted()` elements from the static styles property

I'm trying to style the :slotted elements in a component from the static styles property as recommended in the docs.
static get styles() {
return [
css `
::slotted(*) {
color: var(--white, #fff);
font-family: "Open Sans", sans-serif;
}
`,
// more styles...
]
}
But for some reason, is getting no effect.
Instead if define the same style in a style element into the render() function it works as expected
<style>
::slotted(*) {
color: var(--white, #fff);
font-family: "Open Sans", sans-serif;
}
// more styles...
</style>
I'm not sure if this is expected (and why) or if this is a bug.
Seems to be a syntax problem in my example. I was using an style array.
This is working fine
static get styles(): CSSResultArray {
return [
css`
:host {
/* styles */
}
::slotted(span) {
/* styles */
}
`,
css`
:host([data-type="primary"]) button {
/* styles */
}
`
];
}

How do I nest attribute selector under :host-context?

Using LESS pre-processor along with shadow-dom for theming support of individual components. I have also attempted nesting :host-context and :host selectors to no avail.
:host-context(.dark) {
#import (multiple) 'variables/dark-theme';
.dropdown;
}
:host-context(.light) {
#import (multiple) 'variables/light-theme';
.dropdown;
}
.dropdown() {
//some component styles here
&:disabled {
background-color: #disabled-bg;
color: #disabled-color;
.dropDownListSelect {
cursor: not-allowed;
}
}
}
This is a result of my own ignorance with Shadow-DOM as it is still somewhat new to me. I was able to accomplish this by using the &:host selector.
:host-context(.dark) {
#import (multiple) 'variables/dark-theme';
.dropdown;
}
:host-context(.light) {
#import (multiple) 'variables/light-theme';
.dropdown;
}
.dropdown() {
//some component styles here
&:host([disabled]) {
background-color: #disabled-bg;
color: #disabled-color;
.dropDownListSelect {
cursor: not-allowed;
}
}
}

How can I get grunt-autoprefixer to prefix uncompiled LESS files?

I'm working with LESS and I'd like to run grunt-autoprefixer on my LESS markup WITHOUT compiling LESS, because my LESS is compiled on my CMS automatically.
Is this possible?
Here's my Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
concat: {
sqs_template: {
src: ['js/one.js', 'js/two.js'],
dest: 'sqs_template/scripts/app.js',
},
},
autoprefixer: {
options: {
remove: true,
},
multiple_files: {
expand: true,
flatten: true,
src: 'css/*.less',
dest: 'sqs_template/css/',
},
},
watch: {
js: {
files: ['js/**/*.js'],
tasks: ['concat'],
},
css: {
files: ['css/**/*.less'],
tasks: ['autoprefixer'],
},
},
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.loadNpmTasks('grunt-contrib-watch');
};
Here's an example of the LESS I'm trying to prefix:
//------------------------------------*\
// SOME CSS
//------------------------------------*/
// Variables
#site-width: 960px;
#color: #333333;
// Mixins
.some-font {
font-family: sans-serif;
font-size: 1.5rem;
font-weight: bold;
}
.some-container {
display: flex;
max-width: #site-width;
margin: 0 auto;
.some-container-inner {
p {
.some-font;
color: #color;
}
}
}
I would want grunt-autoprefixer to do nothing but prefix my LESS, and put it into the sqs_template folder. Right now, grunt-autoprefixer errors because it doesn't seem to recognize the variables or mixins.
Is this possible?
Thanks!
Instead of autoprefixing, you could use mixins to prefix the needed values yourself. There's LESS-Prefix library that contains mixins for the usual suspects.
As a simple example, if you are using LESS-Prefix (or have a similar mixin yourself), you can just include the mixin file and type the CSS-properties prepended by a .
div {
.box-shadow(0px 0px 10px rgba(255,0,0,.5));
}
which passes the values through this mixin:
.box-shadow(#args) {
-webkit-box-shadow: #args;
box-shadow: #args;
}
and you'll end up with this:
div {
-webkit-box-shadow: 0px 0px 10px rgba(255,0,0,.5);
box-shadow: 0px 0px 10px rgba(255,0,0,.5);
}

Resources