I'm working in a React(NextJS) project using Material UI. I have some tables (MUI X Data Grid component) with different background colors in the column headers like this:
My problem is when I scroll horizontally very fast (not slowly but very fast), the color moves 1 space/column, so in the previous image you can see that the column "rank" for example, should be yellow and if I scroll horizontally very fast, it changes to red:
As you can see the colors move 1 space/column, this seems like a Material UI bug to me but I'm not sure...
This is my React component:
import React, { useState, useEffect } from 'react'
import { css } from '@emotion/react'
import PropTypes from 'prop-types'
import { cardCss } from '../CavMortal/grid/Grid'
import { fullHeight } from '../CavMortal/ScoreItem'
import { CardElevation } from '@findep/mf-landings-core'
import Grid from '@material-ui/core/Grid'
import { DataGrid } from '@mui/x-data-grid';
import { splitString} from '../../helpers/splitString'
const customCardCss = css`
${cardCss}
${fullHeight}
& [class*="MuiCardContent-root"] {
${fullHeight}
}
`
function TablaSubdireccion({ dataSubdirecciones, headerStyles }) {
const [columnsName, setColumnsName] = useState([])
const [rows, setRows] = useState([])
const getColumns = () => {
let columns = []
for(let i = 0; i < dataSubdirecciones.length; i++){
for(let j = 0; j < dataSubdirecciones[i].datosAgrupadorList.length; j++){
columns.push({
field: dataSubdirecciones[i].datosAgrupadorList[j].nombreDato,
headerName: dataSubdirecciones[i].datosAgrupadorList[j].nombreDato,
width: 130,
renderHeader: (params) => (
<div>
{
splitString(dataSubdirecciones[i].datosAgrupadorList[j].nombreDato).map((word) => (
<React.Fragment key={word}>
{word}
<br />
</React.Fragment>
))
}
</div>
),
})
}
}
return columns
}
const getRows = () => {
let rows = []
for (let i = 0; i < dataSubdirecciones.length; i++) {
let rowData = { id: i }
for (let j = 0; j < dataSubdirecciones[i].datosAgrupadorList.length; j++) {
rowData[dataSubdirecciones[i].datosAgrupadorList[j].nombreDato] = dataSubdirecciones[i].datosAgrupadorList[j].valorDato
}
rows.push(rowData)
}
return rows
}
useEffect(() => {
setColumnsName(getColumns())
setRows(getRows())
}, [dataSubdirecciones])
return(
<Grid item css={css`flex-grow: 1;`}>
<div style={{ height: 500, width: '99%' }}>
<CardElevation fullWidth noPadding css={customCardCss}>
<DataGrid
sx={headerStyles}
rows={getRows()}
columns={getColumns()}
hideFooterPagination={true}
hideFooter={true}
headerHeight={50}
pageSize={10}
/>
</CardElevation>
</div>
</Grid>
)
}
TablaSubdireccion.propTypes = {
dataSubdirecciones: PropTypes.array,
headerStyles: PropTypes.object,
}
export default TablaSubdireccion
And this is the object headerStyles, which is received as props and contains the colors for every nth child/column:
const MAIN_TABLES_HEADER_STYLES = {
'& .MuiDataGrid-columnHeaderTitleContainer': {
lineHeight: 1.5,
},
'.MuiDataGrid-columnSeparator': { display: 'none' },
'&.MuiDataGrid-root': { border: 'none' },
'& .MuiDataGrid-columnHeader:nth-child(1)': {
backgroundColor: '#000000',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(2)': {
backgroundColor: '#000000',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(3)': {
backgroundColor: '#9e9e9e',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(4)': {
backgroundColor: '#9e9e9e',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(5)': {
backgroundColor: '#9e9e9e',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(6)': {
backgroundColor: '#9e9e9e',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(7)': {
backgroundColor: '#6f0000',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(8)': {
backgroundColor: '#0075ad',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(9)': {
backgroundColor: '#d20000',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(10)': {
backgroundColor: '#ffd600',
color: '#000000',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(11)': {
backgroundColor: '#ffd600',
color: '#000000',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(12)': {
backgroundColor: '#ffd600',
color: '#000000',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(13)': {
backgroundColor: '#70b7bc',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(14)': {
backgroundColor: '#70b7bc',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(15)': {
backgroundColor: '#009f94',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(16)': {
backgroundColor: '#1e9a00',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(17)': {
backgroundColor: '#1e9a00',
color: '#ffffff',
fontWeight: 'bold',
},
'& .MuiDataGrid-columnHeader:nth-child(18)': {
backgroundColor: '#1e9a00',
color: '#ffffff',
fontWeight: 'bold',
},
}
Does anybody knows why this happens or how to fix it?
Thanks.
Using nth-child
styling isn't going to be reliable when horizontal scrolling is in play. The data grid does virtualization of columns when you scroll horizontally, so not all columns are always being rendered which will then throw off the nth-child
styling.
You can see this in action in this extreme example with 30 columns with customized colors on the 3rd and 4th via nth-child
CSS selectors: https://codesandbox.io/s/horizontal-scrolling-tlmqeh?file=/demo.tsx.
In that example the styling is done similar to your CSS:
<DataGridPro
sx={{
"& .MuiDataGrid-columnHeader:nth-child(3)": {
backgroundColor: "red",
color: "#ffffff",
fontWeight: "bold"
},
"& .MuiDataGrid-columnHeader:nth-child(4)": {
backgroundColor: "purple",
color: "#ffffff",
fontWeight: "bold"
}
}}
apiRef={apiRef}
onCellClick={handleCellClick}
hideFooter
{...data}
/>
You can fix this by instead using headerClassName
in the column definitions as shown in the documentation here: https://mui.com/x/react-data-grid/style/#styling-column-headers.
Here's a modification of my earlier example that uses headerClassName
: https://codesandbox.io/s/horizontal-scrolling-087h4m?file=/demo.tsx
const { data } = useDemoData({
dataSet: "Commodity",
rowLength: 100
});
// data.columns[0] is the hidden id column, so data.columns[1] is the column
// definition for the first visible column.
data.columns[3].headerClassName = "red-header";
data.columns[4].headerClassName = "purple-header";
...
<DataGridPro
sx={{
"& .MuiDataGrid-columnHeader.red-header": {
backgroundColor: "red",
color: "#ffffff",
fontWeight: "bold"
},
"& .MuiDataGrid-columnHeader.purple-header": {
backgroundColor: "purple",
color: "#ffffff",
fontWeight: "bold"
}
}}
apiRef={apiRef}
onCellClick={handleCellClick}
hideFooter
{...data}
/>