Skip to content

Instantly share code, notes, and snippets.

@emeraldsanto
Created February 24, 2021 16:34
Show Gist options
  • Save emeraldsanto/645b44d8ee767aa7ac1f7ea5465f953c to your computer and use it in GitHub Desktop.
Save emeraldsanto/645b44d8ee767aa7ac1f7ea5465f953c to your computer and use it in GitHub Desktop.
A basic implementation of a scaling stylesheet measurements
import { Dimensions, StyleSheet } from "react-native";
const SCALABLE_PROPERTIES = [
"padding",
"paddingStart",
"paddingEnd",
"paddingTop",
"paddingBottom",
"paddingRight",
"paddingLeft",
"paddingHorizontal",
"paddingVertical",
"margin",
"marginStart",
"marginEnd",
"marginTop",
"marginBottom",
"marginRight",
"marginLeft",
"marginHorizontal",
"marginVertical",
"fontSize",
"lineHeight",
"height",
"width",
"minHeight",
"minWidth",
"maxHeight",
"maxWidth",
"borderRadius"
];
const BASE_HEIGHT = 812; // iPhone X height (dev device);
/**
* This class is a wrapper around StylesSheet.create. It is used to make sure
* that all values entered into stylesheets are scaled as the screen height
* grows and shrinks on different devices. Developers should not use
* StyleSheet.create directly but use this class instead
*/
export class ScalingStyleSheet {
static scaleStyles<
T extends StyleSheet.NamedStyles<T> | StyleSheet.NamedStyles<any>
>(styles: T): T {
const styleKeys = Object.keys(styles) as (keyof typeof styles)[];
// Loop through all scalable properties and scale each property based on the
// `scaleProperty` function
styleKeys.forEach((styleProp) => {
const currentStyle = styles[styleProp];
const stylePropKeys = Object.keys(
currentStyle
) as (keyof typeof currentStyle)[];
stylePropKeys.forEach((prop) => {
if (
SCALABLE_PROPERTIES.includes(prop) &&
typeof currentStyle[prop] === "number"
) {
currentStyle[prop] = ScalingStyleSheet.scaleProperty(
currentStyle[prop]
);
}
});
});
return styles;
}
/**
* Scales all CSS properties in the app based on the height of the screen
*
* @param value The raw intended size of a CSS Property
*/
static scaleProperty(value: number): number {
const currentHeight = Dimensions.get("window").height;
if (currentHeight <= BASE_HEIGHT) {
return value;
}
const scaled = (currentHeight / BASE_HEIGHT) * value;
return Math.round((scaled + Number.EPSILON) * 100) / 100;
}
/**
* Creates and scales the stylesheet object
*
* @param styles CSS Style parameters
*/
static create<
T extends StyleSheet.NamedStyles<T> | StyleSheet.NamedStyles<any>
>(styles: T | StyleSheet.NamedStyles<T>): T {
return StyleSheet.create(ScalingStyleSheet.scaleStyles(styles));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment