Hidden beauty

Sådan flytter du ankerpunkter ned under en sticky header med CSS

Vi er blevet vant til sticky headers, der bliver hængende i toppen af browseren, når vi scroller ned. Det er godt for den hurtige navigation tilbage eller videre. Men sticky headers er et problem for ankerpunkter – altså interne links på den samme sider, der linker til et ID som fx #kapitel33.

Der findes masser af beskidte kneb med at tilføje ekstra plads over dem, men det giver tom plads. Fint nok til en overskrift, men ubrugeligt til fx et tilbage til en fodnote-reference. Ingen ekstra linjeplads over tilfældigt udvalgte linjer, tak.

Det kan også gøres med javascript – men vi har ikke brug for flere scripts, når det kan klares med et par simple definitioner i stylesheets.

Men lad mig med denne artikel give dig tre css-tricks, der løser de væsentligste problemer med ankerpunkter:

  • scroll-margin-top lægger ekstra plads over
  • :target, der udvælger målet
  • scroll-behavior, der giver dig valg mellem spring eller blød scroll

Værsågod, kast dig ud i det. Eller læs videre og få det forklaret med eksempler.

En klasse over dem alle :target

En af udfordringerne ved at håndtere interne links er, at få dem alle med i CSS-definitionen.

Tidligere har vi enten måtte nøjes med at tildele plads til overskrifter og så angivet en style med

h1, h2, h3, h4, h5, h6{margin-top: 50px}

Men det er jo ikke altid, at man vil scrolle til en overskrift. Hvis man fx har indhold med fodnoter i WordPress, så duer den løsning ikke. Her er for eksempel et link i et ord i et almindeligt afsnit, der skal linke til en tekst nederst på siden[1].

Derfor duer den løsning ikke.

Men det gør heller ikke noget, for vi har en bedre løsning: vi kan definere samtlige mål for et link med en selector: “:target”. Du får lige først lidt baggrund.

Hvad er selectors?

Selectors er i CSS mønstre vi bruger til at udvælge de elementer, der skal påvirkes af en stil.

Det er fra det helt simple .class og #id til de mere avancerede :first-of-type eller :nth-last-child(n). Og så altså vores :target. Der er mange muligheder, så kig på dem med mellemrum og bliv lidt klogere undervejs. Det burde faktisk aldrig være nødvendigt at overstyre med !important.

Normalt vil man bruge :target med en class eller id foran, fordi man ønsker at udvælge et bestemt element. Men da den selector godt kan stå alene, så kan vi med :target udvælge “alle mål for en ankertekst”. Altså alle de elementer, der henvises til fra et link på den samme side.

Og lige for en ordens skyld, så fungerer det også selvom vi linker fra en anden side til noget inde i teksten, fordi linket først sender os til selve siden – derefter ned på den samme side.

Så første del af vores CSS bliver altså

:target{}

Ekstra plads over målet

Plads over – det er jo bare margin-top:100px?

Ja, men det duer jo ikke, når det fx er en fodnote midt i en tekst.

Men så giver vi teksten ekstra højde og skjuler den igen med negativ margin?

God ide, men det duer bare ikke i praksis. For teksten ovenover bliver skjult under den negative margin, så hvis der er et link, kan man ikke klikke på det. Upraktisk.

Og ja, man kan gøre alle mulige ting og ende med fx det her:

/** old solution - don't use this! **/
body:not(.elementor-editor-active) /* for not messsing up elementor editor */
*[id]:before {
    content: "";
    display:block;
    height: 150px; /* fixed header height*/
    margin: -150px 0 0; /* negative fixed header height */
    visibility: hidden;
    pointer-events: none;
    z-index: -1; /* This prevents any links being behind the offset block and un-clickable */
}

Så er der taget højde for næsten alting – men det virker bare ikke altid. Og det er noget værre rod!

For der findes faktisk en funktion til lige præcis den her situation: scroll-margin.

Den parameter er en del af Scroll Snapping, der bestemmer, hvad der sker når man scroller ned ved fx at klikke på scrollbar-en.

Men fidusen er, at det ikke tilføjer noget som helst til teksten. Og kun påvirker scrolling og altså ideelt til vores behov her.

Så nu har vi en brugbar løsning:

:target{   scroll-margin-top: 150px; }

Margin skal selvfølgelig tilpasses efter hvor høj, din menu er.

Det er meget mere elegant og virker i alle situationer.

Blød landing

Standard for scrolling er, at det sker øjeblikket, når du klikker på linket. Men det virker meget brat og er ubehageligt, da øjet ikke kan følge med.

Det er langt bedre med bevægelse, der kan ses ske. I praksis handler det om at lave en bevægelse med både ease-in og ease-out. Det vil sige blød start og blød landing.

Heldigvis er det ikke spor svært, for der er en CSS funktion til det: scroll-behaviour

Det betyder, at vi ender med

:target{   scroll-margin-top: 150px; } 
html{ scroll-behaviour: smooth; }

Læs mere om disse begreber i W3C definitionerne:
https://drafts.csswg.org/css-scroll-snap-1/#scroll-margin
https://www.w3.org/Style/Examples/007/target.en.html#target
https://www.w3.org/TR/cssom-view/#smooth-scrolling

[1] Her er teksten, fodnotereferencen henviser til. Og 1-tallet linker tilbage til det afsnit du kom fra. Og det her er jo heller ikke en overskrift.

Bliv lidt klogere med Pro tips om WordPress

Bare rolig – vi siger det ikke til nogen!

Indhold

Pssttt - har jeg ikke set dig her før? 😉

Få en mail hver gang der er nye tips og tricks – så behøver du ikke selv holde øje med om der er nyt!

Bare rolig. Vi hverken spammer dig eller giver dine informationer videre til tredjepart.