Question

How to prevent a # href scroll down to a section/id of the page, but still use :target to do other things

I'm new to HTML/CSS/SCSS, but I'm trying to create a single page, that looks like it's changing pages, but really is just using display: none, and display: block.

I got this working with the following code:

// Hide all sections by default
section {
  display: none;
}

// Initially display nav, hero, footer, portfolio, contact sections
#nav-section,
#hero-section,
#footer-section,
#portfolio-section,
#contact-section {
  display: block;
}

// Show about, coding, or scs sections when targeted
#about-section:target,
#coding-section:target,
#scs-section:target {
  display: block;
}

// Hide portfolio and contact when about, coding, or scs are targeted
#about-section:target ~ #portfolio-section,
#about-section:target ~ #contact-section,
#coding-section:target ~ #portfolio-section,
#coding-section:target ~ #contact-section,
#scs-section:target ~ #portfolio-section,
#scs-section:target ~ #contact-section {
  display: none;
}

// Show portfolio and contact when either is targeted
#portfolio-section:target,
#contact-section:target,
#portfolio-section:target ~ #contact-section,
#contact-section:target ~ #portfolio-section {
  display: block;
}

// Ensure other sections are hidden when portfolio or contact is targeted
#portfolio-section:target ~ #about-section,
#portfolio-section:target ~ #coding-section,
#portfolio-section:target ~ #scs-section,
#contact-section:target ~ #about-section,
#contact-section:target ~ #coding-section,
#contact-section:target ~ #scs-section {
  display: none;
}
<p><a href="#about-section">About Me</a></p>
<p><a href="#portfolio-section">My Portfolio</a></p>
<p><a href="#coding-section">Coding Examples</a></p>
<p><a href="#scs-section">SCS Scheme</a></p>
<p><a href="#contact-section">Contact Me</a></p>

Everything is working fine, but obviously it still click goes down to that part of the page. Note I have a big hero image.

Is there anyway to solve this without JavaScript? I'm trying to see if it's possible in HTML/CSS/SCSS alone.

I did try and change the nav links to non-relating IDs, like #coding-section to #coding and updating the SCSS from:

#coding-section:target \~ #portfolio-section,

to

#coding:target \~ #portfolio-section,

but that did not work for me.

 3  52  3
1 Jan 1970

Solution

 2

You can do this with JavaScript as explained in this question: Prevent browser from scrolling to element when hash is present in URL but keep it in the URL.

To do it without JavaScript, you can offset the scroll target position of the element using the scroll-margin (specifically scroll-margin-top). You can set this value so that the browser scrolls to the top of the page. To pick a value you can either use JS to calculate the height of all the content above the sections or set a fixed value that is larger than that content would ever be (e.g. 500vh).

This will still cause scrolling, but now the browser will scroll to the top of the page. Depending on your layout and needs setting a different value for the scroll-margin might work better.

section {
    scroll-margin-top: 100vh;
}
<h1>My Website</h1>

<div>
    <a href="#one">One</a>
    <a href="#two">Two</a>
    <a href="#three">Three</a>
</div>

<section id="one">
    One
</section>
<section id="two">
    Two
</section>
<section id="three">
    Three
</section>

<div style="height: 200vh;"></div>

2024-07-11
Henry Woody