Header counter

agree. I used a lot of header links, I don’t want to change the name of header which will break the link.
I am wondering if we can just use css to change the display before the header, instead of the content of header.

3 Likes

I am not sure what you mean by that. Anything on the line of the header belongs to the header. And if you add something before the hash (#), the text on that line is not loneger a header.

Hello, I’m new to this forum!

I came up with a pure CSS solution to count the headings.

I’ve modified previously sent code and got a solution that adds a heading number in both edit and preview mode. Since it’s a pure CSS solution, the heading numbers are decorative and don’t modify the actual document content.

1

The code uses CSS variables, so you can easily set up the deliminator, as well as the initial number, by changing the --initial and --delim values respectively. All the individual levels are also customizable:

image

You can also style the heading numbers:

To start using the code, add it to one of your CSS snippets.

:root {
	/* ? Changes the number each heading starts counting from, 0 means 1, -1 means 0, ... */
	--initial: 0;

	/* ? Changes the symbol between the numbers. (Keep the quotation marks!) */
	--delim: '.';

	/* ? Delete the heading *value* (right side) if you don't want to count it */
	/* ? For example, if you want to skip Heading 1, keep only this: */
	--h1-num: ;

	--h1-num: counter(var(--h1)) var(--delim);
	--h2-num: var(--h1-num) counter(var(--h2)) var(--delim);
	--h3-num: var(--h2-num) counter(var(--h3)) var(--delim);
	--h4-num: var(--h3-num) counter(var(--h4)) var(--delim);
	--h5-num: var(--h4-num) counter(var(--h5)) var(--delim);
	--h6-num: var(--h5-num) counter(var(--h6)) var(--delim);

	/* Other values */
	--h1: h1;
	--h2: h2;
	--h3: h3;
	--h4: h4;
	--h5: h5;
	--h6: h6;
}

/* ! Styling here! */
:is(.cm-header, h1, h2, h3, h4, h5, h6)::before {
	position: absolute;
	transform: translateX(calc(-100% - 0.7rem));
	opacity: 0.5;
}

body {
	counter-reset: var(--h1) var(--h2) var(--h3) var(--h4) var(--h5) var(--h6);
}

.cm-header-1::before,
h1::before {
	counter-increment: var(--h1);
	counter-set: var(--h2) var(--initial);
	content: var(--h1-num);
}

.cm-header-2::before,
h2::before {
	counter-increment: var(--h2);
	counter-set: var(--h3) var(--initial);
	content: var(--h2-num);
}

.cm-header-3::before,
h3::before {
	counter-increment: var(--h3);
	counter-set: var(--h4) var(--initial);
	content: var(--h3-num);
}

.cm-header-4::before,
h4::before {
	counter-increment: var(--h4);
	counter-set: var(--h5) var(--initial);
	content: var(--h4-num);
}

.cm-header-5::before,
h5::before {
	counter-increment: var(--h5);
	counter-set: var(--h6) var(--initial);
	content: var(--h5-num);
}

.cm-header-6::before,
h6::before {
	counter-increment: var(--h6);
	content: var(--h6-num);
}

/* ? Selectors to prevent double heading from showing up when editing a line */
.cm-formatting-header::before {
	display: none;
}

.cm-formatting-header ~ .cm-header::before {
	opacity: 0;
}
2 Likes

Thanks a lot, that’s very interesting. I always knew it should be possible in Obsidian too.

I literally copied your code, and enabled the snippet.
Every H1 header is shown as 1. instead of 1. 2. etc.

Every H2 header is shown as 0.1. instead of 1.1. or 2.1. etc.
Every H3 header is shown as 0.0.1 instead of 1.1.1. etc.

Is that a bug or do I need to adjust something? I looked but could not find anything “wrong”.

I tested the code in v1.0.0 in the Default and Minimal theme. Could you please tell me what version and theme you are using, so I can look into it?

I am using version 1.0 and Gruvbox theme.

Update: I disabled Gruvbox and relaunched Obsidian, the result is still the same as described above.

Strangely enough, it works on my end with Gruvbox enabled.

image

There might be different factors at play, including some of our plugins. I’ll look into it further and to find the culprit.

1 Like

Previously if you had multiple editors open, the heading numbers were going up for all the headings as if they were one document (so, for example, the other editor would start counting from 3).

A new version of the code with slight alterations to fix this behavior:

:root {
	/* ? Changes the number each heading starts counting from, 0 means 1, -1 means 0, ... */
	--initial: 0;

	/* ? Changes the symbol between the numbers. (Keep the quotation marks!) */
	--delim: '.';

	/* ? Delete the heading *value* (right side) if you don't want to count it */
	/* ? For example, if you want to skip Heading 1, keep only this: */
	--h1-num: ;

	--h1-num: counter(var(--h1)) var(--delim);
	--h2-num: var(--h1-num) counter(var(--h2)) var(--delim);
	--h3-num: var(--h2-num) counter(var(--h3)) var(--delim);
	--h4-num: var(--h3-num) counter(var(--h4)) var(--delim);
	--h5-num: var(--h4-num) counter(var(--h5)) var(--delim);
	--h6-num: var(--h5-num) counter(var(--h6)) var(--delim);

	/* Other values */
	--h1: h1;
	--h2: h2;
	--h3: h3;
	--h4: h4;
	--h5: h5;
	--h6: h6;
}

/* ! Styling here! */
:is(.cm-header, h1, h2, h3, h4, h5, h6)::before {
	position: absolute;
	transform: translateX(calc(-100% - 0.7rem));
	opacity: 0.5;
}

.cm-editor {
	counter-reset: var(--h1) var(--h2) var(--h3) var(--h4) var(--h5) var(--h6);
}

.cm-header-1::before,
h1::before {
	counter-increment: var(--h1);
	counter-set: var(--h2) var(--initial);
	content: var(--h1-num);
}

.cm-header-2::before,
h2::before {
	counter-increment: var(--h2);
	counter-set: var(--h3) var(--initial);
	content: var(--h2-num);
}

.cm-header-3::before,
h3::before {
	counter-increment: var(--h3);
	counter-set: var(--h4) var(--initial);
	content: var(--h3-num);
}

.cm-header-4::before,
h4::before {
	counter-increment: var(--h4);
	counter-set: var(--h5) var(--initial);
	content: var(--h4-num);
}

.cm-header-5::before,
h5::before {
	counter-increment: var(--h5);
	counter-set: var(--h6) var(--initial);
	content: var(--h5-num);
}

.cm-header-6::before,
h6::before {
	counter-increment: var(--h6);
	content: var(--h6-num);
}

/* ? Selectors to prevent double heading from showing up when editing a line */
.cm-formatting-header::before {
	display: none;
}

.cm-formatting-header ~ .cm-header::before {
	opacity: 0;
}
2 Likes

With updated code there is some improvement in the H2 and H3 numbering: in some cases it numbers them correctly.

What also happens that if there are 2 H1 headings on the screen, they will be numbered correctly, e.g. 1 and 2. When I scroll up and the first disappears from view, the number of the second one changes to number 1.

I tried it too with all my plug-ins turned off but there is no difference.

I tried it with the Minimal theme, same result.

FYI, these are my plug-ins:



BTW, when I test your code, I delete the numbers that Number Headings added, then turn off that plug-in.

I tested the snippet in the sandbox vault:

I added the H1 test header, because the other headers that are there by default are H2 headers.

As you can see, the numbering is not right.

Have you tried that in a longer note with headings and subheadings whereby you have to scroll to get to see them?

If not, try that with Gruvbox. What will happen is that, starting from the 1st H1 heading at the top of that document, the numbering will be right.

But when you then scroll down, the next H1 heading, which was numbered 2 by the snippet, changes to 1, and the subheadings below it change accordingly.

looking at the css I found it worked ok in edit but not in preview. I have since switched to the Number Headings plugin which doesn’t work exactly the way I like but well enough for my needs. it even has a toc generator

@dracozny I have been using Number Headings ever since it came out. And while it is a useful plug-in, there is 1 irritating thing about it: the numbers are physically added to the headings, which means that when the numbers change all the links to those headings are broken. The dev said it could not be changed in this plug-in.

Licat has said that to have Obsidian amend links automatically would be very resource intensive and dramatically slowdown Obsidan. Therefore, a no-go.

The CSS code proposed by @Platon_Ivanov solves that because the heading numbers are not physically added to the headings, so I am very interested in it. Hopefully we can resolve my issue with it.

However, there is a downside to his CSS proposal: since the numbers are “virtual”, an outline/table of contents plug-in, such as the core plug-in or Floating TOC do not see the numbers. And that makes correlating the TOC and the note’s text headings, therefore navigation of long notes, more cumbersome. On the bright side, though, there is CSS code for Typora that I use and that does @Platon_Ivanov’s trick AND have the outline in the sidebar “see” the numbers; in other words, it IS possible to have the everything. I am hoping Platon_Ivanov will eventually be able to get to that stage with his CSS code. I am not CSS savvy enough to achieve that.

3 Likes

Hello!

I’m coming back with some news regarding the heading counter!

I wanted to make the post more interactive by linking to previous posts in the thread, as well as other resources, but the links were unfortunately being flagged as spam because of my trust level (turns out I can only have 2 links per post).

When I scroll up and the first disappears from view, the number of the second one changes to number 1.

I’ve tried to tackle the issues and I would guess that the headings are being disabled for rendering performance so that the CSS cannot count them.

To try to fix that issue, I’ve worked with TypeScript to save the numbers for individual headings for the CSS to use in the styling. In the end I ended up creating a plugin.

This plugin is just a proof of concept

There are multiple issues:

  • With multiple tabs or workspaces open, the count won’t reset for each of them
  • No settings like in the CSS snippet yet

I will fix the issues and add more features to the plugin if it fixes the issue we’ve met before. In case not, I have other solutions in mind that I will try to implement.

I would like to kindly ask anyone interested in the topic to install the plugin and let me know how it works for you. I would especially appreciate @Klaas’s input, since with the CSS snippet they came across an issue I’ve been not able to recreate on my end.

3 Likes

Hi @Platon_Ivanov, thanks for the effort you’re putting in. A plug-in, wow, very nice.

I installed the plug-in manually in the plug-ins folder, but it does not show up in Settings > Community plug-ins, even after relaunching Obsidian. So, I cannot enable it.

FYI: I first tried this one, obsidian-heading-counter-plugin - no luck. Then I tried this one, obsidian-heading-counter-1.0.0 - no luck either. In the latter one I noticed the main.js file is missing.

BTW, regarding new features, I don’t know if you are aware of the Style Settings plug-in, but a lot of community plug-ins “latch onto it” (sorry, I don’t know the correct term) to give users the possibility for extra customization.

Thank you for trying to install it!

The obsidian-heading-counter-plugin (the release ZIP) should work if put the whole folder in the plugins folder inside of .obsidian. At this point you should see this in the list of installed plugins:

image

Let me know if it still doesn’t show up so that I can try to troubleshoot it further.

Using the Style Settings plugin is a great idea! I will look into how it works and try to integrate it with this plugin.

1 Like

I still have numbering issues in reading view.

note: ignore the extra set of numbers that is from the other plugin which I turned off and only deleted a few of the numbers at the start.

2 Likes

I did put the whole folder in the Obsidian plug-ins folder, and I did that with both versions I mentioned above. Unfortunately, I still don’t see them.

BTW, did you see what I said about the main.js file?

Note that all my comments relate to Live Preview as I hardly ever using Reading mode.

1 Like

If Number Headings is enabled, you can delete all the heading numbers in a note in a simple way: do CTRL/CMD+P (= command pallet), start typing num and the dropdown list will show the option to erase all the numbers.

Sure, though I wasn’t going to go through that if the plugin didn’t work in Reading view, which as you can see from the top half of my screenshot it doesn’t. I just deleted enough of them to prove out the issue.