Skip to content

Commit

Permalink
feat: use range context in media queries
Browse files Browse the repository at this point in the history
resolves #1
  • Loading branch information
jasonraimondi committed Jan 18, 2023
1 parent 3fe6917 commit 8e9bd4d
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 71 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ yarn-error.log
node_modules/
dist/
coverage/
package/
34 changes: 21 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,21 @@ Generates mobile first `@custom-media` rules from a configuration object.
pnpm add -D postcss-custom-media-generator
```

This plugin depends on further processing using one of the following methods:

- If you use [postcss-preset-env], just make sure this plugin is loaded before postcss-preset-env, and you should be good to go.
- [postcss-custom-media] and [postcss-media-minmax].

## Usage

Pass in a configuration of desired global media queries. You can pass in any arbitrary key, and any valid CSS media query value. Strings will be passed directly, and numbers will be turned into mobile-first queries.
**Note: This plugin should be run first in your PostCSS pipeline.**

Pass in a configuration of desired global media queries.

A configuration object like this:
You can pass in a key of any arbitrary string, and a value of either a string or a number.

- Strings should be valid CSS media queries
- Numbers will be turned into mobile-first queries.

```js
module.exports = {
Expand All @@ -30,7 +40,7 @@ module.exports = {
md: 800,
lg: 1000
},
"postcss-custom-media": {}
"postcss-preset-env": {},
}
};
```
Expand All @@ -40,19 +50,16 @@ Becomes:
```postcss
@custom-media --light (prefers-color-scheme: light);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --sm-only (min-width: 600px) and (max-width: 799px);
@custom-media --sm (min-width: 600px);
@custom-media --md-only (min-width: 800px) and (max-width: 999px);
@custom-media --md (min-width: 800px);
@custom-media --lg (min-width: 1000px);
@custom-media --lg-only (min-width: 1000px);
@custom-media --sm-only (600px <= width < 800px);
@custom-media --sm (600px <= width);
@custom-media --md-only (800px <= width < 1000px);
@custom-media --md (800px <= width);
@custom-media --lg (1000px <= width);
```

When combined with the [postcss-custom-media] plugin:
Write your css like this:

```postcss
@custom-media --md (min-width: 800px);
@media (--md) {
/* styles for medium viewport */
}
Expand All @@ -64,5 +71,6 @@ When combined with the [postcss-custom-media] plugin:
}
```

[postcss-media-minmax]: https://github.com/postcss/postcss-media-minmax
[postcss-custom-media]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-media
[postcss-custom-env]: https://github.com/csstools/postcss-plugins/tree/main/plugin-packs/postcss-preset-env
[postcss-preset-env]: https://github.com/csstools/postcss-plugins/tree/main/plugin-packs/postcss-preset-env
39 changes: 39 additions & 0 deletions src/createMobileFirstMediaQueries.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { createMobileFirstMediaQueries } from "./createMobileFirstMediaQueries";

it("outputs custom media queries object built for mobile first designs", () => {
expect(
createMobileFirstMediaQueries({
sm: 600,
md: 800,
lg: 1000,
xl: 1200,
xxl: 1400,
}),
).toEqual({
"--sm": `600px <= width`,
"--sm-only": `600px <= width < 800px`,
"--md": `800px <= width`,
"--md-only": `800px <= width < 1000px`,
"--lg": `1000px <= width`,
"--lg-only": `1000px <= width < 1200px`,
"--xl": `1200px <= width`,
"--xl-only": `1200px <= width < 1400px`,
"--xxl": `1400px <= width`,
});
});

it("sorts mixed inputs before creating custom media queries", () => {
expect(
createMobileFirstMediaQueries({
tablet: 800,
desktop: 1400,
phone: 400,
}),
).toEqual({
"--phone": `400px <= width`,
"--phone-only": `400px <= width < 800px`,
"--tablet": `800px <= width`,
"--tablet-only": `800px <= width < 1400px`,
"--desktop": `1400px <= width`,
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ type CustomMediaInput = Record<string, number>;
// type CustomMediaResponseKey = `--${string}`;
type CustomMediaResponse = Record<string, string>;

export function generateMediaQueries(map: CustomMediaInput): CustomMediaResponse {
export function createMobileFirstMediaQueries(map: CustomMediaInput): CustomMediaResponse {
const result: CustomMediaResponse = {};

const sortedInput = sortInput(map);
Expand All @@ -13,11 +13,10 @@ export function generateMediaQueries(map: CustomMediaInput): CustomMediaResponse
for (const [key, breakpoint] of entries) {
const nextBreakpoint = values[cnt + 1];
if (nextBreakpoint) {
result[`--${key}-only`] = `(min-width: ${breakpoint}px) and (max-width: ${nextBreakpoint - 1}px)`;
result[`--${key}`] = `(min-width: ${breakpoint}px)`;
result[`--${key}-only`] = `${breakpoint}px <= width < ${nextBreakpoint}px`;
result[`--${key}`] = `${breakpoint}px <= width`;
} else {
result[`--${key}`] = `(min-width: ${breakpoint}px)`;
result[`--${key}-only`] = result[`--${key}`];
result[`--${key}`] = `${breakpoint}px <= width`;
}
cnt++;
}
Expand Down
41 changes: 0 additions & 41 deletions src/generate_media_queries.spec.ts

This file was deleted.

18 changes: 8 additions & 10 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ it("handles number values as mobile-first", async () => {

await run(
"",
`@custom-media --sm-only (min-width: 600px) and (max-width: 799px);
@custom-media --sm (min-width: 600px);
@custom-media --md-only (min-width: 800px) and (max-width: 999px);
@custom-media --md (min-width: 800px);
@custom-media --lg (min-width: 1000px);
@custom-media --lg-only (min-width: 1000px)`,
`@custom-media --sm-only (600px <= width < 800px);
@custom-media --sm (600px <= width);
@custom-media --md-only (800px <= width < 1000px);
@custom-media --md (800px <= width);
@custom-media --lg (1000px <= width)`,
config,
);
});
Expand All @@ -53,10 +52,9 @@ it("handles number and string values", async () => {
await run(
"a { color: red; }",
`@custom-media --dark (prefers-color-scheme: dark);
@custom-media --sm-only (min-width: 600px) and (max-width: 799px);
@custom-media --sm (min-width: 600px);
@custom-media --md (min-width: 800px);
@custom-media --md-only (min-width: 800px);
@custom-media --sm-only (600px <= width < 800px);
@custom-media --sm (600px <= width);
@custom-media --md (800px <= width);
a { color: red; }`,
config,
);
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Root } from "postcss";
import { AtRule } from "postcss";
import { generateMediaQueries } from "./generate_media_queries";
import { createMobileFirstMediaQueries } from "./createMobileFirstMediaQueries";

const plugin = (opts: Record<string, string> = {}) => {
const { strings, numbers } = extractNumbers(opts);
const config = Object.assign(strings, generateMediaQueries(numbers), {});
const config = Object.assign(strings, createMobileFirstMediaQueries(numbers), {});

return {
postcssPlugin: "postcss-custom-media-generator",
Expand Down

0 comments on commit 8e9bd4d

Please sign in to comment.