Responsive styling and viewport dependant JavaScript.

#Screen Ranges

These ranges represent the most common ones we use for responsive design.

Test

#Screen Range Media Queries

Media queries for CSS that is only applied within. All range names are inclusive, for example mobileTabletDesktop means mobile and tablet and desktop.


Queryrange startrange end
screenRangeQueries.mobile0px699px
screenRangeQueries.tablet700px991px
screenRangeQueries.desktop992px1839px
screenRangeQueries.widescreen1840pxInfinity
screenRangeQueries.mobileTablet0px991px
screenRangeQueries.tabletDesktop700px1839px
screenRangeQueries.desktopWidescreen992pxInfinity
screenRangeQueries.mobileTabletDesktop0px1839px
screenRangeQueries.tabletDesktopWidescreen700pxInfinity
import { screenRangeQueries } from "@blocks/theme";

const ExampleComponent = styled.div`
  /* mobile first */
  background-color: green;

  /* 992px to Infinity */
  ${screenRangeQueries.desktopWidescreen} {
    background-color: purple;
  }
`;

#Screen Range Effect Hook

The useScreenRangeEffect executes range based javascript. Use with caution, this may cause unwanted re-renders, when setting state.

Callback arguments

  • isInRange is true and false according to matching the range
  • reason shows the phase of when it was matched, "mount" or "change"
import { useScreenRangeEffect } from "@blocks/theme";
import { useState } from "react";

const Component = () => {
  const [isDesktopOrWidescreen, setIsDesktopOrWidescreen] = useState(false);

  useScreenRangeEffect(
    "desktopWidescreen", // screen range name
    (isInRange, reason) => {
      setIsDesktopOrWidescreen(isInRange);
    },
    [],
  );
};

Hint: For touch and mouse distinction, consider using useDeviceEffect().

#Breakpoints

Breakpoint values are accessible via breakpoints object from @blocks/theme.


Breakpointviewport width
xxs431px
xs700px
sm992px
md1200px
lg1400px
xl1600px
xxl1840px

#Breakpoint Media Queries

Use screenRangeQueries whenever possible, they're for special cases where the ranges are not flexible enough.

// try to use screenRangeQueries whenever possible.
import { breakpointRangeQueries } from "@blocks/theme";

const ExampleComponent = styled.div`
  background-color: green;

  /* from 0px to 1199px */
  ${breakpointRangeQueries["*-md"]} {
    background-color: red;
  }
`;

#Syntax of the breakpoint queries

Wildcard based open boundaries.


Queryrange startrange enddescription
breakpointRangeQueries["xs-md"]700px1199pxeverything between xs (inclusive)
up to the md breakpoint (exclusive)
breakpointRangeQueries["*-md"]0px1199pxeverything from zero
up to the md breakpoint (exclusive)
breakpointRangeQueries["md-*"]1200pxInfinityeverything from md (inclusive)
to Infinity

#Breakpoint Range Effects

The useBreakpointRangeEffect hook is a simple way to listen to the breakpoint changes in JavaScript.

The callback arguments

  • isInRange is true and false according to matching the range
  • reason shows the phase of when it was matched, "mount" or "change"

For more flexibility, consider using useMediaQueryEffect() instead.

import { useBreakpointRangeEffect } from "@blocks/theme";
import { useState } from "react";

const Component = () => {
  const [inRange, setInRange] = useState(false);

  useBreakpointRangeEffect(
    "md-*", // breakpoint range query key
    (isInRange, reason) => {
      setInRange(isInRange);
    },
    [],
  );
};

#Media Query Effect Hook

The useMediaQueryEffect hook is a more flexible way to listen to the media query changes in JavaScript. It leverages the window.matchMedia API under the hood: MDN matchMedia.

import { useMediaQueryEffect } from "@blocks/theme";
import { useState } from "react";

const Component = () => {
  const [isLandscape, setIsLandscape] = useState(false);

  useMediaQueryEffect(
    "(orientation: landscape)", // media query
    (queryDidMatch) => {
      setIsLandscape(queryDidMatch);
    },
    [],
  );
};

const CustomQueryComponent = () => {
  // You can also use this hook to build custom screen range queries
  const [inRange, setInRange] = useState(false);

  // 992px - 1199px
  const customScreenRangeQuery = `@media (min-width: ${breakpoints.sm}px) and (max-width: ${breakpoints.md - 1}px)`;
  useMediaQueryEffect(customScreenRangeQuery, (queryDidMatch) =>
    setInRange(queryDidMatch),
  );
};