@astrojs/starlight
Version:
Build beautiful, high-performance documentation websites with Astro
132 lines (114 loc) • 4.71 kB
CSS
/*
How does anchor link placement work?
Because anchor links need to placed inline at the end of a heading, but are not children of the
heading element itself, positioning them to behave in a desirable way is a tiny bit tricky. Here’s
how we do it.
1. We wrap the heading and anchor link in a div and make the heading element inline:
<div class="sl-heading-wrapper">
<h2>...</h2><a class="sl-anchor-link">...</a>
</a>
2. We need to avoid the anchor link wrapping onto a new line by itself like this because it looks
broken:
Some heading text
⛓
3. To achieve this we add an area of padding to the end of the heading and move the link over this
padding using negative margin:
padding-inline-end creates space at the end of the line
↓
Some heading text[ ]⛓
margin-inline-start then pulls the anchor link into that space
↓
Some heading text[ ⛓ ]
This ensures that when the anchor link wraps, the final word in the heading will wrap with it.
*/
@layer starlight.content {
/* ======================================================
WRAPPER
====================================================== */
.sl-markdown-content .sl-heading-wrapper {
/* The size of the SVG icon. */
--sl-anchor-icon-size: 0.8275em;
/* The horizontal space between the SVG icon and the end of the heading text. */
--sl-anchor-icon-gap: 0.25em;
/* The end of line space required to accommodate the anchor link. */
--sl-anchor-icon-space: calc(var(--sl-anchor-icon-size) + var(--sl-anchor-icon-gap));
line-height: var(--sl-line-height-headings);
}
/* We need to apply the same rule we use for heading spacing to the parent wrapper. */
.sl-markdown-content
:not(h1, h2, h3, h4, h5, h6, .sl-heading-wrapper)
+ :is(.sl-heading-wrapper) {
margin-top: 1.5em;
}
/* These font sizes are set in `markdown.css` for heading elements, but we need them one level higher on the wrapper. */
.sl-markdown-content .sl-heading-wrapper.level-h1 {
font-size: var(--sl-text-h1);
}
.sl-markdown-content .sl-heading-wrapper.level-h2 {
font-size: var(--sl-text-h2);
}
.sl-markdown-content .sl-heading-wrapper.level-h3 {
font-size: var(--sl-text-h3);
}
.sl-markdown-content .sl-heading-wrapper.level-h4 {
font-size: var(--sl-text-h4);
}
.sl-markdown-content .sl-heading-wrapper.level-h5 {
font-size: var(--sl-text-h5);
}
.sl-markdown-content .sl-heading-wrapper.level-h6 {
font-size: var(--sl-text-h6);
}
/* ======================================================
HEADING
====================================================== */
.sl-markdown-content .sl-heading-wrapper > :first-child {
display: inline;
/* Apply end-of-line padding to the heading element. */
padding-inline-end: var(--sl-anchor-icon-space);
}
/* ======================================================
LINK
====================================================== */
.sl-markdown-content .sl-anchor-link {
position: relative;
/* Move the anchor link over the heading element’s end-of-line padding. */
margin-inline-start: calc(-1 * var(--sl-anchor-icon-size));
/* Prevent double or triple clicks from potentially selecting the anchor link a11y text. */
-webkit-user-select: none;
user-select: none;
/* Prevent double clicks on the last word (or single word) of a heading to include an extra new
line in Chrome and Safari. */
display: inline-flex;
}
/* Increase clickable area for anchor links with a pseudo element that doesn’t impact layout. */
.sl-markdown-content .sl-anchor-link::after {
content: '';
position: absolute;
/* While most icon spacing is done with `em` to be relative to the heading font-size, increasing
the touch area is most important for smaller headings like h5/h6, so we use absolute units,
which have a diminishing impact at larger font-sizes. */
inset: -0.25rem -0.5rem;
}
/* Size and position the SVG icon inside the link. */
.sl-markdown-content .sl-anchor-icon > svg {
display: inline;
width: var(--sl-anchor-icon-size);
/* Center the link icon SVG vertically in the line. */
vertical-align: top;
transform: translateY(
calc((var(--sl-line-height-headings) * 1em - var(--sl-anchor-icon-size)) / 2)
);
}
/* On devices with hover capability, hide the anchor link icons and show only show them when focused
or when the heading is hovered. */
@media (hover: hover) {
.sl-markdown-content .sl-anchor-link {
opacity: 0;
}
.sl-markdown-content .sl-anchor-link:focus,
.sl-markdown-content .sl-heading-wrapper:hover .sl-anchor-link {
opacity: 1;
}
}
}