# Useful CSS Stuff

**URL:** <https://forum.inductiveautomation.com/t/useful-css-stuff/95414>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [September 2, 2024, 1:58am UTC](https://forum.inductiveautomation.com/t/useful-css-stuff/95414 "2024-09-02T01:58:19Z")\
**Posts on this page:** 1\
**Showing post:** 62

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [December 6, 2025, 11:52am UTC](https://forum.inductiveautomation.com/t/useful-css-stuff/95414/62 "2025-12-06T11:52:17Z")

</div>

# Alternative Alarm Status Table Styling - Use Pills for Priority and State columns

Disclaimer: I haven’t tested any of this all that thoroughly yet!

I had a request from a customer to change the alarm status table styles. This was a bit of fun (and headache).

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/0/603dbc7656b437d42c3946d8a6336003206acb02.png)

This requires CSS and a bit of JS injection (required for the splitting of the **State** values).

It has a number of parts:

1. Alarm Status Table component which contains specific rowStyles

2. Markdown Javascript injector component which converts the State column text into separate components and adds them into a flex

3. CSS to add to the Advanced Stylesheet

If you just want to import a single View, here’s the project export in 8.3.2. You’ll still need to copy in the styling into the adv. stylesheet though.

[AlarmStatusTable-AlternateStyling.zip](https://forum.inductiveautomation.com/uploads/short-url/bxmxvvFb25YMjEu797rw3iS37uk.zip) (44.2 KB)

They also wanted the datetime formatted differently as well, in case you want this too. If so, replace the Markdown above with this version:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/d/6dbd7780e739da6fb8086919f6ff6960538898a6.png)

> **Markdown JS Injector (State & Datetime mods) - Copy JSON and Paste into the View containing the AST**
>
> ```json
> [
> {
> "type": "ia.display.markdown",
> "version": 0,
> "props": {
> "style": {
> "position": "absolute"
> },
> "markdown": {
> "escapeHtml": false
> }
> },
> "meta": {
> "name": "JSInject_ConvertStateColToPillBoxes_0"
> },
> "position": {
> "shrink": 0,
> "basis": 0
> },
> "custom": {
> "inlineJavascript": "(() => {\n const styleAlarmStates = () => {\n document.querySelectorAll(\".ia_table__cell[data-column-id=state]:not(.ia_table__head __header__ cell) .content > div\").forEach(el => {\n if (el.querySelector(\".custom_alarmStatusTable__stateCol_pill\"))\n return;\n const text = el.textContent.trim();\n if (!text)\n return;\n const parts = text.split(\",\").map(s => s.trim());\n const classMap = {\n \"Active\": \"custom_alarmStatusTable__stateCol_active\",\n \"Cleared\": \"custom_alarmStatusTable __stateCol_cleared\",\n \"Acknowledged\": \"custom_alarmStatusTable__ stateCol_ack\",\n \"Unacknowledged\": \"custom_alarmStatusTable__stateCol_unack\"\n };\n const pills = parts.map(part => {\n const stateClass = classMap[part] || \"\";\n return \"<span class=\\\"custom_alarmStatusTable__stateCol_pill \" + stateClass + \"\\\">\" + part + \"</span>\";\n }).join(\"\");\n el.innerHTML = \"<div class=\\\"custom_alarmStatusTable__stateCol_container\\\">\" + pills + \"</div>\";\n });\n };\n\n const formatDateTimeCells = () => {\n document.querySelectorAll('.alarmStatusTable .ia_table__cell:not(.ia_table __head__ header__cell) .content > div').forEach(div => {\n const title = div.getAttribute('title');\n const datetimeRegex = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}[+-]\\d{4}$/;\n \n if (title && datetimeRegex.test(title) && !div.querySelector('div[style*=\"flex\"]')) {\n const text = div.textContent.trim();\n const parts = text.split(' ');\n \n if (parts.length >= 5) {\n const date = parts.slice(0, 3).join(' ').trim();\n const time = parts.slice(3).join(' ').trim();\n \n div.innerHTML = `\n <div style=\"display: flex; flex-direction: column; gap: 2px; align-items: flex-end;\">\n <div style=\"font-weight: bold;\">${date}</div>\n <div style=\"font-size: 0.9em; color: #666;\">${time}</div>\n </div>\n `;\n }\n }\n });\n };\n\n const setupObserver = () => {\n let rafId;\n const observer = new MutationObserver(() => {\n if (rafId)\n return;\n rafId = requestAnimationFrame(() => {\n styleAlarmStates();\n formatDateTimeCells();\n rafId = null;\n });\n });\n const tableContainer = document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\");\n if (tableContainer) {\n styleAlarmStates();\n formatDateTimeCells();\n observer.observe(tableContainer, {\n childList: true,\n attributes: true,\n subtree: true,\n attributeFilter: [\"title\", \"style\"]\n });\n }\n };\n\n const visibilityObserver = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type === \"attributes\" &&\n mutation.attributeName === \"style\" &&\n mutation.target.getAttribute(\"data-component\") === \"ia.display.alarmstatustable\" &&\n mutation.target.style.display !== \"none\") {\n console.log(\"alarmStatusTable visibility observer fired\");\n if (document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n setupObserver();\n } else {\n const revealWaitObserver = new MutationObserver(() => {\n if (document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n revealWaitObserver.disconnect();\n setupObserver();\n }\n });\n revealWaitObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n }\n }\n });\n\n visibilityObserver.observe(document.body, {\n subtree: true,\n attributes: true,\n attributeFilter: [\"style\"]\n });\n\n setupObserver();\n if (!document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n const waitObserver = new MutationObserver(() => {\n if (document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n waitObserver.disconnect();\n setupObserver();\n }\n });\n waitObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n})();"
> },
> "propConfig": {
> "props.source": {
> "binding": {
> "config": {
> "struct": {
> "script": "{this.custom.inlineJavascript}"
> },
> "waitOnAll": true
> },
> "transforms": [
> {
> "code": "#\tcode = \"<img style='display:none' src='/favicon.ico' onload=\\\"\" + value.script.replace('\"', '&quot;') + '\\\"></img>'\n#\t\n#\tcode = code.replace(\"\\n\", \"\").replace(\"\\t\", \"\").replace(\"\\n\", \"\").replace(\"\\r\", \"\").replace(\"\\r\", \"\").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \")\n#\t\n#\treturn code\n\tscript = value.script\n\tscript = script.replace('\"', '&quot;')\n\tscript = script.replace('\\n', '').replace('\\t', '').replace('\\r', '')\n\t\n\t# Collapse multiple spaces - repeat until stable\n\twhile ' ' in script:\n\t script = script.replace(' ', ' ')\n\t\n\tcode = '<img style=\"display:none\" src=\"/favicon.ico\" onload=\"{}\"></img>'.format(script)\n\treturn code",
> "type": "script"
> }
> ],
> "type": "expr-struct"
> }
> }
> }
> }
> ]
> 
> ```

Edit: Updated the Markdown JSON (State & Datetime mods version only) with a fix to address the AST not re-formatting when it’s hidden and shown again by toggling the `display` prop

---

_[View the full topic](https://forum.inductiveautomation.com/t/useful-css-stuff/95414)._
