Responsive helpers
Ranges
Instead of "breakpoints", we'll use different name: "ranges". "Breakpoint" represents a single point and we think it's easier to reason about responsiveness using "range".
Range
Range
represents single range of resolutions.
Examples of ranges:
xs
- a range representing vertical mobile phones (from 0 to 419px)md
- a range representing standard vertical tablets (from 960px to 1200px)xl
- a range representing desktops (from 1600px to infinity)
let xs = "xs" 0 419; // a range named "xs" spanning from 0 to 419.xsfrom // 0xsto // 419xsname // "xs"xsisInfinite // false, this range is finitexsisCurrent // true if window.innerWidth is between 0 and 419, otherwise false // Ranges can be infinitelet xl = "xl" 1600 undefined; // a range named "xl" spanning from 1600 to infinity.xlfrom // 1600xlto // undefinedxlisInfinite // true
Range
object has helper methods for CSS-in-JS:
// `mediaQuery` method generates media query string from `Range`xsmediaQuery // "(max-width: 419px)"xlmediaQuery // "(min-width: 1600px)" let md = "md" 720 1280;mdmediaQuery // "(min-width: 720px) and (max-width: 1280px)" // `css` method generates CSS for specific rangexs // "@media (max-width: 419px) { font-size: 10px; }" md// @media (min-width: 720px) and (max-width: 1280px) { // font-size: 10px; // max-width: 200px;// }
RangeSet
Usually (in 99% of cases), you don't create Range
instances directly (via new Range
) in your project.
What you should do is to define entire range set that covers all resolutions from 0 to infinity. This is what RangeSet
class is for.
RangeSet
represents a resolution spectrum divided into ranges. You can create RangeSet
like this:
let rangeSet = xs: 0 sm: 420 md: 992 lg: 1400 xl: 1920
Here we created RangeSet
with 5 ranges: xs
, sm
, md
, lg
, xl
.
You can access specific Range
from RangeSet
in 2 ways:
// Via get` methodrangeSetfrom // 0rangeSetto // 419 // Directly as a propertyrangeSetmdfrom // 992rangeSetmdto // 1399
RangeSet
has couple of helpers allowing creating new ranges based on your set:
// `to` methodrangeSet // returns new `Range` spanning from 0 to 1399rangeSet // returns new `Range` spanning from 0 to 1919 // `from` methodrangeSet // return new `Range` spanning from 992 to infinityrangeSet // return new `Range` spanning from 1400 to infinity // `fromTo` methodrangeSet // return new `Range` spanning from 992 to 1919rangeSet // return new `Range` spanning from 0 to 991
There are other helper methods for RangeSet
:
rangeSetcurrent; // return currently active `Range` (based on current window.innerWidth value) rangeSetfirst // returns lowest `Range` (xs)rangeSetsecond // return second lowest `Range` (sm) rangeSetlast // returns highest `Range` (xl)
RangeSet.main
You should always have one major RangeSet
in your project and assign it to RangeSet.main
property.
RangeSet.main
has special meaning and is used by other helpers functions (like rslin
).
By default, RangeSet.main
has following ranges:
xs: 0 // all phones in vertical mode are below this. Minimal 320px for iPhone SE, maximal 414px for iPhone 6+. All Galaxy Note etc, have lower ones. xs_plus: 420 // horizontal phones + untypical small tablets (like Galaxy Nexus), least important resolution. sm: 720 // all vertical tablets start with 720px (Surface). iPads and Galaxy Tab, etc, all are above. Nexus 7 is an exception, should behave as SM. md: 960 // standard horizontal tablets are > 960px (even with Nexus 7), like iPad or Galaxy lg: 1200 // smaller laptops (1280) and big tablets in horizontal mode (iPad Pro, Galaxy 10) lg_plus: 1366 // most laptops 13 inch and 15 inch (1366, 1440px) xl: 1600 // bigger resolution laptops (1600) xl_plus: 2000 // desktops bigger than full HD
If you want to change them, in some init place of your project you should run sth like this:
RangeSetmain = xs: 0 sm: 420 md: 992 lg: 1400 xl: 1920;
ResponsiveSize
Very often it's easier to think about values as a function of resolution, not just a single value.
ResponsiveSize
ResponsiveSize
is a class that represents a CSS value as a function (for all resolutions).
Imagine we have a container which width is 90vw
for resolutions below 1280px, 80vw
between 1280 and 1600px and has fixed width (1280px) from 1600px up.
Normally we use media queries to code this in CSS. However, we might think that container width is actually a function of resolution.
let containerWidth = 0: "80vw" 1280: "90vw" 1600: "1280px";
Now in your CSS-in-JS you can do sth like this.
// we use styled-components format
let Container = styled.div`
margin: 0 auto;
${containerWidth.css('width')}
`;
Voila. This will automatically translate to:
{@)) @)
If RangeSet.main
is set, you can also use range names instead of resolutions:
let responsiveSize = xs: "80vw" lg: "90vw" xl: "1280px";
rs
shorthand
There's a useful shorthand for creating responsive sizes:
let responsiveSize = ; let responsiveSize2 = ; // constant value 100let responsiveSize3 = ; // constant value "80vw"let responsiveSize4 = ; // might also clone `ResponsiveSize`
It's useful when you create a React Component which takes some size as a prop. Let's say we create Container
with configurable width:
// styled-components format again
let Container = styled.div`
margin: 0 auto;
${props => rs(props.width).css('width')}
`;
// You can now pass width as a standard single value
let container1 = <Container width={100} />;
// But also you can use responsive size
let container2 = <Container width={{
xs: 100,
md: 200,
xl: 300
}} />;
Such API is very nice to write and read.
rslin
rslin
is a helper function that creates linear ResponsiveSize
.
Examples:
let linearSize = ; // Now `linearSize` has following value:// - from 0 to RangeSet.main.second.from: 10px// - from RangeSet.main.second.from to RangeSet.main.last.to: linear function from 10px to 50px// - from RangeSert.main.last.to to infinity: 50px;`;
Linear sizing is great for handling responsiveness of font sizes and vertical spacings. Calling linearSize.css('font-size')
returns:
{@)) @)
This CSS is complicated but works and you don't have to worry about it. rslin
takes care of this.
IMPORTANT
In order to make it work, RangeSet.main
must be defined.
This should be pretty clear because rslin
takes 2 parameters and should know which resolutions are mapped to these values. First value is always mapped to RangeSet.main.first.to
(mobile phone resolution usually) and second one to RangeSet.main.last.from
(big desktop).