Breakpoints

Breakpoints can be configured in your theme-variables.js. We will automatically create a number of helpers for you to then use these breakpoints in your shop's interface.

Default breakpoints

The default breakpoints are defined in theme-variables.js. Feel free to edit these as you like.

Copy
Copied
breakpoints: {
  xs: '20rem',
  sm: '40rem',
  md: '50rem',
  lg: '64rem',
  xl: '80rem'
}

Note there is a label defined for each breakpoint. These will be used in the helper components later.

Using breakpoints in Linaria components or css declarations

You can use the special helpers by importing them from Theme.js like this:

Copy
Copied
import { theme } from '../Theme.js'
import { css } from 'linaria';
import { styled } from 'linaria/react';

const Component = styled('div')`
  ${theme.above.md} {
    color: red;
  }
  ${theme.below.md} {
    color: blue;
  }
  ${theme.only.xs} {
    color: pink;
  }
  ${theme.between['md-lg']} {
    background: red;
  }
`

// You can also do the same inside `css`:
const styles = css`
  ${theme.above.md} {
    color: red;
  }
`

<Component>I'm super responsive</Component>
<div className={styles}>Me too!</div>

Hopefully these examples above all speak for themselves! The methods above will automatically be substituted with the appropriate media queries.

i.e. theme.above.md will be substituted with @media (min-width: 50rem) {} (assuming your md breakpoint is 50rem).

For more information about theming, check out the docs here.

Using breakpoints in JSX

There are also a number of components available at @jetshop/ui/Breakpoints that can be used to selectively render components based on the viewport width. For example, you may want to use this for creating a completely different view for mobile and desktop devices. Unlike when using simple CSS media queries, the mobile components will not render at all when viewed on a desktop viewport, and vice-versa.

The components work in the same way as the methods shown above. They are named Above, Below and Between.

Each of these components renders a function with matches as the arg. If this is true, the viewport matches your query. If it is false, it does not match your query.

Alternatively, if you just want to render something at a specific breakpoint, you can use the render prop

Render prop vs child-as-function with matches arg

There are two ways to use these components.

The child-as-fn pattern

The components all render a function as their immediate child with matches as an argument. matches will be either true or false, depending on if you media query has been matched. You can use this to determine what to display. This can be useful if you want to display one thing if the query does match, and another thing if the query does not match.

Example:

Copy
Copied
<Above breakpoint="sm">
  {(matches) =>
    matches
      ? "this will render above the sm breakpoint"
      : "this will render below the small breakpoint"
  }
</Above>

This is more performant than using one Above component and one Below component, and is the recommended approach for this situation.

The render prop

You can also use the render prop if you just want to render one thing at the given breakpoint. It takes a function that returns a ReactNode.

Example:

Copy
Copied
<Above
  breakpoint="sm"
  render={() => `this will render above the 'sm' breakpoint`}
/>

More examples

Resize your browser window to see these re-render at different breakpoints.

Copy
Copied
<Playground>
  <div>
    <h2>Above</h2>
    <hr />
    <Above breakpoint="md">
      {(matches) =>
        matches ? (
          <div style={{ color: "blue" }}>
            Your viewport is greater than the `md` breakpoint
          </div>
        ) : (
          <div style={{ color: "red" }}>
            Your viewport is smaller than the `md` breakpoint!
          </div>
        )
      }
    </Above>
  </div>

  <div style={{ marginTop: "2rem" }}>
    <h2>Below</h2>
    <hr />
    <Below breakpoint="md">
      {(matches) =>
        matches ? (
          <div style={{ color: "blue" }}>
            Your viewport is smaller than the `md` breakpoint
          </div>
        ) : (
          <div style={{ color: "red" }}>
            Your viewport is greater than the `md` breakpoint!
          </div>
        )
      }
    </Below>
  </div>

  <div style={{ marginTop: "2rem" }}>
    <h2>Between</h2>
    <hr />
    <Between breakpoints={["sm", "lg"]}>
      {(matches) =>
        matches ? (
          <div style={{ color: "orange" }}>
            Your viewport falls between `sm` and `lg`
          </div>
        ) : (
          <div style={{ color: "green" }}>
            Your viewport falls outside `sm` and `lg`. It's either huge or tiny!
          </div>
        )
      }
    </Between>
  </div>

  <div style={{ marginTop: "2rem" }}>
    <h2>Render prop</h2>
    <hr />
    <Above
      breakpoint="md"
      render={() =>
        `This will only render if your browser is larger than the 'md' breakpoint`
      }
    />
  </div>
</Playground>
Copyright © Norce 2023. All right reserved.