Skip to content

Instantly share code, notes, and snippets.

@AshKyd
Last active February 6, 2020 14:36
Show Gist options
  • Save AshKyd/841af4573af5f11480d1b66103cfdf4a to your computer and use it in GitHub Desktop.
Save AshKyd/841af4573af5f11480d1b66103cfdf4a to your computer and use it in GitHub Desktop.
A copy-pasteable React ratio box compont. Make boxes with customizable ratios. Should be pretty fast.
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
const topLevelStyle = {
position: 'relative'
};
const innerStyle = {
position: 'absolute',
left: 0,
top: 0,
width: '100%',
height: '100%'
};
function getStyles(ratio) {
const [width, height] = ratio.split('x');
return {
height: 0,
overflow: 'hidden',
position: 'relative',
paddingTop: `${Math.round((height / width) * 100)}%`
};
}
/**
* React CSS ratio box. Specify a ratio e.g. "16x9" to create a 16x9 box.
* e.g. `<RatioBox ratio="16x9" style={{ background: 'teal', width: 300 }} />`
*/
export default function RatioBox({
ratio,
children,
el: El = 'div',
style = {},
topLevelProps,
...props
}) {
const ratioStyle = useMemo(() => getStyles(ratio), [ratio]);
return (
<El
style={style ? { ...style, ...topLevelStyle } : topLevelStyle}
{...topLevelProps}
>
<div style={ratioStyle}>
<div style={innerStyle} {...props}>
{children}
</div>
</div>
</El>
);
}
RatioBox.propTypes = {
/** Ratio e.g. "4x3" */
ratio: PropTypes.string,
/** Children */
children: PropTypes.node,
/** The type of element to render. Default "div" */
el: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
/** Any specific styles to apply to the top level div */
style: PropTypes.object
};
import React from 'react';
import { storiesOf } from '@storybook/react';
import RatioBox from '.';
const stories = storiesOf('Components/RatioBox', module);
stories.add('300px wide 16x9', () => (
<RatioBox ratio="16x9" style={{ background: 'teal', width: 300 }} />
));
stories.add('300px wide 1x1', () => (
<RatioBox ratio="1x1" style={{ background: 'pink', width: 300 }} />
));
stories.add('100px wide 16x9', () => (
<RatioBox ratio="16x9" style={{ background: 'orange', width: 100 }} />
));
stories.add('100px wide 9x16', () => (
<RatioBox ratio="9x16" style={{ background: 'fuchsia', width: 100 }} />
));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment