1

I am using styled-components, prettier and stylelint. Here is my .stylelintrc.json:

{
  "extends": [
    "stylelint-config-standard",
    "stylelint-prettier",
    "stylelint-config-prettier",
    "stylelint-config-rational-order"
  ],
  "plugins": ["stylelint-order", "stylelint-config-rational-order/plugin"],
  "customSyntax": "postcss-styled-syntax"
}

As you can see, I am using stylelint-config-rational-order/plugin and when I am running this command:

stylelint \"src/**/*.tsx\" --fix"

... I am expecting stylelint to automatically fix styles order in all corresponding files, they should approximately look like this:

// Test.tsx -- BEFORE LINTING

import styled from 'styled-components';

export const Test = styled.div<{ active: boolean }>`
  width: 20px;
  height: 20px;

  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  background: ${p => p.active && 'var(--blue)'};
  transition: var(--transition-200);
  flex-shrink: 0;

  &:hover {
    background: ${p => !p.active && 'var(--blue-hover)'};
  }

  cursor: pointer;
  border-radius: 50%;
  margin-right: 8px;
  height: 20px;

  &:last-child {
    margin-right: 0;
  }
`;
// Test.tsx -- AFTER LINTING (desired result)

import styled from 'styled-components';

export const Test = styled.div<{ active: boolean }>`
  height: 20px;
  width: 20px;

  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  background: ${p => p.active && 'var(--blue)'};
  transition: var(--transition-200);
  border-radius: 50%;
  margin-right: 8px;

  cursor: pointer;

  &:hover {
    background: ${p => !p.active && 'var(--blue-hover)'};
  }

  &:last-child {
    margin-right: 0;
  }
`;

But in fact I am getting this result:

// Test.tsx -- AFTER LINTING (not desired result)

import styled from 'styled-components';

export const Test = styled.div<{ active: boolean }>`
  width: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  background: ${p => p.active && 'var(--blue)'};
  transition: var(--transition-200);
  flex-shrink: 0;

  &:hover {
    background: ${p => !p.active && 'var(--blue-hover)'};
  }

  cursor: pointer;
  border-radius: 50%;
  margin-right: 8px;
  height: 20px;

  &:last-child {
    margin-right: 0;
  }
`;

As you can see it just removes some breaks and doing absolutely nothing in terms of reordering.

So, my question is – is there a way to make stylelint --fix work with stylelint-config-rational-order/plugin (or similar reordering plugins) and styled-components and automatically fix all css-in-js throughout the app according to mentioned rules?

–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

UPD: I've tried to use more advanced config to make stylelint add empty lines between logical groups, here it is:

// stylelint.config.js

const propertyGroups = require('stylelint-config-recess-order/groups');

module.exports = {
  extends: ['stylelint-config-standard'],
  plugins: ['stylelint-order'],
  customSyntax: 'postcss-styled-syntax',
  rules: {
    // Configure the custom rule manually.
    'order/properties-order': propertyGroups.map(group => ({
      ...group,
      emptyLineBefore: 'always',
    })),
  },
};

However, I still can not achieve desired result, when I run npx stylelint Test.tsx --fix I get this output:

import styled, { css } from 'styled-components';

const Test = styled.div<{ flag: boolean }>`
  display: flex;
  height: 18px;
  background-color: var(--color-primary);
  width: 18px;
  justify-content: center;
  border-radius: 50%;
  font-size: 14px;
  ${p =>
    p.flag &&
    css`
      border-radius: 0;
      background-color: green;
    `}
  line-height: 20px;
  color: var(--color-white);
  align-items: center;
  &:hover {
    background-color: red;
  }
`;

/* Desired result */

// const Test = styled.div<{ flag: boolean }>`
//   height: 18px;
//   width: 18px;

//   display: flex;
//   align-items: center;
//   justify-content: center;

//   font-size: 14px;
//   line-height: 20px;
//   color: var(--color-white);

//   border-radius: 50%;
//   background-color: var(--color-primary);

//   &:hover {
//     background-color: red;
//   }

//   ${p =>
//     p.flag &&
//     css`
//       border-radius: 0;
//       background-color: green;
//     `}
// `;

/* Fact result */

// const Test = styled.div<{ flag: boolean }>`
//   display: flex;
//   height: 18px;
//   background-color: var(--color-primary);
//   width: 18px;
//   justify-content: center;
//   border-radius: 50%;
//   font-size: 14px;
//   ${p =>
//     p.flag &&
//     css`
//       background-color: green;
//       border-radius: 0;
//     `}
//   line-height: 20px;
//   color: var(--color-white);
//   align-items: center;

//   &:hover {
//     background-color: red;
//   }
// `;

1 Answer 1

1

Use the stylelint-config-recess-order shared config, rather than stylelint-config-rational-order:

{
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-recess-order"
  ],
  "customSyntax": "postcss-styled-syntax"
}

The recess order config is maintained (last published 2 weeks ago), unlike the rational order config (last published 4 years ago). The recess order config appears compatible with the postcss-styled-syntax custom syntax and supports modern CSS properties.

The two configs have similar groupings, i.e., they start with positioning, box model, typography, etc.

Running npx stylelint test.tsx gives:

import styled from "styled-components";

export const Test = styled.div<{ active: boolean }>`

  display: flex;
  flex: 1;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-right: 8px;
  cursor: pointer;
  background: ${(p) => p.active && "var(--blue)"};
  border-radius: 50%;
  transition: var(--transition-200);

  &:hover {
    background: ${(p) => !p.active && "var(--blue-hover)"};
  }

  &:last-child {
    margin-right: 0;
  }
`;

Stylelint also detected and removed the duplicate height property.

If you want empty lines between groups, you can follow the advanced guidance when to configure the rule:

const propertyGroups = require('stylelint-config-recess-order/groups')

module.exports = {
    extends: ["stylelint-config-standard"],
    plugins: ["stylelint-order"],
    customSyntax: "postcss-styled-syntax",
    rules: {
        // Configure the custom rule manually.
        'order/properties-order': propertyGroups.map((group) => ({
            ...group,
            emptyLineBefore: 'always'
        })),
    },
}

Additionally, you don't need:

  • stylelint-config-prettier as stylelint-config-standard no longer conflicts with Prettier
  • stylelint-prettier as it's recommended to run Prettier as a separate tool
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer, this config actually does group properties similar to the way I need but I am still facing one problem – it does not adding line-breaks after each logic styles group. This is essential for me. Is there any way this can be achieved?
I've updated the answer to show how.
Hey, thanks for your update. However, I'm still not able to achieve desired result, please be kind to read UPD section in my question so you can see the problem. I am not aiming to achieve this specific order of groups but I really want to have empty lines between them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.