What the markup marks for you

Skinning — part 5 of 9

A stylesheet can only style what it can select. Each of these was one run of text, or one element among identical ones, until a skin needed to tell the parts apart -- so each is marked. Most look exactly as they did until a rule of yours says otherwise; the page dates and the count are new words on the page, and site.css styles those two.

The parts of the series sentence. "Nový Sean.cz — part 3 of 19" is three spans: .series-note__name, .series-note__sep and .series-note__part. On the series' own listing every card repeats the name the heading has just said:

.listing-heading--series ~ .post-list-item .series-note__name,
.listing-heading--series ~ .post-list-item .series-note__sep { display: none; }

The joiner is a span of its own so that hiding the name does not leave a dash opening the line.

The year of an archive page. Its heading says a kind and a value, as a tag's and a series' do: .listing-heading__kind is the word "Archive", .listing-heading__value is the year, and the year alone is the link back to the map of years. Whatever sets the value apart on .listing-heading--tag now works on .listing-heading--archive too.

A listing's own tag. On /tag/hills/ every card has "hills" among its pills. That pill is .tag-pill.tag-pill-own there, and an ordinary .tag-pill on every other page:

.tag-pill-own { opacity: 0.5; }

A count of nothing. The three numbers under a post -- favourites, boosts, replies -- are .post-stat; one that is zero is .post-stat.post-stat--zero as well. The zero is still written, so the row keeps its three places; whether it is worth reading is yours to say:

.post-stat--zero { visibility: hidden; }

The numbers are filled in by a script after the page loads, so this is a class you will not find by reading the built HTML.

A mention and a hashtag in a post's text. A link whose whole text is "@somebody" or "#something" is a.mention, a hashtag a.mention.hashtag as well -- the classes Mastodon's own markup gives them, which is what the comments under a post and the toots in the sidebar already carry. One rule now reaches all three:

a.mention { text-decoration: none; }

The author among the replies. A reply from the account that announced the post is .comment.comment--author. The script tells it by the address of the announcement, so it works for a live thread, a moderated one and a Bluesky one alike.

An answer to a comment. A reply that answers another reply, rather than the post, is .comment.comment--reply, and site.css sets it in by the width of a picture (margin-left, less below 700px). One step whatever the depth: the list is in thread order, so an answer already stands under what it answers. To have the thread flat again, set the margin to zero.

The search's count and its matches. The status over the results is <span class="search-count">4</span> <span class="search-unit">results</span>, so a skin can keep the number and drop the word. In a result's title and excerpt the words that were asked for are <mark>; site.css gives it the pills' ground instead of the browser's yellow (.search-result mark).

The days a page covers. Under a listing, the label between the two links is page 12 -- the word in .pagination-word, the number in .pagination-number -- followed by .pagination-sep (the dot) and .pagination-dates; on the page the numbering starts from, .pagination-start stands where the link to older posts would. site.css hides the dot and puts the dates on a line of their own under the number; to have them on one line, show the dot and make the dates inline -- and then look at it on a phone, where two links and a range across a new year do not fit beside each other.

How many a listing holds. The number after a heading's name is <sup class="listing-heading__count"> -- on the first page of a tag's or a type's listing, on every page of a series, on an archive year and on the map of years, and on the two lists of lists: /tag/ (how many tags) and /series/ (how many series). It is not on /page/N/ of a tag, so do not build a layout that needs it there -- and a skin that hides it has those two pages to hide it on as well.

The archive's cells, three times. A month is .archive-month with one of .is-l1 to .is-l4 or .is-empty, and it is drawn in three places from the same markup: the map on /archive/, the legend that is the map's last row (<li class="archive-legend">, its two words .archive-legend__word), and the row at the top of a year (<p class="archive-jump">, its label .archive-jump__label). Repaint .archive-month.is-l3 and all three follow; that is the point of sharing it. The legend's cells are empty and are not links.

The row of letters on the tag index. <p class="tag-index-jump"> holds a label, .tag-index-jump__label, and a link per letter. The switch hides it with the hidden attribute while the list is in count order, so if your skin gives the row a display, keep .tag-index-jump[hidden] { display: none; } after it -- site.css has to say the same thing for the same reason.

The index of series. /series/ is <ul class="series-index"> with a <li class="series-index-item"> per series: the name (a.series-index-name), the number of parts (sup.series-index-count) and the years (span.series-index-years). Its heading is .listing-heading--series-index.

The ways on from the 404 page. Under its sentence the page has a search field and a row of pills. Both are things you have styled already, with a class added: the field is the bar's <form class="search-form"> and is also .not-found-search; the pills are a post's tag pills, in <div class="tags not-found-links">, each .tag-pill.not-found-link and one of --back, --archive, --year, --tags. So a skin gets them dressed without a rule -- and usually wants two anyway, because a 404 that centres its sentence will want these centred with it:

.not-found-search { margin-inline: auto; }
.not-found-links  { text-align: center; }

site.css gives the field a border (the bar's field has none: it is a light patch on a coloured strip) and makes the input fill its form with main .not-found-search input -- one step heavier than the bar's rule on purpose, so the width your skin gave the field in the bar does not shrink this one. A year's pill carries hidden until the page's script shows it; if you give .not-found-link a display, keep .not-found-link[hidden] { display: none; } after it.

A result on the cheat sheet. On /markdown/ what a source becomes stands in <div class="md-example">, right under the <pre> that shows the source. Without a rule it is invisible, which is the default look:

.md-example { border-left: 2px solid var(--accent); padding-left: 1rem; }