Provisioning now restores all GUI customizations on reset+reprovision: - create_pod_espocrm.sh: deploy the version-controlled espocrm-custom/ tree (CTag entity, layouts, i18n, clientDefs, custom views, custom CSS) into the pod, then chown www-data and rebuild. Replaces the earlier inline CSS-only step. Adds a live-phase cache rebuild so customizations and the client cacheTimestamp are refreshed on every run. - espocrm-custom/: snapshot of custom/ and client/custom/ (source of truth). - snapshot_espocrm_custom.sh: refresh the snapshot from a running pod. - readme.md: usage, first-time host setup, image-update and reset workflows. - Include the task/instruction notes and plan.md for reference. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.9 KiB
EspoCRM Customization: Variable Column Widths for Markdown Tables
Instructions for Claude Code. Goal: integrate a custom CSS file into the EspoCRM provisioning so that Markdown tables in text fields get content-based column widths instead of equal fixed widths. The EspoCRM installation is generated by a shell script into a Podman pod, so both files below must be created by the provisioning script — manual edits inside the pod would be lost on the next provisioning run.
Problem and Root Cause
EspoCRM renders Markdown in text fields (e.g. Opportunity → Beschreibung) inside .complex-text containers. The core stylesheet contains this rule (verified live on this instance, EspoCRM 9.3.8, 2026-06-06):
.alert table, .alert > .message table, .complex-text table,
.confirm-message table, .popover-content table {
table-layout: fixed;
width: 100%;
}
table-layout: fixed distributes the table width equally across all columns regardless of content. Measured effect on a 4-column table in a record detail view: every column 200 px wide, causing short columns (Nr., Bew.) to waste space and the long Anforderung column to wrap into unnecessarily tall rows.
With table-layout: auto, columns size to their content. Verified by live style injection on the test record: column widths became 37 / 112 / 49 / 604 px — exactly the desired result.
Solution: EspoCRM Custom CSS Mechanism
EspoCRM's official mechanism for custom stylesheets (docs): register the CSS file in the cssList metadata. Both involved directories (client/custom/, custom/) are upgrade-safe — EspoCRM upgrades do not touch them. The CSS filename is arbitrary; we use the declarative name table-var-col.css.
File 1 (new): <espocrm-root>/client/custom/css/table-var-col.css
/**
* Variable column widths for Markdown tables in text fields.
*
* EspoCRM core CSS forces `table-layout: fixed; width: 100%` on
* `.complex-text table`, which makes all columns equally wide.
* `auto` lets columns size to content instead.
*
* Registered via custom/Espo/Custom/Resources/metadata/app/client.json (cssList).
*/
.complex-text table {
table-layout: auto !important;
width: auto !important;
max-width: 100% !important;
}
Notes:
- The selector deliberately targets only
.complex-text(text fields on record views), not the alert/popover tables of the core rule. !importantguards against load-order variations;cssListentries are appended after the theme stylesheet, but this makes the override robust either way.
File 2 (new or merge): <espocrm-root>/custom/Espo/Custom/Resources/metadata/app/client.json
{
"cssList": [
"__APPEND__",
"client/custom/css/table-var-col.css"
]
}
IMPORTANT — merge, do not overwrite: This instance already has GUI customizations. If client.json already exists, append the path to the existing cssList array (keeping "__APPEND__" as its first element) and leave all other keys untouched. Check first.
Integration into the Provisioning Script
- Locate where the script already injects EspoCRM GUI customizations and follow the same convention (e.g.
podman cp, volume mount, or heredoc). - Create both files after the EspoCRM installation step.
- Match file ownership/permissions to the other EspoCRM application files (typically the webserver user inside the container, e.g.
www-data:www-data). The CSS file must be readable by the webserver. - Clear the cache afterwards —
cssListis metadata and is cached:
podman exec <container> php /var/www/html/clear_cache.php
# or, if the script already performs a rebuild:
podman exec <container> php /var/www/html/rebuild.php
(Adapt container name and EspoCRM root path to the script's actual values.)
Testing
- Persistence test (the actual requirement): re-run the provisioning script from scratch, then verify both files exist inside the pod:
podman exec <container> ls -l /var/www/html/client/custom/css/table-var-col.css /var/www/html/custom/Espo/Custom/Resources/metadata/app/client.json - Log in to the CRM, hard-reload (
Ctrl+F5). In DevTools → Network, filter fortable-var-col→ the stylesheet must load with HTTP 200. - Open the test record (4-column Markdown table in
Beschreibung):https://crm.creature-go.com/#Opportunity/view/6a23fc99e2391e7be - Visual check: columns
Nr.,Einordnung,Bew.at minimal width,Anforderungtakes the remaining space; rows are one to two lines instead of uniformly tall. - Programmatic check in the DevTools console:
getComputedStyle(document.querySelector('.complex-text table')).tableLayout
// expected: "auto" (without the fix: "fixed")
- Regression check: open a record whose description contains no table and one with other Markdown (lists, headings) — rendering must be unchanged. Existing GUI customizations must still be active.