# Task dynamic styling

**URL:** <https://community.silverbullet.md/t/task-dynamic-styling/3708>\
**Category:** Tricks & Techniques\
**Created:** [January 3, 2026, 3:10pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708 "2026-01-03T15:10:40Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 3, 2026, 3:10pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/1 "2026-01-03T15:10:41Z")

</div>

EDIT: info 01/08/2026  
Full message below

> [@Task dynamic styling](https://community.silverbullet.md/t/task-dynamic-styling/3708/15):
>
> This work is deprecated with the Edge version published 2026-01-08 which adds an enclosing span with a specific class (“sb-attribute”) and a “data-x”. \<span class="sb-list sb-task"\> TODO \</span\> \<span class="sb-attribute" data-statut="ok"\> /\* \<= NEW line added by the Edge version published 2026-01-08) \*/ \<span class="sb-list sb-frontmatter sb-meta"\>[\</span\> \<span class="sb-list sb-frontmatter sb-atom"\>statut\</span\> \<span class="sb-list sb-frontmatter sb-meta"\>: \</span\> \<span class="sb-list …

EDIT: update of 01/05/2026  
Full message below

> [@Task dynamic styling](https://community.silverbullet.md/t/task-dynamic-styling/3708/5):
>
> To familiarize myself with the SilverBullet environment, I set myself a challenge: style the tasks. It was laborious but the objective was achieved. The solution, based on a JS script, is published in my repository [Github](https://github.com/Baudogit/silverbullet/tree/main/Tasks%20styling) (I am not familiar with publishing via the Library Manager. Sorry!). You will find: observer.js which does the job observer\_start.md which stores custom CSS rules in a space-lua (yes, NOT a space-style!) and launches observer.js when the SilverBullet session starts Please r…

 ![PAGE de TESTS_](https://community.silverbullet.md/uploads/default/original/2X/0/022975df54eb2b3386fdc1b837bcfa1e117d5c97.png)

---

<div class="post-metadata">

**Author:** ![Platinum](https://community.silverbullet.md/user_avatar/community.silverbullet.md/platinum/32/2510_2.png) [@Platinum](https://community.silverbullet.md/u/Platinum)\
**Post date:** [January 4, 2026, 8:19am UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/2 "2026-01-04T08:19:52Z")

</div>

This is pretty fancy I’d have to say!

I assume this is the output of a query and not the source for the tasks?

---

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 4, 2026, 8:35am UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/3 "2026-01-04T08:35:49Z")

</div>

It’s the source. Code js does the job in real time.  
Doc is being written and the code will be published on github in the afternoon… Patience!

---

<div class="post-metadata">

**Author:** ![Platinum](https://community.silverbullet.md/user_avatar/community.silverbullet.md/platinum/32/2510_2.png) [@Platinum](https://community.silverbullet.md/u/Platinum)\
**Post date:** [January 4, 2026, 9:51am UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/4 "2026-01-04T09:51:09Z")

</div>

Oh wow, even better! This seems comprehensive too!

---

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 5, 2026, 4:03pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/5 "2026-01-05T16:03:23Z")

</div>

To familiarize myself with the SilverBullet environment, I set myself a challenge: **style the tasks**. It was laborious but the objective was achieved.

The solution, based on a JS script, is published in my repository [Github](https://github.com/Baudogit/silverbullet/tree/main/Tasks%20styling) (I am not familiar with publishing via the Library Manager. Sorry!).

## You will find:

- **observer.js** which does the job
- **observer\_start.md** which stores custom CSS rules in a `space-lua` (yes, NOT a `space-style`!) and launches observer.js when the SilverBullet session starts

Please read **observer\_README\_FR.md** or **observer\_README\_EN.md** to learn everything about the making-off and set up your own rules.

Other files are made available, including:

- **observer\_tests.md** to check your installation and custom rules
- observer\_new\_avec\_log.js and observer\_old\_avec\_debug.js to access quantifications and runtime markup in the console. These older versions do not support passing arguments from space-lua (see observer\_Readme).

This script anticipates the development proposed here [https://github.com/silverbulletmd/silverbullet/issues/1740](https://github.com/silverbulletmd/silverbullet/issues/1740). @zef: can you take a look and check the consistency between the two approaches? THANKS.

Please send me your feedback here (not on Github) by publishing an image of your customization.

Happy styling!

---

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 5, 2026, 4:12pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/6 "2026-01-05T16:12:11Z")

</div>

Here is the diagram of the structure targeted by the script:  
(in french, sorry!)

 ![carte](https://community.silverbullet.md/uploads/default/original/2X/6/6a32f411f350f4488b2f46dfd34d43018a4a78c2.png)

---

<div class="post-metadata">

**Author:** ![Mr.Red](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mr.red/32/821_2.png) [@Mr.Red](https://community.silverbullet.md/u/Mr.Red)\
**Post date:** [January 5, 2026, 5:00pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/7 "2026-01-05T17:00:11Z")

</div>

Nice job 👍

But if I would have something like that in my space I would instantly get a panic attack and would start heavy breathing…😅😮‍💨

---

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 6, 2026, 10:34am UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/10 "2026-01-06T10:34:48Z")

</div>

UPDATE 2026-01-06

New version: **observer.js** and **observer\_start.md**  
Reason: passing arguments to js script didn’t work  
Changed: js script is now an ES6 module | the default CSS rules are removed (they are already in the `space-lua`)  
Sorry !

---

<div class="post-metadata">

**Author:** ![Platinum](https://community.silverbullet.md/user_avatar/community.silverbullet.md/platinum/32/2510_2.png) [@Platinum](https://community.silverbullet.md/u/Platinum)\
**Post date:** [January 6, 2026, 5:28pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/11 "2026-01-06T17:28:30Z")

</div>

> [@Mr.Red](#):
>
> But if I would have something like that in my space I would instantly get a panic attack and would start heavy breathing

I see the screenshot comprehensive demo of all the possibilities that can be achieved with the code. We only need to turn on the parts that make us more productive.

---

<div class="post-metadata">

**Author:** ![urnlahzer](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/u/ecc23a/32.png) [@urnlahzer](https://community.silverbullet.md/u/urnlahzer)\
**Post date:** [January 7, 2026, 6:01pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/12 "2026-01-07T18:01:28Z")

</div>

I also didn’t like the tables with tasks and wanted to change them. I took a different approach and just created a new template for tasks, then query and use that template. Happy to share if it’s useful. I am not sure if that approach would allow all the colors and cool stuff you have, but it allowed me to bold certain portions, reorganize things how I like them, etc.

---

<div class="post-metadata">

**Author:** ![Platinum](https://community.silverbullet.md/user_avatar/community.silverbullet.md/platinum/32/2510_2.png) [@Platinum](https://community.silverbullet.md/u/Platinum)\
**Post date:** [January 7, 2026, 6:09pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/13 "2026-01-07T18:09:56Z")

</div>

Please do share your code and a screenshot for inspiration if nothing else!

---

<div class="post-metadata">

**Author:** ![urnlahzer](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/u/ecc23a/32.png) [@urnlahzer](https://community.silverbullet.md/u/urnlahzer)\
**Post date:** [January 7, 2026, 6:53pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/14 "2026-01-07T18:53:48Z")

</div>

So I have queries for “stale” tasks (where attribute StartDate is old) and for overdue tasks (where DueDate is older than today). Here’s a screenshot for overdue showing the client name in bold, the due date, the task text, and finally the page.

 ![TaskScreenshot](https://community.silverbullet.md/uploads/default/original/2X/a/a4036837b9c5d57ec48e12d1e59951693968bd18.png)

As a meta page, here is the Lua:

````auto
---
tags: meta
---

# Task Helper Functions
```space-lua
-- Initialize custom namespace
custom = custom or {}

-- Calculate age in days from a date string (YYYY-MM-DD format)
function custom.daysAgo(dateStr)
    if not dateStr then return 0 end
    local year, month, day = dateStr:match("^(%d%d%d%d)%-(%d%d)%-(%d%d)$")
    if not (year and month and day) then
        return 0
    end
    local taskTime = os.time({year = year, month = month, day = day})
    local now = os.time()
    local diff = math.floor((now - taskTime) / 86400) -- 86400 seconds in a day
    return diff
end

-- Extract client name from page path (first part before /)
function custom.getClientFromPath(pagePath)
    if not pagePath then return "" end
    local client = pagePath:match("^([^/]+)")
    return client or pagePath
end

-- Extract project name from page path (second part after first /)
function custom.getProjectFromPath(pagePath)
    if not pagePath then return "" end
    local _, project = pagePath:match("^([^/]+)/([^/]+)")
    return project or ""
end

-- Format the task display line with client, project, date, and name
function custom.formatTaskLine(task, dateField)
    local client = custom.getClientFromPath(task.page)
    local project = custom.getProjectFromPath(task.page)
    local dateVal = task[dateField] or ""
    
    local parts = {}
    if client ~= "" then table.insert(parts, " **" .. client .. "**") end
    if project ~= "" then table.insert(parts, "_" .. project .. "_") end
    if dateVal ~= "" then table.insert(parts, "📅 " .. dateVal) end
    
    return table.concat(parts, " | ")
end

````

Here is the query for the overdue tasks:

```auto
${template.each(query[[
from index.tag "task"
where not done and DueDate != nil and table.includes(itags, "work") and DueDate < os.date("%Y-%m-%d")
order by DueDate
limit 20
]], function(task) 
  local client = task.page:match("^([^/]+)") or "" 
  return "* [" .. task.state .. "] **" .. client .. "** · Due: ==" .. task.DueDate .. "== | " .. task.name .. " | [[" .. task.ref .. "]]\n" 
end)}

```

Here is the query for the stale tasks:

```auto

${template.each(query[[
  from index.tag "task"
  where not done and table.includes(itags, "work") and StartDate != nil and ((StartDate < os.date('%Y-%m-%d', os.time() - 5*86400)) )
  order by StartDate 
  limit 20
]], function(task)
  local client = task.page:match("^([^/]+)") or ""
  return "* [" .. task.state .. "] **" .. client .. "** | Started: " .. task.StartDate .. " | " .. task.name .. " | [[" .. task.ref .. "]]\n"
end)}

```

---

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 8, 2026, 9:23pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/15 "2026-01-08T21:23:10Z")

</div>

This work is deprecated with the Edge version published 2026-01-08 which adds an enclosing span with a specific class (“sb-attribute”) and a “data-x”.

```auto
<span class="sb-list sb-task"> TODO </span>
 
<span class="sb-attribute" data-statut="ok"> /* <= NEW line
added by the Edge version published 2026-01-08) */

<span class="sb-list sb-frontmatter sb-meta">[</span>
<span class="sb-list sb-frontmatter sb-atom">statut</span>
<span class="sb-list sb-frontmatter sb-meta">: </span>
<span class="sb-list sb-frontmatter">ok</span>
<span class="sb-list sb-frontmatter sb-meta">]</span>

</span>

```

---

<div class="post-metadata">

**Author:** ![Platinum](https://community.silverbullet.md/user_avatar/community.silverbullet.md/platinum/32/2510_2.png) [@Platinum](https://community.silverbullet.md/u/Platinum)\
**Post date:** [January 9, 2026, 6:28am UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/16 "2026-01-09T06:28:46Z")

</div>

> [@bau](#):
>
> This work is deprecated with the Edge version published 2026-01-08 which adds an enclosing span with a specific class (“sb-attribute”) and a “data-x”.

Good to know, thank you. But thank you for the whole thread and code. Even if this particular work was made redundant, I learned a lot from your work!

---

<div class="post-metadata">

**Author:** ![urnlahzer](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/u/ecc23a/32.png) [@urnlahzer](https://community.silverbullet.md/u/urnlahzer)\
**Post date:** [January 9, 2026, 6:09pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/17 "2026-01-09T18:09:46Z")

</div>

Sorry, can you explain this more? I don’t understand the significance of the sb-attribute addition.

---

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 9, 2026, 8:18pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/18 "2026-01-09T20:18:59Z")

</div>

Evolution proposal 1740 was integrated yesterday, by @zef , into the Edge (pre-release) version of Silverbullet.

When generating the html code (backend of md pages) by Silvebullet, a span is added to the description of the attributes it encapsulates.

This span is associated:

- to a new class: “sb-attribute”
- to an attribute (in the HTML sense) which conveys the name of the attribute (in the Silverbullet sense) and its value, which allows this information to be manipulated like a CSS selector.

This will make, among other things, customizing the display of a task much easier.

Example of the new structure for a task attribute:

```auto
<span class="sb-list sb-task"> TODO </span>
 
<span class="sb-attribute" data-statut="ok">

<span class="sb-list sb-frontmatter sb-meta">[</span>
<span class="sb-list sb-frontmatter sb-atom">statut</span>
<span class="sb-list sb-frontmatter sb-meta">: </span>
<span class="sb-list sb-frontmatter">ok</span>
<span class="sb-list sb-frontmatter sb-meta">]</span>

</span>

```

**CSS rule example with new components:**

- background of all atributs elements :  
.sb-attribute[data-statut] { background-color: red;}

- background of the value alone:  
.sb-attribute[data-statut] \> .sb-list.sb-frontmatter:not(.sb-meta):not(.sb-atom) { background-color: red;}

---

<div class="post-metadata">

**Author:** ![bau](https://community.silverbullet.md/user_avatar/community.silverbullet.md/bau/32/2597_2.png) [@bau](https://community.silverbullet.md/u/bau)\
**Post date:** [January 10, 2026, 9:19am UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/19 "2026-01-10T09:19:35Z")

</div>

A more complete example, here:

> [@Task Explorer](https://community.silverbullet.md/t/task-explorer/3747):
>
> Thanks to the immense work carried out by @Mr.Red it is possible to prototype a panel with advanced windowing functions. The concept makes it possible to imagine tools complementary to the editor, which would facilitate querying, navigation and visualization. I applied this approach to tasks. The goal is to bypass the current limitation that requires returning to the original task page to modify the task state. The task list incorporates a link that calls the task page in the editor (like Docu…

---

<div class="post-metadata">

**Author:** ![greencow](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/g/977dab/32.png) [@greencow](https://community.silverbullet.md/u/greencow)\
**Post date:** [September 27, 2026, 4:01pm UTC](https://community.silverbullet.md/t/task-dynamic-styling/3708/20 "2026-09-27T16:01:29Z")

</div>

there's an app for that..
