dbtedman / postcss-prefixwrap

A PostCSS plugin that is used to wrap css styles with a css selector to constrain their affect on parent elements in a page.
MIT License
67 stars 12 forks source link

[Feature request] Add support for compound selector #353

Closed oskar-anderson closed 5 months ago

oskar-anderson commented 6 months ago

Request

Add option appendCompoundSelector that generates 2 selectors: PREFIX .container, PREFIX.container. This will allow the style rules to start applying from the prefix level, removing the need to have extra divs.

Basically:

    // Anything other than a root tag is always prefixed.
    if (isNotRootTag(cleanedSelector)) {
        let result = prefixSelector + " " + cleanedSelector;
        if (appendCompoundSelector) {
            result += `, ${prefixSelector}${cleanedSelector}`;
        }
        return result;
    }

Use case

I have 3 levels of styles:

The apps need to use a css prefix to overwrite site styles, but unfortunately the component library also needs a css prefix, otherwise import will fail

`@apply` cannot be used with .font-light because .font-light is included in multiple rulesets. 

This causes cascade problems between Tailwind utility classes and generic styles when dealing with slotted content (EX ".eof .eac menu" > ".eof .mx-9"). Using .eac *:not(.ssc) prefix stops the styles from cascading (ssc - stop style cascade):

/** @type {import('postcss-load-config').Config} */
const config = {
    plugins: [
        require("postcss-import"),
        require("tailwindcss"),
        require("postcss-nested"),
        require("autoprefixer"),
        require("postcss-prefixwrap")('.eac *:not(.ssc)', {
            ignoredSelectors: ["body" , /^body.(.+)/],
        })
   ]
}

But it requires an extra div before the styles start applying, making the html structure cumbersome:

<template>
    <div show.bind="isVisible" class="ssc eac">
    <div>
    <div class="tooltip-container">
        <div class="e4-tooltip ${minWidth === 'wide' ? 'e4-tooltip-wide' : ''} e4-tooltip-${position}" ref="elem">
            <div class="e4-tooltip-arrow" ref="tooltipArrow"></div>
            <div class="overflow-hidden overflow-y-auto py-2 px-4 text-xs leading-snug text-center">
                <div class="ssc ${appStylePrefix}">
                <div>
                    <slot></slot>
                </div>
                </div>
            </div>
        </div>
    </div>
    </div>
    </div>
</template>
dbtedman commented 6 months ago

Thanks @oskar-anderson for the detailed feature request. Seems like a reasonable use case to support. I will take a look and let you know how I go.

dbtedman commented 6 months ago

@oskar-anderson if you see the PR https://github.com/dbtedman/postcss-prefixwrap/pull/361, with a source of

.something {
    font-size: 40px;
}

.something p {
    color: red;
}

Is the following prefix behaviour what you were expecting to see?

my-container .something, .my-container.something {
    font-size: 40px;
}

.my-container .something p, .my-container.something p {
    color: red;
}

If so, I will get this feature released so it is available for you and others to use.

oskar-anderson commented 6 months ago

This looks great!