SassNinja / postcss-extract-media-query

PostCSS plugin to extract all media query from CSS and emit as separate files.
MIT License
130 stars 20 forks source link

@supports queries in @media queries get removed #2

Closed stevepiron closed 4 years ago

stevepiron commented 6 years ago

Hi,

@supports queries in with @media queries are not found in the output.

If using @supports queries only (for the mobile stylesheet) the output is fine, but combined with @media queries, they disappear.

Could you please have a look at that?

SassNinja commented 6 years ago

Hi @stevepiron

thanks for reporting this issue!

The problem is I've only considered rules within @media and not atRules (such as @supports). Seems my addToAtRules method needs some rework. I'll try to do this on the weekend.

p.s.

would be awesome if you gave the plugin a github star 😉

SassNinja commented 6 years ago

Brief update: as this requires a rework of how the CSS is internally saved I'm going to move the @supports support to the next major release (2.0.0)

stevepiron commented 6 years ago

Alright, thanks!

Meanwhile, a workaround is to have @media wrapped by @supports instead of the other way around. Like so:

Good

@supports (display: grid) {
  @media screen only and (min-width: 50em) {
    grid-template-columns: 2fr repeat(3, 1fr);
  }
}

Bad

@media screen only and (min-width: 50em) {
  @supports (display: grid) {
    grid-template-columns: 2fr repeat(3, 1fr);
  }
}
stevepiron commented 5 years ago

Documenting an additional scenario that breaks the CSS output as well:

Input

/**
 * 1. Fallback
 * 2. Firefox
 * 3. Other browsers that support env() and max()
 */
.o-wrapper {
    padding: 0 2rem; /* [1] */
    @supports (padding:calc(constant(safe-area-inset-left))) { /* [2] */
        padding-left: calc(2rem + constant(safe-area-inset-left));
        padding-right: calc(2rem + constant(safe-area-inset-right));
    }
    @supports (padding:calc(max(0px))) { /* [3] */
        padding-left: calc(max(2rem, env(safe-area-inset-left)));
        padding-right: calc(max(2rem, env(safe-area-inset-right)));
    }

    @media screen only and (min-width: 50em) { /* [1] */
        padding-left: 5rem;
        padding-right: 5rem;
    }
    @supports (padding:calc(constant(safe-area-inset-left))) { /* [2] */
        @media screen only and (min-width: 50em) {
            padding-left: calc(5rem + constant(safe-area-inset-left));
            padding-right: calc(5rem + constant(safe-area-inset-right));
        }
    }
    @supports (padding:calc(max(0px))) { /* [3] */
        @media screen only and (min-width: 50em) {
            padding-left: calc(max(5rem, env(safe-area-inset-left)));
            padding-right: calc(max(5rem, env(safe-area-inset-right)));
        }
    }
}

The idea here is to introduce safe-area-inset-left and safe-area-inset-right for gutters when browsing a site in landscape mode on a device featuring a notch (example: iPhone X).

I've tried the "workaround" I found and wrote about in my previous comment which is wrapping the media query with @supports (instead of doing it the other way around) but it doesn't seem to work when multiple @supports are used within the same file.

With such an input, here's the output I get:

Output: main.css (mobile styles)

.o-wrapper {
    padding: 0 2rem;
    padding-left: calc(max(2rem, env(safe-area-inset-left)));
    padding-right: calc(max(2rem, env(safe-area-inset-right)));
}

Output: only-screen-and-min-width-50em.css

@media only screen and (min-width: 50em) {
    .o-wrapper {
        padding-left: 5rem;
        padding-right: 5rem
    }

    .o-wrapper {
        padding-left: calc(5rem + constant(safe-area-inset-left));
        padding-right: calc(5rem + constant(safe-area-inset-right))
    }

    .o-wrapper {
        padding-left: calc(max(5rem,env(safe-area-inset-left)));
        padding-right: calc(max(5rem,env(safe-area-inset-right)))
    }
}

☝️@supports are removed.

With a regular CSS input, I still don't get a good result:

Input

/**
 * 1. Fallback
 * 2. Firefox
 * 3. Other browsers that support env() and max()
 */

.o-wrapper {
    padding: 0 2rem; /* [1] */
}
@supports (padding:calc(constant(safe-area-inset-left))) { /* [2] */
    .o-wrapper {
        padding-left: calc(2rem + constant(safe-area-inset-left));
        padding-right: calc(2rem + constant(safe-area-inset-right));
    }
}
@supports (padding:calc(max(0px))) { /* [3] */
    .o-wrapper {
        padding-left: calc(max(2rem, env(safe-area-inset-left)));
        padding-right: calc(max(2rem, env(safe-area-inset-right)));
    }
}

@media only screen and (min-width: 50em) { /* [1] */
    .o-wrapper {
        padding-left: 5rem;
        padding-right: 5rem;
    }
}
@supports (padding:calc(constant(safe-area-inset-left))) { /* [2] */
    @media only screen and (min-width: 50em) {
        .o-wrapper {
            padding-left: calc(5rem + constant(safe-area-inset-left));
            padding-right: calc(5rem + constant(safe-area-inset-right));
        }
    }
}
@supports (padding:calc(max(0px))) { /* [3] */
    @media only screen and (min-width: 50em) {
        .o-wrapper {
            padding-left: calc(max(5rem, env(safe-area-inset-left)));
            padding-right: calc(max(5rem, env(safe-area-inset-right)));
        }
    }
}

Output: main.css (mobile styles)

.o-wrapper {
    padding: 0 2rem;
    /* [1] */
}

@supports (padding: calc(constant(safe-area-inset-left))) {
    /* [2] */
    .o-wrapper {
        padding-left: calc(2rem + constant(safe-area-inset-left));
        padding-right: calc(2rem + constant(safe-area-inset-right));
    }
}

@supports (padding: calc(max(0px))) {
    /* [3] */
    .o-wrapper {
        padding-left: calc(max(2rem, env(safe-area-inset-left)));
        padding-right: calc(max(2rem, env(safe-area-inset-right)));
    }
}

@supports (padding: calc(constant(safe-area-inset-left))) {
    /* [2] */
}

@supports (padding: calc(max(0px))) {
    /* [3] */
}

Output: only-screen-and-min-width-50em.css

@media only screen and (min-width: 50em) {
    .o-wrapper {
        padding-left: 5rem;
        padding-right: 5rem
    }

    .o-wrapper {
        padding-left: calc(5rem + constant(safe-area-inset-left));
        padding-right: calc(5rem + constant(safe-area-inset-right))
    }

    .o-wrapper {
        padding-left: calc(max(5rem,env(safe-area-inset-left)));
        padding-right: calc(max(5rem,env(safe-area-inset-right)))
    }
}
SassNinja commented 4 years ago

@stevepiron it has taken a while... but now it should work for you (when you place @supports in @media)

stevepiron commented 4 years ago

@SassNinja I've received a bunch of notifications about it 😄 Thank you for fixing that!