Skip to content

Instantly share code, notes, and snippets.

Created July 5, 2016 16:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/6a2dd18f11cb19b8a46953df88774a02 to your computer and use it in GitHub Desktop.
Save anonymous/6a2dd18f11cb19b8a46953df88774a02 to your computer and use it in GitHub Desktop.
QEvBwg
<div id="app"></div>
<br/>
<label for="container-height">Height (px):</label>
<input name="container-height" size="10" id="container-height" type="text" value="80"/>
<button type="button" onClick="changeContainerHeight()">Adjust</button>
/*
* Utility functions
*/
const requestAnimationFrame = window.requestAnimationFrame || (fn=>setTimeout(fn,30));
function changeContainerHeight() {
const cont = document.querySelector('.app-container');
const input = document.querySelector('#container-height');
cont.style.height = input.value + 'px';
}
/*
* HOC to allow Components to receive their width/height as
* props on render.
*/
const Responsive = (WrappedComponent) => class _Responsive extends React.Component {
constructor(props) {
super(props);
this.state = { width: null, height: null };
this.rafCallback = this.getUpdatedSize.bind(this);
}
getUpdatedSize() {
const node = ReactDOM.findDOMNode(this._comp);
let height = node.offsetHeight;
let width = node.offsetWidth;
if (height != this.state.height || width != this.state.width) {
this.setState({
height,
width
});
}
requestAnimationFrame(this.rafCallback);
}
componentDidMount() {
requestAnimationFrame(this.rafCallback);
}
componentWillUnmount() {
cancelInterval(this._interval);
}
render() {
return <WrappedComponent ref={(ref) => this._comp = ref} {...this.props} dimensions={{...this.state}} />;
}
};
/*
* Price Component, which should have responsive text sizing
* based on it's container's height.
*/
@Responsive
class Price extends React.Component {
render() {
const { prefix, price, suffix, subtext, subtextPosition = "bottom" } = this.props;
const [ dollars, cents = '00' ] = price.split('.');
const subcls = ["subtext", subtextPosition].join(' ');
return (
<div ref={(ref)=>this._container = ref} className={"price"}>
<div className={"price-container"}>
<div className={"prefix"}>{ prefix }</div>
<div className={"symbol"}>$</div>
<span className={"dollars"}>{ dollars }</span>
<div className={"cents"}>
{ cents }
<span className={"suffix"}>{ suffix }</span>
</div>
</div>
<div className={subcls}>{ subtext }</div>
</div>
);
}
componentDidUpdate() {
this.resizeFont();
}
resizeFont() {
window.requestAnimationFrame(() => {
const { width, height } = this.props.dimensions;
const factor = this.props.subtext && this.props.subtextPosition == 'bottom' ? .7 : .9;
this._container.style.fontSize = (height * factor).toFixed(2) + 'px';
});
}
}
ReactDOM.render(
<div className={"app-container"}>
<Price prefix="from"
price="29.99"
suffix="/mo"
subtext="for 12 months when bundled"
subtextPosition="right"/>
</div>,
document.getElementById('app')
);
<script src="https://fb.me/react-15.1.0.min.js"></script>
<script src="https://fb.me/react-dom-15.1.0.min.js"></script>
.app-container {
height: 80px;
background-color: rgba(0,0,0,.2);
overflow: hidden;
}
.price {
width: auto;
height: 100%;
font-size: 85%;
text-align: center;
}
.price-container {
display: inline-block;
position: relative;
height: auto;
text-align: center;
-webkit-transition: font-size .3s ease;
-moz-transition: font-size .3s ease;
-o-transition: font-size .3s ease;
transition: font-size .3s ease;
}
.prefix,
.symbol,
.cents {
position: absolute;
display: inline-block;
}
.symbol {
left: -0.6em;
top: .5em;
opacity: .5;
font-size: 30%;
}
.prefix {
left: -2.2em;
bottom: 0.6em;
font-size: 30%;
color: #999;
}
.cents {
left: 100%;
top: .4em;
opacity: .5;
font-size: 33%;
.suffix {
font-size: 80%;
}
}
.subtext {
text-align: center;
font-size: 20%;
opacity: .3;
&.bottom {
margin-top: -5px;
}
&.right {
display: inline-block;
}
&.hidden {
display: none;
}
}
.dollars {
font-size: 100%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment