@phntms/layout
v0.0.1
Published
A lightweight library to implement fully responsive REM based layouts.
Downloads
7
Maintainers
Readme
layout
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.
Installation
Install this package with npm
.
npm i @phntms/layout
Usage
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";
initialize()
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";
layout.initialize();
destroy()
Optional method used to unsubscribe from event listeners at end of lifecycle. Example usage:
import layout from "~/layout";
layout.destroy();
pxToRem()
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')
= Visually5px
at 375px. - Tablet:
pxToRem(5, false, 'tablet')
= Visually5px
at 1024px. - Desktop:
pxToRem(5, false, 'desktop')
= Visually5px
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
.
columns()
Used to create grid columns, irrespective of the current breakpoint.
import layout from "~/layout";
layout.columns(1);
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.
toggleColumnOverlay()
Optional method used to toggle if column overlay is showing or not.
import layout from "~/layout";
layout.toggleColumnOverlay();
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 = DEFAULT_CONFIG.mobile.breakpoint;
const BREAKPOINT_MOBILE_AS_EM = `${pxToEm(BREAKPOINT_MOBILE)}em`;
/** 768px. */
export const QUERY_GREATER_THAN_MOBILE = `(min-width: ${BREAKPOINT_MOBILE_AS_EM})`;
export const BREAKPOINT_TABLET = DEFAULT_CONFIG.tablet.breakpoint;
const BREAKPOINT_TABLET_AS_EM = `${pxToEm(BREAKPOINT_TABLET)}em`;
/** 1032px. */
export const QUERY_GREATER_THAN_TABLET = `(min-width: ${BREAKPOINT_TABLET_AS_EM})`;
export const BREAKPOINT_DESKTOP = DEFAULT_CONFIG.desktop.breakpoint;
const BREAKPOINT_DESKTOP_AS_EM = `${pxToEm(BREAKPOINT_DESKTOP)}em`;
/** 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")};
@media ${QUERY_GREATER_THAN_MOBILE} {
font-size: ${layout.pxToRem(17, 14, "tablet")};
}
@media ${QUERY_GREATER_THAN_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
.
Grid
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!