<div style="height: 200vh;">Крути вниз!</div>
<button class="scroll-to-top-button" onclick="window.scrollTo(0, 0);">▲</button>
<script>
addEventListener("scroll", () => {
document.documentElement.classList.toggle("scroll-to-top-button-is-visible", scrollY > 0.5 * innerHeight)
}, { passive: true });
</script>
<style>
html {
scroll-behavior: smooth;
}
.scroll-to-top-button {
font-size: 300%;
border: none;
outline: none;
width: 1.5em;
height: 1.5em;
background: #345;
position: fixed;
right: .2em;
bottom: .2em;
border-radius: .2em;
line-height: 0;
color: white;
opacity: 0;
pointer-events: none;
transition: 300ms opacity;
}
.scroll-to-top-button-is-visible .scroll-to-top-button {
opacity: 1;
pointer-events: all;
}
</style>
UPD В данном случае outline: none; не ломает доступность, поскольку переместиться в начало страницы при помощи клавиатуры можно нажав клавишу Home, а на сенсорном экране обратной связью об удачном нажатии кнопки будет само перемещение в начало страницы.