Style grid header cells and column groups.
The grid exposes many theme parameters starting header* for customising header appearance:
const myTheme = themeQuartz.withParams({
headerHeight: '30px',
headerTextColor: 'white',
headerBackgroundColor: 'black',
headerCellHoverBackgroundColor: 'rgba(80, 40, 140, 0.66)',
headerCellMovingBackgroundColor: 'rgb(80, 40, 140)',
});For the full list, see the Headers section of the parameters reference.
When the theme parameters are not enough you can use CSS classes, in particular ag-header, ag-header-cell, and ag-header-group-cell:
.ag-header {
font-family: cursive;
}
.ag-header-group-cell {
font-weight: normal;
font-size: 22px;
}
.ag-header-cell {
font-size: 18px;
}"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { AllEnterpriseModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [AllEnterpriseModule];
const myTheme = themeQuartz.withParams({
headerHeight: "30px",
headerTextColor: "white",
headerBackgroundColor: "black",
headerCellHoverBackgroundColor: "rgba(80, 40, 140, 0.66)",
headerCellMovingBackgroundColor: "rgb(80, 40, 140)",
});
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const theme = useMemo<Theme | "legacy">(() => {
return myTheme;
}, []);
const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
{
headerName: "Group 1",
children: [{ field: "athlete", minWidth: 170 }, { field: "age" }],
},
{
headerName: "Group 2",
children: [
{ field: "country" },
{ field: "year" },
{ field: "date" },
{ field: "sport" },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
],
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
editable: true,
filter: true,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
theme={theme}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.ag-header {
font-family: cursive;
}
.ag-header-group-cell {
font-weight: normal;
font-size: 22px;
}
.ag-header-cell {
font-size: 18px;
}
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Header Column Borders and Resize Handles Copy Link
Header Column Borders appear between every column, whereas Resize Handles only appear on resizeable columns (Group 1 in the example below).
const myTheme = themeQuartz.withParams({
headerColumnBorder: { color: 'purple' },
headerColumnBorderHeight: '80%',
headerColumnResizeHandleColor: 'orange',
headerColumnResizeHandleHeight: '25%',
headerColumnResizeHandleWidth: '5px',
});"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { AllEnterpriseModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [AllEnterpriseModule];
const myTheme = themeQuartz.withParams({
headerColumnBorder: { color: "purple" },
headerColumnBorderHeight: "80%",
headerColumnResizeHandleColor: "orange",
headerColumnResizeHandleHeight: "25%",
headerColumnResizeHandleWidth: "5px",
});
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const theme = useMemo<Theme | "legacy">(() => {
return myTheme;
}, []);
const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
{
headerName: "Group 1",
children: [
{ field: "athlete", minWidth: 170, resizable: true },
{ field: "age", resizable: true },
],
resizable: true,
},
{
headerName: "Group 2",
children: [
{ field: "country" },
{ field: "year" },
{ field: "date" },
{ field: "sport" },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
],
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
editable: true,
filter: true,
resizable: false,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
theme={theme}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Style Header on Filter Copy Link
Each time a Column Filter is applied to a column, the CSS class ag-header-cell-filtered is added to the header. This can be used for adding style to headers that are filtered.
The example below adds some styling to ag-header-cell-filtered, so when you filter a column you will notice the column header change.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
AllCommunityModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
GridState,
ModuleRegistry,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [AllCommunityModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "age", maxWidth: 120 },
{ field: "country" },
{ field: "year", maxWidth: 120 },
{ field: "sport" },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 150,
filter: true,
};
}, []);
const initialState = useMemo<GridState>(() => {
return {
filter: {
filterModel: {
country: {
filterType: "text",
type: "contains",
filter: "us",
},
},
},
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
initialState={initialState}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.ag-header-cell-filtered {
background-color: #1b6d8544;
}
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Styling the First and Last Columns Copy Link
You can style all first and last column headers (Grouped, Non-Grouped and Floating Filters) using CSS by targeting the .ag-column-first and .ag-column-last selectors as follows:
.ag-header-group-cell.ag-column-first {
background-color: #2244cc66; /* bluest */
}
.ag-header-cell.ag-column-first {
background-color: #2244cc44; /* bluer */
}
.ag-floating-filter.ag-column-first {
background-color: #2244cc22; /* blue */
}
.ag-header-group-cell.ag-column-last {
background-color: #33cc3366; /* greenest */
}
.ag-header-cell.ag-column-last {
background-color: #33cc3344; /* greener */
}
.ag-floating-filter.ag-column-last {
background-color: #33cc3322; /* green */
}"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
AllCommunityModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [AllCommunityModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
{
headerName: "Athlete Details",
children: [
{ field: "athlete" },
{ field: "age", maxWidth: 120 },
{ field: "country" },
],
},
{ field: "year", maxWidth: 100 },
{
headerName: "Sport Details",
children: [
{ field: "total", columnGroupShow: "closed" },
{ field: "gold", columnGroupShow: "open" },
{ field: "silver", columnGroupShow: "open" },
{ field: "bronze", columnGroupShow: "open" },
],
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 150,
filter: true,
floatingFilter: true,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.ag-header-group-cell.ag-column-first {
background-color: #2244cc66; /* bluest */
}
.ag-header-cell.ag-column-first {
background-color: #2244cc44; /* bluer */
}
.ag-floating-filter.ag-column-first {
background-color: #2244cc22; /* blue */
}
.ag-header-group-cell.ag-column-last {
background-color: #33cc3366; /* greenest */
}
.ag-header-cell.ag-column-last {
background-color: #33cc3344; /* greener */
}
.ag-floating-filter.ag-column-last {
background-color: #33cc3322; /* green */
}
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
};