Using SCSS and React, I have made a little table (not an HTML table), which is responsive based on variable-width cells. That is to say, each cell whose width is not variable has a flex-basis
value, whereas variable width cells have a flex-grow
value of 1
and no flex-basis
.
The example I have used is for match odds for football, but really it could be used for anything that involves dynamic data, i.e. dealing with varying-length names.
Please, may I have feedback on my use of flexbox and appropriate usage of BEM, and whether such a solution to the problem is better than using either HTML tables or divs with table-cell
classnames?
SCSS:
$odds-cell-width: 60px;
$more-cell-width: 100px;
.c-marketview {
display: flex;
flex-flow: column nowrap;
max-width: 1300px;
min-width: 850px;
margin: auto;
* {
box-sizing: border-box;
}
}
.c-marketview__header,
.c-marketview__item {
display: flex;
flex-flow: row nowrap;
border: 1px solid goldenrod;
}
.c-marketview__header__match-result,
.c-marketview__header__over-under,
.c-marketview__header__double-chance {
flex: 0 0 $odds-cell-width * 3;
display: flex;
flex-flow: row wrap;
.c-marketview__header__title {
flex: 1 100%;
}
}
.c-marketview__header__empty {
display: flex;
flex: 1 1 auto;
}
.c-marketview__header__empty--end,
.c-marketview__item__more {
flex: 0 1 $more-cell-width;
}
.c-marketview__item__match {
display: flex;
flex: 1;
flex-flow: column wrap;
}
.c-marketview__item__time {
display: flex;
flex-flow: column nowrap;
}
.c-marketview__item__time {
flex: 0 1 60px;
}
.u-center {
display: flex;
align-items: center;
justify-content: center;
}
.is-odds {
flex: 0 0 $odds-cell-width;
@extend .u-center;
}
JSX:
function renderHeader() {
return (
<div className="c-marketview__header">
<div className="c-marketview__header__empty"></div>
<div className="c-marketview__header__match-result">
<span className="c-marketview__header__title u-center">Match Result</span>
<span className="c-marketview__header__selection is-odds">1</span>
<span className="c-marketview__header__selection is-odds">X</span>
<span className="c-marketview__header__selection is-odds">2</span>
</div>
<div className="c-marketview__header__over-under">
<span className="c-marketview__header__title u-center">Over / Under</span>
<span className="c-marketview__header__selection is-odds">O/U</span>
<span className="c-marketview__header__selection is-odds">O</span>
<span className="c-marketview__header__selection is-odds">U</span>
</div>
<div className="c-marketview__header__double-chance">
<span className="c-marketview__header__title u-center">Double Chance</span>
<span className="c-marketview__header__selection is-odds">HD</span>
<span className="c-marketview__header__selection is-odds">HA</span>
<span className="c-marketview__header__selection is-odds">AD</span>
</div>
<div className="c-marketview__header__empty--end"></div>
</div>
);
}
function renderMarketViewItem(clock, date, name, competition, matchOdds, oUOdds, dCOdds, moreAmount) {
return (
<div className="c-marketview__item">
<div className="c-marketview__item__time u-center">
<div className="c-marketview__item__time__clock">{clock}</div>
<div className="c-marketview__item__time__date">{date}</div>
</div>
<div className="c-marketview__item__match">
<div className="c-marketview__item__match__name">{name}</div>
<div className="c-marketview__item__match__competiton">{competition}</div>
</div>
<div className="c-marketview__item__match-result--1 is-odds">{matchOdds[0]}</div>
<div className="c-marketview__item__match-result--2 is-odds">{matchOdds[1]}</div>
<div className="c-marketview__item__match-result--3 is-odds">{matchOdds[2]}</div>
<div className="c-marketview__item__over-under--1 is-odds">{oUOdds[0]}</div>
<div className="c-marketview__item__over-under--2 is-odds">{oUOdds[1]}</div>
<div className="c-marketview__item__over-under--3 is-odds">{oUOdds[2]}</div>
<div className="c-marketview__item__double-chance--1 is-odds">{dCOdds[0]}</div>
<div className="c-marketview__item__double-chance--2 is-odds">{dCOdds[1]}</div>
<div className="c-marketview__item__double-chance--3 is-odds">{dCOdds[2]}</div>
<div className="c-marketview__item__more u-center">
<div className="c-marketview__item__more__lozenge">+{moreAmount} more</div>
</div>
</div>
)
}
var Main = React.createClass({
render() {
var header = renderHeader();
return (
<div className="c-marketview">
{header}
{renderMarketViewItem(
'20:00',
'19 Jun',
'Bosnia-Hercegovina vs Democratic Republic of Congo',
'Euro 2016',
['5.00', '3.20', '1.80'],
['8.50', '46.00', '1.00'],
['1.91', '1.33', '1.15'],
'104'
)}
{renderMarketViewItem(
'20:00',
'19 Jun',
'Bulgaria vs Romania',
'Euro 2016',
['5.00', '1.50', '4.20'],
['2.50', '46.00', '1.00'],
['5.91', '1.33', '3.15'],
'102'
)}
{renderMarketViewItem(
'20:00',
'20 Jun',
'England vs Slovakia',
'Euro 2016',
['1.10', '2.10', '7.70'],
['3.50', '46.00', '1.00'],
['7.94', '7.34', '7.14'],
'1002'
)}
{renderMarketViewItem(
'20:00',
'20 Jun',
'Extremely Long Team Name Goes Right Here vs Super Ridiculous Long Name 2 Woooooooooooooow',
'Euro 2024',
['15.10', '22.10', '237.70'],
['53.50', '436.00', '13.00'],
['75.94', '71.34', '72.14'],
'10002'
)}
</div>
)
}
})
ReactDOM.render(<Main/>, document.getElementById('market-view'));