Quick Start Guide | |
---|---|
Tutorial Concept | Learn advanced cell styling techniques in a JavaScript spreadsheet using SpreadJS. This tutorial shows how to implement dynamic highlights, hover effects, conditional formatting, and validation styles to create interactive spreadsheet UIs. |
What You Will Need | NPM Package: @mescius/spread-sheets |
Controls Referenced | SpreadJS - JavaScript Spreadsheet Component Documentation | Online Demo Explorer |
The industry leading JavaScript spreadsheet control, SpreadJS, is widely recognized for delivering Excel-like features along with powerful customization options, making it a top choice for web-based spreadsheet applications. While the official SpreadJS documentation provides solid guidance on basic cell styling, many real-world projects call for more dynamic and interactive styling approaches tailored to user actions and data context.
In this blog post, we’ll dive into advanced cell styling techniques that extend beyond the standard documentation. You’ll learn how to apply dynamic highlights, context-aware formatting, and create reusable style patterns all designed to enhance your spreadsheets’ look and feel. Whether you’re building a custom Excel-like interface or adding rich data visualization features, these practical examples will help you improve user experience and make your SpreadJS applications more engaging and usable.
Advanced Cell Styling & Formatting in JavaScript Spreadsheets
- Styling a Cell When It’s Focused
- Styling Selection Color with CSS
- Multi-Selection Range Styling
- Styling Cells Containing Formulas
- Styling Invalid Formula Cells
- Styling Cells on Hover
- Applying Alternating Row Styles
- Styling Empty or Required Cells
- Styling Row and Column Headers
- Conditional Formatting for Dynamic Styling
- Reusing Styles with Named Styles
Download a Free Trial of the Industry Leading JavaScript Spreadsheet, SpreadJS, Today!
1. Styling a Cell When It Is Focused
While SpreadJS provides native selection highlighting, developers can customize this experience further by applying a specific background color or style to the focused cell.
In this example, we use the SelectionChanged event to track when the focused cell changes. Each time the user selects a new cell, we apply a custom style using setStyle(row, col, style) to highlight it and we also remove the style from the previously focused cell. To achieve this, we maintain state using two variables prevRow
and prevCol
which store the location of the last focused cell so its style can be cleared. Additionally, we apply the same custom style to the initially focused cell when the spreadsheet first loads, ensuring a consistent appearance from the start.
function initSpread() {
sheet.setValue(0, 0, "Click on cell you want to highlight");
// Define the focused style
const focusedStyle = new GC.Spread.Sheets.Style();
focusedStyle.backColor = "#e0f7fa";
focusedStyle.borderTop = new GC.Spread.Sheets.LineBorder("blue", GC.Spread.Sheets.LineStyle.thin);
focusedStyle.borderBottom = new GC.Spread.Sheets.LineBorder("blue", GC.Spread.Sheets.LineStyle.thin);
focusedStyle.borderLeft = new GC.Spread.Sheets.LineBorder("blue", GC.Spread.Sheets.LineStyle.thin);
focusedStyle.borderRight = new GC.Spread.Sheets.LineBorder("blue", GC.Spread.Sheets.LineStyle.thin);
let prevRow = -1;
let prevCol = -1;
// Bind SelectionChanged event to apply style on selection
sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, function (e, args) {
// Clear style from previously focused cell
if (prevRow >= 0 && prevCol >= 0) {
sheet.setStyle(prevRow, prevCol, new GC.Spread.Sheets.Style());
}
const sel = args.newSelections[0];
const row = sel.row;
const col = sel.col;
prevRow = row;
prevCol = col;
// Apply custom focused style
sheet.setStyle(row, col, focusedStyle);
});
// Apply style to initial selection on load
const selections = sheet.getSelections();
if (selections && selections.length > 0) {
const row = selections[0].row;
const col = selections[0].col;
prevRow = row;
prevCol = col;
sheet.setStyle(row, col, focusedStyle);
}
}
initSpread();
Try for yourself here in our live Style Focused Cell JS CodeMine sample or check out our documentation.
2. Styling Selection Color with CSS
SpreadJS allows developers to customize the appearance of the selection highlight to better align with your application's design system. While the default selection style works for most scenarios, you may want to use brand-specific colors or improve visibility for accessibility purposes.
In this example, we attempt to style the selection area by targeting the internal .gc-selection
class using CSS. The goal is to give selected cells a purple border and a soft violet background, making the active selection clearer and more visually distinct.
.gc-selection {
border-color: purple;
background-color: rgba(238, 210, 245, 0.5);
}
Try this yourself with our live Custom Selection Color JS CodeMine.
3. Multi-Selection Range Styling
In this example, we listen to the SelectionChanged event and apply a custom background color (#d9ead3, a soft green) to each selected range. Before applying new styles, we clear any previously applied cell styles to avoid overlapping or leftover highlights.
function initSpread() {
const multiSelectStyle = new GC.Spread.Sheets.Style();
multiSelectStyle.backColor = "#d9ead3";
sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, function (e, args) {
sheet.suspendPaint();
// Clear previous styles
sheet.clear(
0, 0,
sheet.getRowCount(),
sheet.getColumnCount(),
GC.Spread.Sheets.SheetArea.viewport,
GC.Spread.Sheets.StorageType.style
);
// Apply style to each selected range
args.newSelections.forEach(function (range) {
for (let r = range.row; r < range.row + range.rowCount; r++) {
for (let c = range.col; c < range.col + range.colCount; c++) {
sheet.setStyle(r, c, multiSelectStyle);
}
}
});
sheet.resumePaint();
});
}
initSpread();
Check out live Multi-Selection Range Styling JS CodeMine sample to learn more.
4. Styling Cells Containing Formulas
Highlighting cells that contain formulas can help users distinguish between static values and dynamic calculations, especially in large spreadsheets. SpreadJS allows you to detect when a formula is entered and style the corresponding cell accordingly.
In this example, we listen for the EditEnded event to detect when the user finishes editing a cell. We then check whether the cell contains a formula using getFormula(row, col)
. If it does, we apply a custom style: a green background, bold font, and subtle top/bottom borders to visually indicate that the cell contains a calculation.
function initSpread() {
sheet.setValue(0, 0, "Enter a formula and the cell will be styled");
sheet.bind(GC.Spread.Sheets.Events.EditEnded, function (e, args) {
const row = args.row;
const col = args.col;
const formula = sheet.getFormula(row, col);
if (formula) {
// Apply style when formula is present
const style = new GC.Spread.Sheets.Style();
style.backColor = "#e8f5e9"; // light green background
style.font = "bold 12px Segoe UI";
style.foreColor = "#2e7d32"; // dark green text
style.borderBottom = new GC.Spread.Sheets.LineBorder("#81c784", GC.Spread.Sheets.LineStyle.thin);
style.borderTop = new GC.Spread.Sheets.LineBorder("#a5d6a7", GC.Spread.Sheets.LineStyle.hair);
sheet.setStyle(row, col, style);
} else {
//Remove style when formula is removed
sheet.setStyle(row, col, new GC.Spread.Sheets.Style());
}
});
}
initSpread();
Try for yourself with our JS Formula Cell Style CodeMine sample.
5. Styling Invalid Formula Cells
A common usability enhancement in JS Excel-like applications is visually signaling when a cell contains an invalid formula. SpreadJS provides built-in support for this through CellStatesType.invalidFormula, allowing you to define custom styles that alert users to issues with formula syntax or usage.
In this example, we enable invalid formula detection by setting spread.options.allowInvalidFormula = true. We then use the cellStates.add() method to apply a red dashed border around any cell that contains an invalid formula helping users quickly identify and correct input errors.
initSpread(spread);
function initSpread(spread) {
// Allow invalid formulas
spread.options.allowInvalidFormula = true;
const sheet = spread.getActiveSheet();
// Add a prompt in cell A1
sheet.setValue(0, 0, "Type an invalid formula like: =SUM()");
// Create the style to apply to invalid formula cells
const invalidStyle = new GC.Spread.Sheets.Style();
const dashedRedBorder = new GC.Spread.Sheets.LineBorder('red', GC.Spread.Sheets.LineStyle.mediumDashed);
invalidStyle.borderTop = dashedRedBorder;
invalidStyle.borderBottom = dashedRedBorder;
invalidStyle.borderLeft = dashedRedBorder;
invalidStyle.borderRight = dashedRedBorder;
// Define a range covering the entire sheet
const fullRange = new GC.Spread.Sheets.Range(0, 0, sheet.getRowCount(), sheet.getColumnCount());
// Apply the style to cells with invalid formulas
sheet.cellStates.add(
fullRange,
GC.Spread.Sheets.CellStatesType.invalidFormula,
invalidStyle,
GC.Spread.Sheets.SheetArea.viewport
);
}
Try this live JavaScript spreadsheet Invalid Formula Styling demo here.
6. Styling Cells on Hover
Adding hover effects in a JavaScript spreadsheet app makes it easier for users to see where their mouse is, improving how they navigate. Whether for interactive tutorials, validation feedback, or simply a polished UI, hover styling help guide the user’s focus without requiring clicks or input.
In this example, we define a custom style that changes the background and text color when a user hovers over a specific range of cells. We apply the style using GC.Spread.Sheets.CellStatesType.hover.
sheet.setValue(0, 0, "Hover over this cell");
sheet.setValue(1, 0, "And this one too");
sheet.setValue(2, 0, "Also this");
sheet.setColumnWidth(0, 200);
var hoverStyle = new GC.Spread.Sheets.Style();
hoverStyle.backColor = "#ffe0e0";
hoverStyle.foreColor = "#990000";
// Define a range (A1:A10)
var hoverRange = new GC.Spread.Sheets.Range(0, 0, 10, 1);
sheet.cellStates.add(
hoverRange,
GC.Spread.Sheets.CellStatesType.hover,
hoverStyle
);
Try this live JavaScript spreadsheet Cell Hover Style demo here.
7. Applying Alternating Row Styles
Alternating row styles are a simple yet powerful way to improve the readability of data-heavy JS spreadsheets. This technique helps users visually group data by applying a different background color to every other row commonly known as zebra striping.
In this example, we manually loop through the rows and apply a light gray background to even-numbered rows (0, 2, 4, ...). This method gives you full control over styling and can be easily adapted for dynamic datasets or custom patterns beyond just two alternating colors.
function initSpread() {
// Apply alternating row background color
for (let row = 0; row < 100; row++) {
if (row % 2 === 0) {
for (let col = 0; col < 10; col++) {
const style = new GC.Spread.Sheets.Style();
style.backColor = "#f9f9f9";
sheet.setStyle(row, col, style);
}
}
}
}
initSpread();
Check out the online Alternating Row Styles JS spreadsheet demo.
8. Styling Empty or Required Cells
In many spreadsheets, some cells must be filled out by the user. To help users see which cells are empty, we add a red border around those cells. This gives a clear but gentle reminder without stopping the user from typing.
In this example, we use the tag()
method to mark every cell as "required", attaching metadata to each cell. We then listen to the EditEnded
event to detect when a user finishes editing a cell. If the edited cell is empty, a red border is applied to signal that input is needed. Once the cell contains a valid value, the red border is removed automatically, giving clear visual validation.
function initSpread() {
const rowCount = sheet.getRowCount();
const colCount = sheet.getColumnCount();
// Mark all cells as required
for (let row = 0; row < rowCount; row++) {
for (let col = 0; col < colCount; col++) {
sheet.getCell(row, col).tag("required");
}
}
// Validate required fields on edit end
sheet.bind(GC.Spread.Sheets.Events.EditEnded, function (e, args) {
const row = args.row;
const col = args.col;
const cell = sheet.getCell(row, col);
if (cell.tag() === "required") {
const value = cell.value();
const style = new GC.Spread.Sheets.Style();
if (value === undefined || value === null || value === "") {
const redBorder = new GC.Spread.Sheets.LineBorder("red", GC.Spread.Sheets.LineStyle.thin);
style.borderTop = redBorder;
style.borderBottom = redBorder;
style.borderLeft = redBorder;
style.borderRight = redBorder;
} else {
style.borderTop = null;
style.borderBottom = null;
style.borderLeft = null;
style.borderRight = null;
}
sheet.setStyle(row, col, style);
}
});
}
initSpread();
Try for yourself with our live Empty Cell Styling JS CodeMine demo.
9. Styling Row and Column Headers
The row and column headers in SpreadJS help users understand the data by showing labels for rows and columns. By default, these headers use a simple gray style, but SpreadJS gives you full control to customize them and better match the visual design of your spreadsheet or application.
In this example, we apply distinct styles to both row and column headers using setStyle()
. The row headers get a blue background with white text, while the column headers are styled with a dark background and gold text, each using bold fonts for clarity.
function initSpread() {
// Show row and column headers
sheet.options.rowHeaderVisible = true;
sheet.options.colHeaderVisible = true;
// Row header style
const rowHeaderStyle = new GC.Spread.Sheets.Style();
rowHeaderStyle.backColor = "#4A90E2";
rowHeaderStyle.foreColor = "#FFFFFF";
rowHeaderStyle.font = "bold 13px Segoe UI";
sheet.setStyle(-1, 0, rowHeaderStyle, GC.Spread.Sheets.SheetArea.rowHeader);
// Column header style
const colHeaderStyle = new GC.Spread.Sheets.Style();
colHeaderStyle.backColor = "#333333";
colHeaderStyle.foreColor = "#FFD700";
colHeaderStyle.font = "bold 13px Segoe UI";
sheet.setStyle(0, -1, colHeaderStyle, GC.Spread.Sheets.SheetArea.colHeader);
}
initSpread();
To learn more check our the online JS CodeMine demo or read our Set Header Color documentation.
10. Conditional Formatting for Dynamic Styling
Conditional formatting in web applications enables dynamic styling based on the values within cells, allowing you to build smarter, more reactive spreadsheet UIs. It’s perfect for scenarios like highlighting errors or trends without having to manually style individual cells.
In this example, we define a cell style that turns text red and apply it using a conditional formatting rule that targets all negative values in the JS worksheet. The rule is applied to the entire sheet using the special range(-1, -1, -1, -1)
syntax.
function initSpread() {
// Add positive and negative data
const sampleData = [
[10, -5, 15],
[-2, 7, -8],
[3, -1, 12]
];
for (let r = 0; r < sampleData.length; r++) {
for (let c = 0; c < sampleData[r].length; c++) {
sheet.setValue(r, c, sampleData[r][c]);
}
}
// Define style for negative numbers
const negativeStyle = new GC.Spread.Sheets.Style();
negativeStyle.foreColor = "red";
// Define a range that targets the entire sheet
const fullSheetRange = new GC.Spread.Sheets.Range(-1, -1, -1, -1);
// Apply conditional formatting rule highlighting negative values in red
sheet.conditionalFormats.addCellValueRule(
GC.Spread.Sheets.ConditionalFormatting.ComparisonOperators.lessThan,
"0",
"",
negativeStyle,
[fullSheetRange]
);
}
initSpread();
Try for yourself here with our Live JS CodeMine demo or learn more here with out Conditional Formatting documentation.
11. Reusing Styles with Named Styles
When many cells use the same formatting, it’s easier to create reusable named styles to keep things organized and simple to manage. Instead of recreating a style object repeatedly, you can define it once, register it globally, and apply it by name wherever needed.
In this example, we create a named style called “highlightStyle"
, set its background and text color, and register it using spread.addNamedStyle()
. Then we apply it to cell D4 using setStyleName()
allowing consistent styling across the spreadsheet with just a single line of code.
function initSpread() {
// Define a named style
const highlightStyle = new GC.Spread.Sheets.Style();
highlightStyle.name = "highlightStyle";
highlightStyle.backColor = "#ffff99";
highlightStyle.foreColor = "#000";
// Add the named style to the workbook
spread.addNamedStyle(highlightStyle);
// Apply to cell D4
sheet.setStyleName(3, 3, "highlightStyle");
}
initSpread();
To learn more, see our JS CodeMine sample and read the Set Named Style documentation.
Download a Free Trial of the Industry Leading JavaScript Spreadsheet, SpreadJS, Today!
Conclusion
By applying these advanced cell styling techniques, you can create more interactive and visually appealing Excel-like spreadsheets in JavaScript applications using SpreadJS. Experience with these methods to enhance your user experience and bring your web-based spreadsheet applications to the next level. Stay tuned for more tips and best practices to make the most of SpreadJS’ powerful features!