Bookmarklet for Mastodon
I was a bit annoyed at using Mastodon on the web while logged out.
Specifically, if you visit a user's web page, you naturally start at the top of the page. But, the most recent post will be below their profile information and below any pinned posts. So, you have to scroll before any new information shows.
I tried looking for an HTML anchor that I could save to a bookmark. But, I did not find one.
Instead, I asked a large language model to write some JavaScript that would scroll to the first post. And, I put that into a bookmarklet.
Bookmarklet Code
If you save the following JavaScript code to the 'Address' field of a web browser bookmark, then clicking on that bookmark will scroll to the first new Mastodon post.
I know this works in Firefox and Vivaldi. It probably works in Chrome. It might not work in Safari.
javascript:(function(){ const feedContainer = document.querySelector('div[role="feed"].item-list'); if (feedContainer) { const firstArticle = feedContainer.querySelector('article'); if (firstArticle) { firstArticle.scrollIntoView({ behavior: 'smooth', block: 'start' }); } } })();
If you're confused, here are all the steps:
- Create a new bookmark in your web browser.
- Copy the code above.
- Paste the code into the Address field of the bookmark.
- Give the bookmark a name. I named my bookmark "Mastodon Scroll".
- Save the bookmark.
- Navigate your web browser to a user's Mastodon profile.
- Click on the bookmark you saved.
Clicking on the bookmark should scroll the newest Mastodon post into view.
Background
Mastodon HTML Code
A basic Mastodon user profile has all the posts organized in a HTML <div/> element like this:
<div role="feed" class="item-list"> <article> </article> <article> </article> <article> </article> </div>
So, we'll just use some basic JavaScript to select the correct HTML element and scroll it into view.
Use the querySelector() method to select the first element that matches a CSS selector.
The JavaScript generated by Gemini uses querySelector() twice:
// Select the <div/> element. document.querySelector('div[role="feed"].item-list'); // And, select, the first <article/> element. feedContainer.querySelector('article');
Use the scrollIntoView() method to scroll that post into view.
firstArticle.scrollIntoView();
The language model I chatted with used constants and some method options.
You could also use this more basic version without the constants and options. This works because you can chain methods off of any object including the built-in "document" object.
javascript:(function(){ document.querySelector('div[role="feed"].item-list').querySelector('article').scrollIntoView(); })();
Bookmarklets
If you're not familiar with bookmarklets, basically, you can save some JavaScript in a browser bookmark. And then you can execute that code when you click on the bookmark.
The "JavaScript:" URI scheme is what allows the browser to interpret the code saved in the bookmark's address field.
When I work on a new bookmarklet, I get the code working in a web browser's JavaScript console. Then, I place that code into a template. Be careful to remove all comments from the code.
javascript:(function(){ // New bookmarklet code goes here. // No JavaScript comments (like this one) should be saved to your bookmark's Address field. })();
Google Gemini 2.5 Custom (AI Mode)
Here is the chat I had with Google's Gemini large language model. I initially searched for help and then clicked on the 'AI Mode' tab currently available on Google's search results page.
Question One
Input
Is there a HTML anchor for the first post under the pinned posts on a Mastodon web page?
Output
Mastodon's web interface doesn't typically provide a dedicated HTML anchor directly for the first non-pinned post on a timeline or user profile page.
How Mastodon handles pinned posts:
- Pinned posts appear at the top: Mastodon allows users to pin specific posts to the top of their profile, appearing above all other chronological updates.
- No specific anchor for the non-pinned section: The standard HTML structure doesn't include a unique anchor tag specifically for the first post after the pinned posts.
Workarounds:
- Custom HTML Embeds: If you're embedding Mastodon posts on your own website, you could create a custom HTML section and add anchors to specific posts.
- CSS selectors: You could potentially use CSS selectors like :first-of-type or :not(:first-child) in combination with other selectors to target the element you want, but this is more for styling than direct linking.
- Mastodon API: If you're building a custom application interacting with Mastodon, the API provides methods to fetch timelines and lists of posts, allowing you to identify the first non-pinned post programmatically.
Important Notes:
- Mastodon's structure can change: The internal HTML structure of the Mastodon web interface is subject to change with updates, so relying on specific CSS or HTML for anchoring may not be reliable in the long term.
- The focus is on user experience: The current design of the Mastodon web interface emphasizes providing a seamless and chronological view of content, with pinned posts providing a static starting point.
In summary, while there isn't a pre-built HTML anchor for the first post after the pinned posts, you can achieve similar functionality using custom embeds, CSS selectors, or by interacting with the Mastodon API.
Question Two
Input
Is there a JavaScript method that will scroll a part of the DOM into view?
Output
Yes, there are several JavaScript methods to scroll a part of the DOM into view. The most common and recommended method is element.scrollIntoView().
element.scrollIntoView()
- This method is part of the Element interface in the Document Object Model (DOM).
- It scrolls the element's ancestor containers such that the element on which scrollIntoView() is called is visible to the user.
- It can be called without any arguments for default behavior, or with an optional scrollIntoViewOptions object to customize the scrolling.
scrollIntoViewOptions Object
This object allows you to control the scrolling behavior with properties like:
- behavior: Determines the animation of the scroll. Can be 'auto' (instant), 'smooth', or 'instant'.
- block: Defines the vertical alignment of the element within the visible area. Options include 'start', 'center', 'end', and 'nearest'.
- inline: Defines the horizontal alignment of the element within the visible area. Options are similar to block: 'start', 'center', 'end', and 'nearest'.
Example:
const element = document.getElementById('myElement'); // Replace 'myElement' with the ID of your element element.scrollIntoView({ behavior: 'smooth', block: 'center' });
Use code with caution.
This code snippet will smoothly scroll the element with the ID "myElement" to the center of the viewport.
Other methods:
- window.scrollTo(x, y): Scrolls the window to a specific set of coordinates.
- window.scrollBy(x, y): Scrolls the document by a specified number of pixels relative to its current position.
Note: While window.scrollTo() and window.scrollBy() can be used to scroll to an element, scrollIntoView() is generally preferred as it is specifically designed for scrolling an element into view, and it handles the ancestor containers automatically.
Question Three
Input
Please show me a JavaScript snippet that would scroll the first non-pinned post on Mastodon web page into view.
Output
Disclaimer: Directly manipulating the HTML structure of a website you don't own (like the Mastodon web interface) can be unreliable due to potential changes in the website's design. This script relies on the current HTML structure of Mastodon, which may change in future updates. However, this JavaScript snippet demonstrates a general approach to finding and scrolling an element based on its position after certain elements (like pinned posts).
// Find the pinned posts container (assuming it exists and has a specific class) // Replace '.timeline-pinned-posts' with the actual class name const pinnedPostsContainer = document.querySelector('.timeline-pinned-posts'); if (pinnedPostsContainer) { // Find the parent element that contains both pinned and non-pinned posts const timelineContainer = pinnedPostsContainer.parentElement; if (timelineContainer) { // Get all the posts within the timeline container // Replace '.status' with the class name for individual posts const allPosts = timelineContainer.querySelectorAll('.status'); // Find the first non-pinned post let firstNonPinnedPost = null; let foundPinned = false; for (const post of allPosts) { if (post.closest('.timeline-pinned-posts')) { // This is a pinned post, continue searching foundPinned = true; } else if (foundPinned) { // This is the first post after the pinned posts firstNonPinnedPost = post; break; // Stop searching once the first non-pinned post is found } } // Scroll the first non-pinned post into view if (firstNonPinnedPost) { firstNonPinnedPost.scrollIntoView({ behavior: 'smooth', block: 'start' }); } } }
Use code with caution.
The following explains the JavaScript code:
- The code attempts to locate the HTML element containing pinned posts using pinnedPostsContainer. To find the correct CSS class for this element, inspect the Mastodon web page's source code.
- The code then identifies the parent element of pinnedPostsContainer, which also contains non-pinned posts.
- The code gathers all post elements within the timelineContainer. Again, the correct CSS class for individual posts on the Mastodon web page needs to be found.
- The code iterates through the posts to find the first one that isn't within the pinnedPostsContainer.
- The closest() method determines if a post is within the pinnedPostsContainer.
- The foundPinned flag identifies when the pinned posts have been passed.
- Once the firstNonPinnedPost is found, scrollIntoView() scrolls it into the viewport. The animation is controlled by behavior: 'smooth', and block: 'start' aligns the element's top with the viewport's top.
To use the code:
- Use your browser's developer tools to inspect the HTML structure of the Mastodon timeline to find the correct CSS classes for the container element for pinned posts, and individual post elements.
- Replace the placeholder class names with the actual class names found.
- Include this JavaScript code on the Mastodon page using a browser extension (like Tampermonkey) or a custom script if you are embedding a Mastodon timeline on your own website.
Important points:
- Changes to Mastodon's HTML structure could break this script.
- If there are many posts, iterating through all of them might affect performance. Optimization can be done by looking for the pinned posts container and then selecting the next sibling element that represents a post.
- Add error handling to handle cases where the required elements are not found.
- Consider whether automatically scrolling is a desired behavior. Providing a button or link that triggers the scroll action might be better.
Question Four
Input
Mastodon uses a <div/> with attributes like role="feed" and class="item-list" And, that <div/> contains <article/> elements. Please show me JavaScript to scroll the first <article/> tag into view.
Output
Yes, using the scrollIntoView() method is the right approach here.
Assuming you're talking about the Mastodon web interface's main timeline feed, where posts are presented as <article> elements within a container div having role="feed" and class="item-list", here's how you can scroll the first <article> tag within that container into view:
// Find the feed container div const feedContainer = document.querySelector('div[role="feed"].item-list'); if (feedContainer) { // Find the first article tag within the feed container const firstArticle = feedContainer.querySelector('article'); if (firstArticle) { // Scroll the first article into view firstArticle.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }
Use code with caution.
The following explains the code:
- document.querySelector('div[role="feed"].item-list'): This code uses querySelector to find a specific div element.
- div[role="feed"]: Selects a div element with the role attribute set to "feed".
- .item-list: Selects an element with the class "item-list".
- This combination ensures the correct container element is targeted.
- feedContainer.querySelector('article'): After the feedContainer is found, this code uses querySelector again on the feedContainer element to find the first descendant <article> element.
- firstArticle.scrollIntoView({ behavior: 'smooth', block: 'start' }):
- scrollIntoView(): This method scrolls the firstArticle element into the visible area of its ancestor containers.
- { behavior: 'smooth', block: 'start' }: These options customize scrolling behavior:
- behavior: 'smooth': Makes scrolling animate smoothly.
- block: 'start': Aligns the top of the element (firstArticle) with the top of the visible area of the scrollable container.
How to use:
- Browser Developer Console: Paste the JavaScript code directly into a browser's developer console on a Mastodon page.
- Browser Extension: Use a browser extension like Tampermonkey or Greasemonkey to inject this script automatically.
- Custom Embedding: Integrate this script into your website's JavaScript to control the scrolling if you're building a website that embeds Mastodon content.
Important Note:
This script assumes the Mastodon web interface's timeline's specific HTML structure (div with role="feed" and class="item-list" containing <article> tags). If Mastodon's HTML structure changes, this script may need adjustments.
Question Five
Input
I have a basic question. Why should I use `const` for the initial variable?
Output
In JavaScript, you should generally use const for variables whose values are not expected to change, and let for variables whose values might be reassigned later in the code. var should be avoided in modern JavaScript development due to its scope issues and potential for unexpected behavior.
Here's why const is the preferred initial variable declaration in many cases:
Readability and Intent:
- Using const makes it clear to anyone reading your code (including your future self) that the value of the variable is not intended to be changed.
- This improves code readability and makes it easier to understand the purpose of the variable.
Prevents Accidental Reassignment:
- const helps prevent accidental reassignments, which can be a source of bugs, especially in larger codebases or when multiple developers are working on the same project.
- If you attempt to reassign a const variable, JavaScript will throw a TypeError, alerting you to the issue.
Optimizations:
- While JavaScript engines can sometimes optimize code declared with let, const provides a stronger hint to the engine that the variable's value will not change.
- This can potentially lead to minor performance optimizations, though this is not the primary reason for using const.
Block Scoping:
- Like let, const is block-scoped, meaning the variable is only accessible within the block (e.g., loops, conditionals) where it is declared.
- This helps prevent unintended variable leakage and promotes cleaner code.
In summary, using const by default offers several benefits for writing clean, readable, and maintainable JavaScript code:
- It makes your intentions clear to others (and yourself).
- It helps prevent accidental errors through reassignment.
- It promotes better code structure with block scoping.
Remember: const prevents the reassignment of a variable's binding, but it does not make the value itself immutable. If the variable holds an object or array, its properties or elements can still be modified. If you want to ensure the contents of an object are immutable, you can use Object.freeze().
References
querySelector() Method | W3Schools
CSS Selectors Reference | W3Schools
CSS Selectors Tutorial | W3Schools
Created: Monday, June 16, 2025
Updated: Monday, June 16, 2025
/gemlog/