Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Handsontable Css Dev

ASecurity

Use when working with Handsontable themes, CSS custom properties, SCSS files, theme tokens, or visual styling - covers theme architecture, CSS variable API, the strict CSS/JS separation rule, and the four-layer process for adding or renaming theme tokens

22,052 stars
0 votes
0 copies
1 views
Added 9/19/2026
developmentjavascripttypescriptjavagitapi

Works with

api

Security Analysis

A92/100
mediumInstalls packages at runtime which could introduce malicious dependencies

Scanned 9/19/2026

$npx -y skills add handsontable/handsontable --skill handsontable-css-dev --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Handsontable Css Dev?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Handsontable Css Dev
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/handsontable-handsontable-css-dev/badge)](https://www.skillsdirectory.com/skills/handsontable-handsontable-css-dev)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: handsontable-css-dev
path: handsontable/src/{styles,themes}/**
description: Use when working with Handsontable themes, CSS custom properties, SCSS files, theme tokens, or visual styling - covers theme architecture, CSS variable API, the strict CSS/JS separation rule, and the four-layer process for adding or renaming theme tokens
---

# Theme and CSS Development

## Themes

Handsontable ships three themes, each with a standard and a `-no-icons` variant (6 bundles total):

| Theme class | Description |
|---|---|
| `ht-theme-main` | Default modern theme |
| `ht-theme-classic` | Legacy/classic look |
| `ht-theme-horizon` | Horizon design |

No-icons variants: `ht-theme-main-no-icons`, `ht-theme-classic-no-icons`, `ht-theme-horizon-no-icons`.

## CSS Custom Properties Are Public API

Theme customization is done entirely through CSS variables. These variables are the **public API** for theming. Renaming or removing a CSS custom property is a **breaking change** and requires a legacy compatibility path (keep the old variable working).

## Cell padding must come from the variables, not from the cell

`StylesHandler#getDefaultRowHeight()` computes
`--ht-line-height + 2 * --ht-cell-vertical-padding + border-bottom-width`, and Walkontable sizes a
table's scroll range from the summed row heights. Writing `padding` onto a `td` leaves the variable at
the theme's value, so the engine computes a row height the cells do not have and the scroll range comes
out wrong. Override `--ht-cell-vertical-padding` / `--ht-cell-horizontal-padding` and derive the `td`
padding from them.

A nested grid built inside a hidden container masks this: its styles cache is empty, the derived row
height reads `null`, and the engine measures the DOM instead.

## Strict CSS/JS Separation

Never mix CSS into JavaScript files. CSS and JS are always in separate files. This is enforced by convention and code review.

## File Structure

| Path | Contents |
|---|---|
| `src/styles/` | SCSS source files (base styles) |
| `src/themes/` | Theme-specific SCSS files |
| `handsontable/styles/` | Compiled CSS output (committed to repo) |
| `browser-targets.js` | Supported browser list |

## Build Commands

- `build:styles` - Compile SCSS to CSS.
- `build:themes-*` - Build theme-specific assets.
- Stylelint validates all CSS/SCSS (`npm run stylelint --prefix handsontable`).

## No `:has()` in stylesheets (lint-enforced)

The custom rule `handsontable/no-has-selector` (error) bans the `:has()` relational pseudo-class in all
`src/**/*.{css,scss}`. In Chrome, a `:has()` rule anywhere in the document makes every matching DOM
mutation re-run style invalidation at a cost that scales with the whole host page — and the grid mutates
the DOM on every scroll re-render, so `:has()` turns scrolling janky on large/complex host pages. Drive
the style from a **class that JS toggles on the target element** instead (the `SelectionManager`
header-accent stamping — `#markActiveHeaderNeighbors` / the `-seam` taggers — is the reference pattern).
The rule lives in `.config/plugin/stylelint/` (a pnpm `file:` dependency, the SCSS analog of
`eslint-plugin-handsontable`; **copied, not symlinked — run `pnpm install` after editing it**). A
genuinely necessary exception (a `:has()` on state that is NOT re-evaluated during a scroll — dialog
focus, dropdown selection, the offscreen `.htGhostTable`) uses
`// stylelint-disable-next-line handsontable/no-has-selector -- <reason>` with a reason that says why it
is off the scroll path.

## Browser Compatibility

All CSS features must work in browsers listed in `browser-targets.js` (latest 2 major versions of Chrome, Firefox, Safari, Edge). The `eslint-plugin-compat` rule enforces this.

## Breaking Change Rules

- **Renaming/removing a CSS custom property** = breaking change. Keep the old variable working.
- **Renaming/removing a CSS class** = breaking change. Keep the old class in the DOM.
- **Always test all 3 themes** after any visual or styling change.

## Adding a New Theme Token - The Four-Layer Process

Handsontable's theme system maintains defense-in-depth across CSS and JS consumers, plus TypeScript support. A new token needs to land in **four layers** - updating fewer looks complete but breaks either the runtime DX or the type contract.

Use this flow whenever you add a `--ht-<component>-<property>` CSS variable or its matching JS token. Renaming or removing a token follows the same playbook plus a legacy-alias path (see Breaking Change Rules above).

### Layer 1 - Static CSS defaults (6 files)

```
handsontable/src/themes/static/css/theme/ht-theme-main.css
handsontable/src/themes/static/css/theme/ht-theme-main-no-icons.css
handsontable/src/themes/static/css/theme/ht-theme-classic.css
handsontable/src/themes/static/css/theme/ht-theme-classic-no-icons.css
handsontable/src/themes/static/css/theme/ht-theme-horizon.css
handsontable/src/themes/static/css/theme/ht-theme-horizon-no-icons.css
```

Each file defines the CSS custom property (`--ht-<kebab-case-name>`) and its resolved default for that theme. Values commonly reference existing lower-level tokens via `var(...)` rather than hardcoded colors, so downstream theme overrides keep cascading.

Group the new variable next to related ones (e.g. `pagination-button-*` next to `pagination-bar-*`) so the file stays scannable. All three themes should declare the same key set; only the resolved values differ.

**Symptom when missing**: the CSS variable is undefined in DevTools but the JS ThemeBuilder "works" in tests that don't assert rendered styles.

### Layer 2 - Token JS runtime defaults (3 files)

```
handsontable/src/themes/static/variables/tokens/main.ts
handsontable/src/themes/static/variables/tokens/classic.ts
handsontable/src/themes/static/variables/tokens/horizon.ts
```

These objects drive the `ThemeBuilder` class at runtime (the JS API for programmatic theming). Use camelCase keys that mirror the CSS variable - `paginationButtonBorderColor` maps to `--ht-pagination-button-border-color`. Values reference other tokens with the `'tokens.otherTokenName'` string syntax or primitive arrays like `['colors.palette.100', 'colors.palette.700']`.

**Symptom when missing**: `ThemeBuilder` doesn't recognize the token at runtime; users passing it to `createTheme()` get no-op behavior.

### Layer 3 - Validation allow-list (1 file)

```
handsontable/src/themes/engine/utils/validation.ts
```

The `VALID_TOKEN_KEYS` Set (around lines 319-363) is the **runtime DX guardrail**. If a user passes a token key not in this set, the ThemeBuilder logs `[ThemeBuilder] Unknown token key: "xxx"` to help them catch typos. Legitimate new tokens must be registered here or users get spurious warnings when they use your new API.

Add the key in the same semantic section as your CSS and tokens changes (e.g., under the `// Pagination` comment).

**Symptom when missing**: unit test `src/themes/engine/__tests__/builder.unit.js` fails the "should not warn for unknown token keys when using built-in tokens in createTheme" case. The test iterates every real token in `mainTokens` and asserts none trigger the warning - it exists specifically to catch drift between layer 2 and layer 3.

### Layer 4 - TypeScript type definitions (1 file)

```
handsontable/src/themes/types.ts
```

The `TokenKey` union (around line 79) is the **compile-time DX for TypeScript users**. Missing entry → TS consumers calling the API with your new token get a type error. The declaration is auto-generated into `tmp/themes/types.d.ts` by `build:types` — edit the source `src/themes/types.ts`, not the generated output.

Add the key in the same semantic section as the other layers. The `test:types` script (`npm run test:types --prefix handsontable`, which runs `tsc -p ./test/types`) enforces this.

**Symptom when missing**: `npm run test:types` fails with a `TokenKey` assignability error.

### Layer 5 (soft) - Public docs

```
docs/content/guides/styling/theme-customization/theme-customization.md
```

Not load-bearing for the runtime, but anything registered in the allow-list and type union is part of the public API contract - it belongs in the variables reference table on this page. Match the existing two-column pattern (CSS name + JS name, then description).

### Naming Convention

JS camelCase ↔ CSS kebab-case, prefixed with `--ht-`. The mapping is by convention - there is no generator, so consistency is on the author:

| JS token name | CSS variable |
|---|---|
| `paginationButtonBorderColor` | `--ht-pagination-button-border-color` |
| `secondaryButtonHoverBackgroundColor` | `--ht-secondary-button-hover-background-color` |
| `dialogContentPaddingHorizontal` | `--ht-dialog-content-padding-horizontal` |

### Consumption in SCSS

Reference the new variable from the component's SCSS file under `src/styles/components/` (for example, `_pagination.scss`). Default to `var(--ht-<name>)` - only use the `var(--ht-<name>, <fallback>)` form when a legacy compatibility fallback is genuinely needed, since a fallback can mask missing-variable bugs.

### Pre-Flight Checklist

Before committing token work, mentally walk the four layers plus tests:

1. CSS in all 6 theme files?
2. JS token in all 3 runtime files?
3. Registered in `validation.ts` allow-list?
4. Added to `TokenKey` in `src/themes/types.ts`?
5. `npm run test:unit --prefix handsontable --testPathPattern=themes` passes?
6. `npm run test:types --prefix handsontable` passes?
7. Docs table updated?

Attribution

handsontablehandsontable
View sourceMore from handsontable →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10311 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →