Page MenuHomePhabricator

[Table of contents] Increase threshold for when a section is active
Closed, ResolvedPublic2 Estimated Story Points

Description

Description

Currently a section is considered active (and therefore bolded in the table of contents) once the top of it's heading begins to intersect with the top of the viewport (or the bottom of the sticky header).

While we don't actually know where, relative to the top of the browser window, people's line of sight is when they're scrolling down a webpage, we are making the assumption that it is not at the very top of the browser window, but rather somewhere a bit below that. Therefore we should increase the threshold by 100px, so that it better matches the practical experience of reading a webpage.

Current threshold
without sticky headerwith sticky header
image.png (1×3 px, 927 KB)
image.png (1×3 px, 908 KB)

To-do

  • Increase the threshold for when a section is active by 100px 75px per T317661#8669626
Updated threshold
without sticky headerwith sticky header
image.png (1×3 px, 886 KB)
image.png (1×3 px, 849 KB)

QA Results - Beta

ACStatusDetails
1T317661#8674733

QA Results - Prod

ACStatusDetails
1T317661#8712386
2T317661#8712386

Event Timeline

alexhollender_WMF renamed this task from Increase threshold for when a section is active to [Table of contents] Increase threshold for when a section is active.Sep 13 2022, 3:55 PM
alexhollender_WMF updated the task description. (Show Details)
ovasileva triaged this task as Medium priority.Sep 14 2022, 2:15 PM

Wanted to file this too. But the approach with a fixed threshold seems suboptimal to me. It's imprecise, and if there is a sequence of short low-level sections like this

image.png (215×328 px, 10 KB)

this is gonna be confusing.

A better approach could include taking heading margins into account. Only paddings are considered parts of the heading by getBoundingClientRect() that gets element positions. margins are in orange, paddings are in green:

image.png (298×532 px, 40 KB)
image.png (204×402 px, 18 KB)

I did this in Convenient-Discussions before sidebar TOC has arrived. A fixed number of pixels could be added to the margin then. But in my opinion, it shouldn't be big, so that only whitespace between sections would count as part of the bottom section; everything else would be ambiguous and confusing.

To avoid running a costly operation of getting the top margin of a heading on every page scroll, it could be cached.

But in my opinion, it shouldn't be big, so that only whitespace between sections would count as part of the bottom section; everything else would be ambiguous and confusing.

I'll try to elaborate. There is no way to tell which section the user is currently reading here:

image.png (950×1 px, 191 KB)

They could be finishing the top section but just as well might be reading the bottom one. Trying to come up with a perfect threshold is a futile task since it would mismatch the actual reading experience way too often and the attempts of the page to guess what I'm reading (instead of just being predictable) would be annoying. It might make more sense to give up guessing and stick to treating the first visible section as the active.

An alternative might be switching to the next section when the last line stops being fully visible. Incidentally, this is the approach Britannica uses:

chrome_QTJsSco2Am.gif (467×1 px, 3 MB)

Hey @Jack_who_built_the_house, thanks for your comments. To clarify two things:

  • there will always be the situation where multiple short sections are visible on the page but only one is highlighted/active in the table of contents, there is no way to avoid this
  • this task is about adjusting the intersection threshold (also known as the root margin), which as far as I understand is always a fixed value. whichever section has most recently intersected with the threshold is considered active. Hopefully the screen recording below helps to further clarify.

Let me know if that makes sense and if you have further questions or suggestions.

  • there will always be the situation where multiple short sections are visible on the page but only one is highlighted/active in the table of contents, there is no way to avoid this

Right, and we shouldn't aim to. The example in T317661#8243878 was meant to demonstrate that the mismatch between the subjectively perceived current section and the active section according to your solution can be dramatic. Here's a 100px threshold with short <h4> sections:

image.png (679×753 px, 49 KB)

We haven't passed the section under "Subheading" yet, and the TOC shows "Subheading 3".

And I don't think this should be solved just by decreasing the threshold value. In particular, this won't make the UI predictable when the user asks themselves the question "How does what I see on the page corresponds to which section is highlighted in the TOC". Note that I said "what I see", not "what I read", since, as you correctly pointed out, we don't actually know where people's line of sight is and what they "read", and (I might add) it's pointless to guess.

  • this task is about adjusting the intersection threshold (also known as the root margin), which as far as I understand is always a fixed value. whichever section has most recently intersected with the threshold is considered active.

So, well, this task proposes a solution without addressing the underlying problem. OK, I created a separate task for it: T318106: Improve user experience with when section is considered active.

I think the best indicator of a the user's active position is the vertical center of the viewport - not only 100px below. This would be the most unbiased solution as the user is either reading below or above it any time.

I just find it really weird that I'm personally reading the "Kernal design decisions" section however it's still highlighting the "System calls" section:

image.png (1×2 px, 463 KB)

@Lectrician1 thanks for your input. I think picking the middle of the screen is a good proposal as well. Without some kind of research it seems difficult to know what might match up best with most people's scrolling/reading experience. At this point all I know about is my own experience. I seem to keep my gaze towards the top of the screen as I'm scrolling. Where do you find your gaze to be?

Also, I just made a slight change to the task description. I think what's important here is where people are looking while they are scrolling, because it's the scrolling interaction that causes the active section in the table of contents to change.

@Lectrician1 thanks for your input. I think using the middle of the screen as the intersection threshold is a good proposal as well. Without some kind of research it seems difficult to know what might match up best with most people's scrolling/reading experience. At this point all I know about is my own experience. I seem to keep my gaze towards the top of the screen as I'm scrolling. Where do you find your gaze to be?

Also, I just made a slight change to the task description. I think what's important here is where people are looking while they are scrolling, because it's the scrolling interaction that causes the active section in the table of contents to change.

Where do you find your gaze to be?

Anywhere except very close to the top or bottom of the screen.

Another innovative solution you could do is just bold all of the sections that are currently visible.

Hi,

As reported here with screenshots, the behavior on live does not match the "current behavior" screenshot at the top right of this ticket. The text there reads "Currently a section is considered active (and therefore bolded in the table of contents) once the top of it's heading begins to intersect with the top of the viewport (or the bottom of the sticky header).", but in fact even this is not working — the bolded section is often not visible on the screen at all. I'm not sure if I should be starting a separate bug for this, since it seems to be a separate issue that won't be fully resolved by implementing the primary feature described here, but it's also similar enough that it could probably be addressed at the same time.

ovasileva raised the priority of this task from Medium to High.Feb 17 2023, 10:33 PM

Change 893521 had a related patch set uploaded (by Bernard Wang; author: Bernard Wang):

[mediawiki/skins/Vector@master] Add threshold to TOC section observer

https://gerrit.wikimedia.org/r/893521

bwang removed bwang as the assignee of this task.Mar 1 2023, 6:00 PM
bwang subscribed.

Change 893521 merged by jenkins-bot:

[mediawiki/skins/Vector@master] Add threshold to TOC section observer

https://gerrit.wikimedia.org/r/893521

Discussed in standup and settled on 75px, moving to needs more work

Change 894712 had a related patch set uploaded (by Bernard Wang; author: Bernard Wang):

[mediawiki/skins/Vector@master] Update scroll threshold to be the same as scroll padding top

https://gerrit.wikimedia.org/r/894712

Change 894712 merged by jenkins-bot:

[mediawiki/skins/Vector@master] Update scroll threshold to be the same as scroll padding top

https://gerrit.wikimedia.org/r/894712

Edtadros subscribed.

Test Result - Beta

Status: ✅ PASS
Environment: beta
OS: macOS Ventura
Browser: Chrome
Device: MBP
Emulated Device:NA

Test Artifact(s):

QA Steps

✅ AC1: Threshold for an active section is 75px from top of viewport without sticky header present

Screenshot 2023-03-07 at 2.32.03 PM.png (381×832 px, 124 KB)

✅ AC1: Threshold for an active section is 75px from top of sticky header when it is present

Screenshot 2023-03-07 at 2.32.48 PM.png (570×812 px, 165 KB)

Edtadros removed ovasileva as the assignee of this task.

Test Result - Prod

Status: ✅ PASS
Environment: enwiki
OS: macOS Ventura
Browser: Chrome
Device: MBP
Emulated Device:NA

Test Artifact(s):

QA Steps

✅ AC1: Threshold for an active section is 75px from top of viewport without sticky header present

Screenshot 2023-03-20 at 5.06.43 PM.png (422×743 px, 137 KB)

✅ AC1: Threshold for an active section is 75px from top of sticky header when it is present

Screenshot 2023-03-20 at 5.07.47 PM.png (436×629 px, 109 KB)