Nearsighted Paramecium Multiverse

    TypeScript icon, indicating that this package has built-in type declarations

    0.0.1 • Public • Published


    NPM version Actions Status PR Welcome

    A lightweight library to implement fully responsive REM based layouts in CSS-in-JS based libraries. Also SSR safe and won't break build if pre-rendered.


    Install this package with npm.

    npm i @phntms/layout


    Initialize a new Layout() instance. On creation, you can also define custom configs or leave blank to inherit the default config.

    To use, we recommend creating a global singleton file, this allows you to reference the layout anywhere in the project. Example singleton:

    import Layout from "@phntms/layout";
    export default new Layout();
    // Or...
    export default new Layout<"mobile" | "tablet" | "desktop">({
      mobile: {
        breakpoint: 768,
        targetViewportWidth: 375,
        // Number of columns to show below 767
        columns: 16,
      tablet: {
        breakpoint: 1032,
        targetViewportWidth: 1032,
        // Number of columns to show between 768 and 1031
        columns: 20,
      desktop: {
        breakpoint: 1440,
        targetViewportWidth: 1440,
        // Number of columns to show above 1032
        columns: 24,

    Note: If you want to have full control over your config and prefer not to use any defaults provided, you can set applyDefaultConfig to false.

    import Layout from '@phntms/layout';
    export default new Layout({...}, false);

    Then to use, simply import the newly created layout singleton file. For example:

    import layout from "~/layout";


    To apply the config set in the constructor and once the app has loaded, this method is required to initialize the layout. Example usage:

    import layout from "~/layout";


    Optional method used to unsubscribe from event listeners at end of lifecycle. Example usage:

    import layout from "~/layout";


    Used to convert PX values to REM. Example usage:

    import layout from "~/layout";
    layout.pxToRem(10, false, "desktop");

    In this example, we're converting 10px to rem at the targetScreenSize of desktop.

    But, what does that mean?

    Each breakpoint has a targetScreenSize. This is the size that we're basing our fluid rem values on. So in the example above, the default target is 1440, which means at a screen size of 1440px, the value will visually be 10px (0.167rem in rem).

    Other examples based on the default config:

    • Mobile: pxToRem(5, false, 'mobile') = Visually 5px at 375px.
    • Tablet: pxToRem(5, false, 'tablet') = Visually 5px at 1024px.
    • Desktop: pxToRem(5, false, 'desktop') = Visually 5px at 1440px.

    What about if the screen size is higher?

    The value will simply scale visually beyond 10px, though the actual rem value won't change.

    What about if the screen size is lower?

    Theres three different possible outcomes here.

    In the example above as pxAsMin is set to false, the value would visually scale below 10px until we reached a screen size of 0px or until we reach a new breakpoint.

    If pxAsMin was set to true, that value would stop visually scaling once the screen reaches 1440px in width.

    Alternatively, if pxAsMin is set to an integer value, such as 8px, the value would visually scale till it reaches 8px in size or a new breakpoint is reached.

    In all outcomes the value will be visually unaffected if scaling above the base value.

    Note: CSS max is used under the hood to clamp values, which means -${pxToRem(10, true, ...)} wouldn't work if this is enabled as the result - -max(10px, 0.167rem) would be invalid. To use negative values, define them inside as the px value. Or set this to false, at which point -${pxToRem(10, false, ...)} is valid as it would result in -0.167rem.


    Used to create grid columns, irrespective of the current breakpoint.

    import layout from "~/layout";

    This library works by dividing the screen into a number of columns, for example 24 by default on desktop. The nice part of this is that 1 gutter (on mobile, tablet, desktop or any breakpoint) = 1 rem.

    Note: We recommend only using columns for horizontal spacings, where vertical spacings should use pxToRem based values.


    Optional method used to toggle if column overlay is showing or not.

    import layout from "~/layout";

    Note: To use grid overlay, you need to additionally import overlay.css. For example:

    import "@phntms/layout/src/overlay.css";

    🍪 Example Usage

    The following examples are all in styled-components, though they would work in any other CSS-in-JS based libraries.

    Media Queries

    Due to how different browsers calculate media queries, when using rem based libraries such as this one, its recommended to use em values over px and rem. For further reading, see this article exploring the topic. With this in mind, following is an example of how you might want to layout global queries:

    const pxToEm = (px: number) => px / 16;
    export const BREAKPOINT_MOBILE =;
    /** 768px. */
    export const QUERY_GREATER_THAN_MOBILE = `(min-width: ${BREAKPOINT_MOBILE_AS_EM})`;
    export const BREAKPOINT_TABLET = DEFAULT_CONFIG.tablet.breakpoint;
    /** 1032px. */
    export const QUERY_GREATER_THAN_TABLET = `(min-width: ${BREAKPOINT_TABLET_AS_EM})`;
    export const BREAKPOINT_DESKTOP = DEFAULT_CONFIG.desktop.breakpoint;
    /** 1440px. */
    export const QUERY_GREATER_THAN_DESKTOP = `(min-width: ${BREAKPOINT_DESKTOP_AS_EM})`;

    Scaling Typography

    Combining the media queries above with type or any other value (such as paddings / margins etc), means you can then create values that scale fully based on the current breakpoint, for example:

    import { css } from "styled-components";
    import layout from "~/layout";
    export const TYPE_SIZE_LARGE = css`
      font-size: ${layout.pxToRem(17, 14, "mobile")};
        font-size: ${layout.pxToRem(17, 14, "tablet")};
        font-size: ${layout.pxToRem(17, 14, "desktop")};

    In this example, type will always maintain its base 17px font size at the targetViewportWidth of each breakpoint. Though if type has a small base value, we recommend always adding a minimum font size for type legibility to ensure it never becomes too small. Here we set a minimum of 14px.


    Here is an example of using the columns to create a fully fluid grid!

    import styled from 'styled-components';
    import layout from '~/layout';
    const Cards = styled.div`
      display: grid;
      grid-column-gap: ${layout.columns(1)};
      grid-template-columns: repeat(3, ${layout.columns(6)});
      // Can even be used alongside `pxToRem`!
      margin-bottom: ${layout.pxToRem(60, true, 'desktop')}

    🍰 Contributing

    Want to get involved, or found an issue? Please contribute using the GitHub Flow. Create a branch, add commits, and open a Pull Request or submit a new issue.

    Please read CONTRIBUTING for details on our CODE_OF_CONDUCT, and the process for submitting pull requests to us!


    npm i @phntms/layout

    DownloadsWeekly Downloads






    Unpacked Size

    43.7 kB

    Total Files


    Last publish


    • dhiaphntm
    • jpedersen
    • digitaljohn
    • paulomfj