Skip to main content

Media queries

Cacao provides a number of different media query variables that you can use in your code.

The media query variables use @custom-media. Because @custom-media is not yet supported the custom media PostCSS plugin is required as part of your build process.

Media query variables have the following naming conventions:

  • The prefix --m- is used to indicate that these are media queries.
  • The variable must be all lowercase.

These are almost always included in a project along with the base styles and the reset styles.

How to import into your CSS

Import this into your CSS with:

@import 'cacao-css/dist/media.css';

Typically this is included above other styles.

See Import Cacao CSS for more information.

How to use the media query variables

To use the media query variables you could put them within the @media declaration. For example, say that you want to use the large viewport media query, you can do something like this:

@media(--m-lg) {
.someSelector {
width: 50%;
}
}

Viewport media queries

The viewport sizes are:

SizeViewport pixel widthVariable"Below" variable"Only" variable
3xs240px--m-3xs--m-3xs-below--m-3xs-only
2xs360px--m-2xs--m-2xs-below--m-2xs-only
xs420px--m-xs--m-xs-below--m-xs-only
sm576px--m-sm--m-sm-below--m-sm-only
md768px--m-md--m-md-below--m-md-only
lg1024px--m-lg--m-lg-below--m-lg-only
xl1280px--m-xl--m-xl-below--m-xl-only
2xl1440px--m-2xl--m-2xl-below--m-2xl-only
3xl1600px--m-3xl--m-3xl-below--m-3xl-only
4xl1920px--m-4xl--m-4xl-below--m-4xl-only
5xl2560px--m-5xl--m-5xl-below--m-5xl-only

The media queries are "mobile first" meaning they target screen widths larger than the specified viewport pixel width. For example, the sm size targets screens larget than 576px.

@custom-media --m-sm (width >= 576px);

Each size also has a below and an only version.

The below version is used to target this screen width and below. It's not a "mobile-first" media query.

@custom-media --m-sm-below (width < 576px);

The only version is used to target the pixel range between this size and the size below it (or 0 if it's the 3xs size). For example, for the sm size

@custom-media --m-sm-only (360px <= width < 576px);

Accessibility preferences

These are used to identify the user's browser preferences for motion and transparency.

@custom-media --m-motion-ok (prefers-reduced-motion: no-preference);
@custom-media --m-motion-not-ok (prefers-reduced-motion: reduce);
@custom-media --m-opacity-ok (prefers-reduced-transparency: no-preference);
@custom-media --m-opacity-not-ok (prefers-reduced-transparency: reduce);

Data preferences

These are used to identify the user's browser preferences around data (typically cellular data usage).

/* Data preferences */
@custom-media --m-use-data-ok (prefers-reduced-data: no-preference);
@custom-media --m-use-data-not-ok (prefers-reduced-data: reduce);

Color preferences

These are used to identify the user's browser preferences around colors.

@custom-media --m-dark (prefers-color-scheme: dark);
@custom-media --m-light (prefers-color-scheme: light);
@custom-media --m-high-contrast (prefers-contrast: more);
@custom-media --m-low-contrast (prefers-contrast: less);
@custom-media --m-inverted-colors (inverted-colors: inverted);
@custom-media --m-forced-colors (forced-colors: active);

Orientation

These are used to identify the user's browser preferences around device orientation.

@custom-media --m-portrait (orientation: portrait);
@custom-media --m-landscape (orientation: landscape);

Pointer types

These are used to help identify the pointer type used with the device.

@custom-media --m-touch (hover: none) and (pointer: coarse);
@custom-media --m-stylus (hover: none) and (pointer: fine);
@custom-media --m-pointer (hover) and (pointer: coarse);
@custom-media --m-mouse (hover) and (pointer: fine);

Color capabilities

These are used to identify the color capabilities of the defice.

@custom-media --m-hd-color (dynamic-range: high) or (color-gamut: p3);

Source CSS

Below is the full source for the media queries.

media.css
/* =========================================================================== *\
Custom media queries.
Because @custom-media is not yet supported a PostCSS plugin is required.
https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-media

Naming conventions:
- The prefix --m- is used to indicate that these are media queries.
- The variable must be all lowercase.
\* =========================================================================== */

/* Accessibility preferences */
@custom-media --m-motion-ok (prefers-reduced-motion: no-preference);
@custom-media --m-motion-not-ok (prefers-reduced-motion: reduce);
@custom-media --m-opacity-ok (prefers-reduced-transparency: no-preference);
@custom-media --m-opacity-not-ok (prefers-reduced-transparency: reduce);

/* Data preferences */
@custom-media --m-use-data-ok (prefers-reduced-data: no-preference);
@custom-media --m-use-data-not-ok (prefers-reduced-data: reduce);

/* Color preferences */
@custom-media --m-dark (prefers-color-scheme: dark);
@custom-media --m-light (prefers-color-scheme: light);
@custom-media --m-high-contrast (prefers-contrast: more);
@custom-media --m-low-contrast (prefers-contrast: less);
@custom-media --m-inverted-colors (inverted-colors: inverted);
@custom-media --m-forced-colors (forced-colors: active);

/* Orientation */
@custom-media --m-portrait (orientation: portrait);
@custom-media --m-landscape (orientation: landscape);

/* Pointer types */
@custom-media --m-touch (hover: none) and (pointer: coarse);
@custom-media --m-stylus (hover: none) and (pointer: fine);
@custom-media --m-pointer (hover) and (pointer: coarse);
@custom-media --m-mouse (hover) and (pointer: fine);

/* Color capabilities */
@custom-media --m-hd-color (dynamic-range: high) or (color-gamut: p3);

/**
* Screen sizes
*
* These breakpoints are inspired by:
* - Pure.(https://purecss.io/grids/#:~:text=%3C/div%3E-,Default%20Media%20Queries,-When%20using%20Responsive)
* - Bootstrap (https://getbootstrap.com/docs/5.3/layout/breakpoints/#available-breakpoints)
* - Open Props (https://open-props.style/#media-queries)
* - https://gs.statcounter.com/screen-resolution-stats/mobile/worldwide
* - https://www.browserstack.com/guide/common-screen-resolutions
* - And our own usage in building websites
*
* Cacao is a mobile-first system.
* We don't use min-width or max-width because we follow Stylelint's media-feature-range-notation rule.
* https://stylelint.io/user-guide/rules/media-feature-range-notation/
*
* We use pixels instead of ems because that is the convention and it helps prevent a Safari bug with how they calculate ems (i.e. they use font-size + zoom level)
* https://cgamesplay.com/post/2023/05/19/stop-using-em-in-media-queries/
*
* https://www.joshwcomeau.com/css/surprising-truth-about-pixels-and-accessibility/ is another viewpoint on this and considers users increacing the default
* font size in their browser settings. Need to explore this more. 10/26/2024
*/

/* 3xs */
@custom-media --m-3xs (width >= 240px);
@custom-media --m-3xs-below (width < 240px);
@custom-media --m-3xs-only (0 <= width < 240px);

/* 2xs */
@custom-media --m-2xs (width >= 360px);
@custom-media --m-2xs-below (width < 300px);
@custom-media --m-2xs-only (0 <= width < 300px);

/* xs */
@custom-media --m-xs (width >= 420px);
@custom-media --m-xs-below (width < 420px);
@custom-media --m-xs-only (300px <= width < 420px);

/* sm */
@custom-media --m-sm (width >= 576px);
@custom-media --m-sm-below (width < 576px);
@custom-media --m-sm-only (360px <= width < 576px);

/* md */
@custom-media --m-md (width >= 768px);
@custom-media --m-md-below (width < 768px);
@custom-media --m-md-only (576px <= width < 768px);

/* lg */
@custom-media --m-lg (width >= 1024px);
@custom-media --m-lg-below (width < 1024px);
@custom-media --m-lg-only (768px <= width < 1024px);

/* xl */
@custom-media --m-xl (width >= 1280px);
@custom-media --m-xl-below (width < 1280px);
@custom-media --m-xl-only (1024px <= width < 1280px);

/* 2xl */
@custom-media --m-2xl (width >= 1440px);
@custom-media --m-2xl-only (1280px <= width < 1440px);
@custom-media --m-2xl-below (width < 1440px);

/* 3xl */
@custom-media --m-3xl (width >= 1600px);
@custom-media --m-3xl-only (1440px <= width < 1600px);
@custom-media --m-3xl-below (width < 1600px);

/* 4xl */
@custom-media --m-4xl (width >= 1920px);
@custom-media --m-4xl-only (1600px <= width < 1920px);
@custom-media --m-4xl-below (width < 1920px);

/* 5xl */
@custom-media --m-5xl (width >= 2560px);
@custom-media --m-5xl-only (1920px <= width < 2560px);
@custom-media --m-5xl-below (width < 2560px);